SEQ.CPP 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /*******************************************************************************
  2. FILE: SEQ.CPP
  3. DESCRIPTION: Sequence engine
  4. AUTHOR: Peter M. Freese
  5. CREATED: 06-23-95
  6. COPYRIGHT: Copyright (c) 1995 Q Studios Corporation
  7. *******************************************************************************/
  8. #include <string.h>
  9. #include "seq.h"
  10. #include "db.h"
  11. #include "debug4g.h"
  12. #include "globals.h"
  13. #include "tile.h"
  14. #include "error.h"
  15. #include "actor.h"
  16. #include "sfx.h"
  17. #define kMaxSequences 1024
  18. struct ACTIVE
  19. {
  20. uchar type;
  21. ushort index;
  22. };
  23. struct SEQINST
  24. {
  25. RESHANDLE hSeq;
  26. Seq *pSequence;
  27. SEQCALLBACK callback;
  28. short timeCounter; // age of current frame in ticks
  29. uchar frameIndex; // current frame
  30. BOOL isPlaying;
  31. void Update( ACTIVE *active );
  32. };
  33. SEQINST siWall[kMaxXWalls], siMasked[kMaxXWalls];
  34. SEQINST siCeiling[kMaxXSectors], siFloor[kMaxXSectors];
  35. SEQINST siSprite[kMaxXSprites];
  36. ACTIVE activeList[kMaxSequences];
  37. static int activeCount = 0;
  38. void Seq::Preload( void )
  39. {
  40. if ( memcmp(signature, kSEQSig, sizeof(signature)) != 0 )
  41. ThrowError("Invalid sequence", ES_ERROR);
  42. if ( (version & 0xFF00) != (kSEQVersion & 0xFF00) )
  43. ThrowError("Obsolete sequence version", ES_ERROR);
  44. for (int i = 0; i < nFrames; i++)
  45. tilePreloadTile(frame[i].nTile);
  46. }
  47. static void UpdateSprite( int nXSprite, SEQFRAME *pFrame )
  48. {
  49. dassert(nXSprite > 0 && nXSprite < kMaxXSprites);
  50. int nSprite = xsprite[nXSprite].reference;
  51. dassert(nSprite >= 0 && nSprite < kMaxSprites);
  52. SPRITE *pSprite = &sprite[nSprite];
  53. dassert(pSprite->extra == nXSprite);
  54. // set the motion bit if the vertical size or position of the sprite changes
  55. if ( (pSprite->flags & kAttrGravity) &&
  56. ( tilesizy[pSprite->picnum] != tilesizy[pFrame->nTile] ||
  57. picanm[pSprite->picnum].ycenter != picanm[pFrame->nTile].ycenter ||
  58. pFrame->yrepeat && pFrame->yrepeat != pSprite->yrepeat) )
  59. pSprite->flags |= kAttrFalling;
  60. pSprite->picnum = (short)pFrame->nTile;
  61. pSprite->pal = (char)pFrame->pal;
  62. // if (pFrame->shadeRelative)
  63. // pSprite->shade += (char)pFrame->shade;
  64. // else
  65. pSprite->shade = (char)pFrame->shade;
  66. if (pFrame->xrepeat)
  67. pSprite->xrepeat = (uchar)pFrame->xrepeat;
  68. if (pFrame->yrepeat)
  69. pSprite->yrepeat = (uchar)pFrame->yrepeat;
  70. if ( pFrame->translucent )
  71. pSprite->cstat |= kSpriteTranslucent;
  72. else
  73. pSprite->cstat &= ~kSpriteTranslucent;
  74. if ( pFrame->translucentR )
  75. pSprite->cstat |= kSpriteTranslucentR;
  76. else
  77. pSprite->cstat &= ~kSpriteTranslucentR;
  78. if ( pFrame->blocking )
  79. pSprite->cstat |= kSpriteBlocking;
  80. else
  81. pSprite->cstat &= ~kSpriteBlocking;
  82. if ( pFrame->hitscan )
  83. pSprite->cstat |= kSpriteHitscan;
  84. else
  85. pSprite->cstat &= ~kSpriteHitscan;
  86. if ( pFrame->smoke )
  87. pSprite->flags |= kAttrSmoke;
  88. else
  89. pSprite->flags &= ~kAttrSmoke;
  90. }
  91. static void UpdateWall( int nXWall, SEQFRAME *pFrame )
  92. {
  93. dassert(nXWall > 0 && nXWall < kMaxXWalls);
  94. int nWall = xwall[nXWall].reference;
  95. dassert(nWall >= 0 && nWall < kMaxWalls);
  96. WALL *pWall = &wall[nWall];
  97. dassert(pWall->extra == nXWall);
  98. pWall->picnum = (short)pFrame->nTile;
  99. // pWall->shade = (char)pFrame->shade;
  100. pWall->pal = (char)pFrame->pal;
  101. if ( pFrame->translucent )
  102. pWall->cstat |= kWallTranslucent;
  103. else
  104. pWall->cstat &= ~kWallTranslucent;
  105. if ( pFrame->translucentR )
  106. pWall->cstat |= kWallTranslucentR;
  107. else
  108. pWall->cstat &= ~kWallTranslucentR;
  109. if ( pFrame->blocking )
  110. pWall->cstat |= kWallBlocking;
  111. else
  112. pWall->cstat &= ~kWallBlocking;
  113. if ( pFrame->hitscan )
  114. pWall->cstat |= kWallHitscan;
  115. else
  116. pWall->cstat &= ~kWallHitscan;
  117. }
  118. static void UpdateMasked( int nXWall, SEQFRAME *pFrame )
  119. {
  120. dassert(nXWall > 0 && nXWall < kMaxXWalls);
  121. int nWall = xwall[nXWall].reference;
  122. dassert(nWall >= 0 && nWall < kMaxWalls);
  123. WALL *pWall = &wall[nWall];
  124. dassert(pWall->extra == nXWall);
  125. dassert(pWall->nextwall >= 0); // it must be a 2 sided wall
  126. WALL *pWall2 = &wall[pWall->nextwall];
  127. pWall->overpicnum = pWall2->overpicnum = (short)pFrame->nTile;
  128. // pWall->shade = (char)pFrame->shade;
  129. pWall->pal = pWall2->pal = (char)pFrame->pal;
  130. if ( pFrame->translucent )
  131. {
  132. pWall->cstat |= kWallTranslucent;
  133. pWall2->cstat |= kWallTranslucent;
  134. }
  135. else
  136. {
  137. pWall->cstat &= ~kWallTranslucent;
  138. pWall2->cstat &= ~kWallTranslucent;
  139. }
  140. if ( pFrame->translucentR )
  141. {
  142. pWall->cstat |= kWallTranslucentR;
  143. pWall2->cstat |= kWallTranslucentR;
  144. }
  145. else
  146. {
  147. pWall->cstat &= ~kWallTranslucentR;
  148. pWall2->cstat &= ~kWallTranslucentR;
  149. }
  150. if ( pFrame->blocking )
  151. {
  152. pWall->cstat |= kWallBlocking;
  153. pWall2->cstat |= kWallBlocking;
  154. }
  155. else
  156. {
  157. pWall->cstat &= ~kWallBlocking;
  158. pWall2->cstat &= ~kWallBlocking;
  159. }
  160. if ( pFrame->hitscan )
  161. {
  162. pWall->cstat |= kWallHitscan;
  163. pWall2->cstat |= kWallHitscan;
  164. }
  165. else
  166. {
  167. pWall->cstat &= ~kWallHitscan;
  168. pWall2->cstat &= ~kWallHitscan;
  169. }
  170. }
  171. static void UpdateFloor( int nXSector, SEQFRAME *pFrame )
  172. {
  173. dassert(nXSector > 0 && nXSector < kMaxXSectors);
  174. int nSector = xsector[nXSector].reference;
  175. dassert(nSector >= 0 && nSector < kMaxSectors);
  176. SECTOR *pSector = &sector[nSector];
  177. dassert(pSector->extra == nXSector);
  178. pSector->floorpicnum = (short)pFrame->nTile;
  179. pSector->floorshade = (char)pFrame->shade;
  180. pSector->floorpal = (char)pFrame->pal;
  181. }
  182. static void UpdateCeiling( int nXSector, SEQFRAME *pFrame )
  183. {
  184. dassert(nXSector > 0 && nXSector < kMaxXSectors);
  185. int nSector = xsector[nXSector].reference;
  186. dassert(nSector >= 0 && nSector < kMaxSectors);
  187. SECTOR *pSector = &sector[nSector];
  188. dassert(pSector->extra == nXSector);
  189. pSector->ceilingpicnum = (short)pFrame->nTile;
  190. pSector->ceilingshade = (char)pFrame->shade;
  191. pSector->ceilingpal = (char)pFrame->pal;
  192. }
  193. void SEQINST::Update( ACTIVE * active )
  194. {
  195. dassert(frameIndex < pSequence->nFrames);
  196. switch (active->type)
  197. {
  198. case SS_WALL:
  199. UpdateWall(active->index, &pSequence->frame[frameIndex]);
  200. break;
  201. case SS_CEILING:
  202. UpdateCeiling(active->index, &pSequence->frame[frameIndex]);
  203. break;
  204. case SS_FLOOR:
  205. UpdateFloor(active->index, &pSequence->frame[frameIndex]);
  206. break;
  207. case SS_SPRITE:
  208. UpdateSprite(active->index, &pSequence->frame[frameIndex]);
  209. break;
  210. case SS_MASKED:
  211. UpdateMasked(active->index, &pSequence->frame[frameIndex]);
  212. break;
  213. }
  214. if ( pSequence->frame[frameIndex].trigger && callback != NULL )
  215. callback(active->type, active->index);
  216. }
  217. SEQINST *GetInstance( int type, int nXIndex )
  218. {
  219. switch ( type )
  220. {
  221. case SS_WALL:
  222. dassert(nXIndex > 0 && nXIndex < kMaxXWalls);
  223. return &siWall[nXIndex];
  224. case SS_CEILING:
  225. dassert(nXIndex > 0 && nXIndex < kMaxXSectors);
  226. return &siCeiling[nXIndex];
  227. case SS_FLOOR:
  228. dassert(nXIndex > 0 && nXIndex < kMaxXSectors);
  229. return &siFloor[nXIndex];
  230. case SS_SPRITE:
  231. dassert(nXIndex > 0 && nXIndex < kMaxXSprites);
  232. return &siSprite[nXIndex];
  233. case SS_MASKED:
  234. dassert(nXIndex > 0 && nXIndex < kMaxXWalls);
  235. return &siMasked[nXIndex];
  236. }
  237. ThrowError("Unexcepted object type", ES_ERROR);
  238. return NULL;
  239. }
  240. void UnlockInstance( SEQINST *pInst )
  241. {
  242. dassert( pInst != NULL );
  243. dassert( pInst->hSeq != NULL );
  244. dassert( pInst->pSequence != NULL );
  245. gSysRes.Unlock( pInst->hSeq );
  246. pInst->hSeq = NULL;
  247. pInst->pSequence = NULL;
  248. pInst->isPlaying = FALSE;
  249. }
  250. void seqSpawn( int nSeqID, int type, int nXIndex, SEQCALLBACK callback )
  251. {
  252. SEQINST *pInst = GetInstance(type, nXIndex);
  253. RESHANDLE hSeq = gSysRes.Lookup(nSeqID, ".SEQ");
  254. dassert( hSeq != NULL);
  255. int i = activeCount;
  256. if ( pInst->isPlaying )
  257. {
  258. // already playing this sequence?
  259. if (pInst->hSeq == hSeq)
  260. return;
  261. UnlockInstance( pInst );
  262. for (i = 0; i < activeCount; i++)
  263. {
  264. if (activeList[i].type == type && activeList[i].index == nXIndex)
  265. break;
  266. }
  267. dassert(i < activeCount); // should have been found
  268. }
  269. Seq *pSequence = (Seq *)gSysRes.Lock(hSeq);
  270. if ( memcmp(pSequence->signature, kSEQSig, sizeof(pSequence->signature)) != 0 )
  271. ThrowError("Invalid sequence", ES_ERROR);
  272. if ( (pSequence->version & 0xFF00) != (kSEQVersion & 0xFF00) )
  273. ThrowError("Obsolete sequence version", ES_ERROR);
  274. pInst->hSeq = hSeq;
  275. pInst->pSequence = pSequence;
  276. pInst->callback = callback;
  277. pInst->isPlaying = TRUE;
  278. pInst->timeCounter = pSequence->ticksPerFrame;
  279. pInst->frameIndex = 0;
  280. if (i == activeCount)
  281. {
  282. dassert(activeCount < kMaxSequences);
  283. activeList[activeCount].type = (uchar)type;
  284. activeList[activeCount].index = (short)nXIndex;
  285. activeCount++;
  286. }
  287. pInst->Update(&activeList[i]);
  288. }
  289. void seqKill( int type, int nXIndex )
  290. {
  291. SEQINST *pInst = GetInstance(type, nXIndex);
  292. if ( pInst->isPlaying )
  293. {
  294. for (int i = 0; i < activeCount; i++)
  295. {
  296. if (activeList[i].type == type && activeList[i].index == nXIndex)
  297. break;
  298. }
  299. dassert(i < activeCount);
  300. // remove it from the active list
  301. activeList[i] = activeList[--activeCount];
  302. pInst->isPlaying = FALSE;
  303. UnlockInstance( pInst );
  304. }
  305. }
  306. void seqKillAll( void )
  307. {
  308. int i;
  309. for (i = 0; i < kMaxXWalls; i++)
  310. {
  311. if ( siWall[i].isPlaying )
  312. UnlockInstance( &siWall[i] );
  313. if ( siMasked[i].isPlaying )
  314. UnlockInstance( &siMasked[i] );
  315. }
  316. for (i = 0; i < kMaxXSectors; i++)
  317. {
  318. if ( siCeiling[i].isPlaying )
  319. UnlockInstance( &siCeiling[i] );
  320. if ( siFloor[i].isPlaying )
  321. UnlockInstance( &siFloor[i] );
  322. }
  323. for (i = 0; i < kMaxXSprites; i++)
  324. {
  325. if ( siSprite[i].isPlaying )
  326. UnlockInstance( &siSprite[i] );
  327. }
  328. activeCount = 0;
  329. }
  330. int seqGetStatus( int type, int nXIndex )
  331. {
  332. SEQINST *pInst = GetInstance(type, nXIndex);
  333. if ( pInst->isPlaying )
  334. return pInst->frameIndex;
  335. return -1;
  336. }
  337. void seqProcess( int nTicks )
  338. {
  339. for (int i = 0; i < activeCount; i++)
  340. {
  341. SEQINST *pInst = GetInstance(activeList[i].type, activeList[i].index);
  342. Seq *pSeq = pInst->pSequence;
  343. dassert(pInst->frameIndex < pSeq->nFrames);
  344. pInst->timeCounter -= nTicks;
  345. while (pInst->timeCounter < 0)
  346. {
  347. pInst->timeCounter += pSeq->ticksPerFrame;
  348. ++pInst->frameIndex;
  349. if (pInst->frameIndex == pSeq->nFrames)
  350. {
  351. if ( pSeq->flags & kSeqLoop )
  352. pInst->frameIndex = 0;
  353. else
  354. {
  355. UnlockInstance( pInst );
  356. if ( pSeq->flags & kSeqRemove )
  357. {
  358. short nSprite, nWall, nNextWall;
  359. switch (activeList[i].type)
  360. {
  361. case SS_SPRITE:
  362. nSprite = (short)xsprite[activeList[i].index].reference;
  363. dassert(nSprite >= 0 && nSprite < kMaxSprites);
  364. deletesprite(nSprite); // safe to not use actPostSprite here
  365. break;
  366. case SS_MASKED:
  367. nWall = (short)xwall[activeList[i].index].reference;
  368. dassert(nWall >= 0 && nWall < kMaxWalls);
  369. wall[nWall].cstat &= ~kWallMasked & ~kWallFlipX & ~kWallOneWay;
  370. if ((nNextWall = wall[nWall].nextwall) != -1)
  371. wall[nNextWall].cstat &= ~kWallMasked & ~kWallFlipX & ~kWallOneWay;
  372. break;
  373. }
  374. }
  375. // remove it from the active list
  376. activeList[i--] = activeList[--activeCount];
  377. break;
  378. }
  379. }
  380. pInst->Update(&activeList[i]);
  381. }
  382. }
  383. }