123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- /*******************************************************************************
- FILE: SEQ.CPP
- DESCRIPTION: Sequence engine
- AUTHOR: Peter M. Freese
- CREATED: 06-23-95
- COPYRIGHT: Copyright (c) 1995 Q Studios Corporation
- *******************************************************************************/
- #include <string.h>
- #include "seq.h"
- #include "db.h"
- #include "debug4g.h"
- #include "globals.h"
- #include "tile.h"
- #include "error.h"
- #include "actor.h"
- #include "sfx.h"
- #define kMaxSequences 1024
- struct ACTIVE
- {
- uchar type;
- ushort index;
- };
- struct SEQINST
- {
- RESHANDLE hSeq;
- Seq *pSequence;
- SEQCALLBACK callback;
- short timeCounter; // age of current frame in ticks
- uchar frameIndex; // current frame
- BOOL isPlaying;
- void Update( ACTIVE *active );
- };
- SEQINST siWall[kMaxXWalls], siMasked[kMaxXWalls];
- SEQINST siCeiling[kMaxXSectors], siFloor[kMaxXSectors];
- SEQINST siSprite[kMaxXSprites];
- ACTIVE activeList[kMaxSequences];
- static int activeCount = 0;
- void Seq::Preload( void )
- {
- if ( memcmp(signature, kSEQSig, sizeof(signature)) != 0 )
- ThrowError("Invalid sequence", ES_ERROR);
- if ( (version & 0xFF00) != (kSEQVersion & 0xFF00) )
- ThrowError("Obsolete sequence version", ES_ERROR);
- for (int i = 0; i < nFrames; i++)
- tilePreloadTile(frame[i].nTile);
- }
- static void UpdateSprite( int nXSprite, SEQFRAME *pFrame )
- {
- dassert(nXSprite > 0 && nXSprite < kMaxXSprites);
- int nSprite = xsprite[nXSprite].reference;
- dassert(nSprite >= 0 && nSprite < kMaxSprites);
- SPRITE *pSprite = &sprite[nSprite];
- dassert(pSprite->extra == nXSprite);
- // set the motion bit if the vertical size or position of the sprite changes
- if ( (pSprite->flags & kAttrGravity) &&
- ( tilesizy[pSprite->picnum] != tilesizy[pFrame->nTile] ||
- picanm[pSprite->picnum].ycenter != picanm[pFrame->nTile].ycenter ||
- pFrame->yrepeat && pFrame->yrepeat != pSprite->yrepeat) )
- pSprite->flags |= kAttrFalling;
- pSprite->picnum = (short)pFrame->nTile;
- pSprite->pal = (char)pFrame->pal;
- // if (pFrame->shadeRelative)
- // pSprite->shade += (char)pFrame->shade;
- // else
- pSprite->shade = (char)pFrame->shade;
- if (pFrame->xrepeat)
- pSprite->xrepeat = (uchar)pFrame->xrepeat;
- if (pFrame->yrepeat)
- pSprite->yrepeat = (uchar)pFrame->yrepeat;
- if ( pFrame->translucent )
- pSprite->cstat |= kSpriteTranslucent;
- else
- pSprite->cstat &= ~kSpriteTranslucent;
- if ( pFrame->translucentR )
- pSprite->cstat |= kSpriteTranslucentR;
- else
- pSprite->cstat &= ~kSpriteTranslucentR;
- if ( pFrame->blocking )
- pSprite->cstat |= kSpriteBlocking;
- else
- pSprite->cstat &= ~kSpriteBlocking;
- if ( pFrame->hitscan )
- pSprite->cstat |= kSpriteHitscan;
- else
- pSprite->cstat &= ~kSpriteHitscan;
- if ( pFrame->smoke )
- pSprite->flags |= kAttrSmoke;
- else
- pSprite->flags &= ~kAttrSmoke;
- }
- static void UpdateWall( int nXWall, SEQFRAME *pFrame )
- {
- dassert(nXWall > 0 && nXWall < kMaxXWalls);
- int nWall = xwall[nXWall].reference;
- dassert(nWall >= 0 && nWall < kMaxWalls);
- WALL *pWall = &wall[nWall];
- dassert(pWall->extra == nXWall);
- pWall->picnum = (short)pFrame->nTile;
- // pWall->shade = (char)pFrame->shade;
- pWall->pal = (char)pFrame->pal;
- if ( pFrame->translucent )
- pWall->cstat |= kWallTranslucent;
- else
- pWall->cstat &= ~kWallTranslucent;
- if ( pFrame->translucentR )
- pWall->cstat |= kWallTranslucentR;
- else
- pWall->cstat &= ~kWallTranslucentR;
- if ( pFrame->blocking )
- pWall->cstat |= kWallBlocking;
- else
- pWall->cstat &= ~kWallBlocking;
- if ( pFrame->hitscan )
- pWall->cstat |= kWallHitscan;
- else
- pWall->cstat &= ~kWallHitscan;
- }
- static void UpdateMasked( int nXWall, SEQFRAME *pFrame )
- {
- dassert(nXWall > 0 && nXWall < kMaxXWalls);
- int nWall = xwall[nXWall].reference;
- dassert(nWall >= 0 && nWall < kMaxWalls);
- WALL *pWall = &wall[nWall];
- dassert(pWall->extra == nXWall);
- dassert(pWall->nextwall >= 0); // it must be a 2 sided wall
- WALL *pWall2 = &wall[pWall->nextwall];
- pWall->overpicnum = pWall2->overpicnum = (short)pFrame->nTile;
- // pWall->shade = (char)pFrame->shade;
- pWall->pal = pWall2->pal = (char)pFrame->pal;
- if ( pFrame->translucent )
- {
- pWall->cstat |= kWallTranslucent;
- pWall2->cstat |= kWallTranslucent;
- }
- else
- {
- pWall->cstat &= ~kWallTranslucent;
- pWall2->cstat &= ~kWallTranslucent;
- }
- if ( pFrame->translucentR )
- {
- pWall->cstat |= kWallTranslucentR;
- pWall2->cstat |= kWallTranslucentR;
- }
- else
- {
- pWall->cstat &= ~kWallTranslucentR;
- pWall2->cstat &= ~kWallTranslucentR;
- }
- if ( pFrame->blocking )
- {
- pWall->cstat |= kWallBlocking;
- pWall2->cstat |= kWallBlocking;
- }
- else
- {
- pWall->cstat &= ~kWallBlocking;
- pWall2->cstat &= ~kWallBlocking;
- }
- if ( pFrame->hitscan )
- {
- pWall->cstat |= kWallHitscan;
- pWall2->cstat |= kWallHitscan;
- }
- else
- {
- pWall->cstat &= ~kWallHitscan;
- pWall2->cstat &= ~kWallHitscan;
- }
- }
- static void UpdateFloor( int nXSector, SEQFRAME *pFrame )
- {
- dassert(nXSector > 0 && nXSector < kMaxXSectors);
- int nSector = xsector[nXSector].reference;
- dassert(nSector >= 0 && nSector < kMaxSectors);
- SECTOR *pSector = §or[nSector];
- dassert(pSector->extra == nXSector);
- pSector->floorpicnum = (short)pFrame->nTile;
- pSector->floorshade = (char)pFrame->shade;
- pSector->floorpal = (char)pFrame->pal;
- }
- static void UpdateCeiling( int nXSector, SEQFRAME *pFrame )
- {
- dassert(nXSector > 0 && nXSector < kMaxXSectors);
- int nSector = xsector[nXSector].reference;
- dassert(nSector >= 0 && nSector < kMaxSectors);
- SECTOR *pSector = §or[nSector];
- dassert(pSector->extra == nXSector);
- pSector->ceilingpicnum = (short)pFrame->nTile;
- pSector->ceilingshade = (char)pFrame->shade;
- pSector->ceilingpal = (char)pFrame->pal;
- }
- void SEQINST::Update( ACTIVE * active )
- {
- dassert(frameIndex < pSequence->nFrames);
- switch (active->type)
- {
- case SS_WALL:
- UpdateWall(active->index, &pSequence->frame[frameIndex]);
- break;
- case SS_CEILING:
- UpdateCeiling(active->index, &pSequence->frame[frameIndex]);
- break;
- case SS_FLOOR:
- UpdateFloor(active->index, &pSequence->frame[frameIndex]);
- break;
- case SS_SPRITE:
- UpdateSprite(active->index, &pSequence->frame[frameIndex]);
- break;
- case SS_MASKED:
- UpdateMasked(active->index, &pSequence->frame[frameIndex]);
- break;
- }
- if ( pSequence->frame[frameIndex].trigger && callback != NULL )
- callback(active->type, active->index);
- }
- SEQINST *GetInstance( int type, int nXIndex )
- {
- switch ( type )
- {
- case SS_WALL:
- dassert(nXIndex > 0 && nXIndex < kMaxXWalls);
- return &siWall[nXIndex];
- case SS_CEILING:
- dassert(nXIndex > 0 && nXIndex < kMaxXSectors);
- return &siCeiling[nXIndex];
- case SS_FLOOR:
- dassert(nXIndex > 0 && nXIndex < kMaxXSectors);
- return &siFloor[nXIndex];
- case SS_SPRITE:
- dassert(nXIndex > 0 && nXIndex < kMaxXSprites);
- return &siSprite[nXIndex];
- case SS_MASKED:
- dassert(nXIndex > 0 && nXIndex < kMaxXWalls);
- return &siMasked[nXIndex];
- }
- ThrowError("Unexcepted object type", ES_ERROR);
- return NULL;
- }
- void UnlockInstance( SEQINST *pInst )
- {
- dassert( pInst != NULL );
- dassert( pInst->hSeq != NULL );
- dassert( pInst->pSequence != NULL );
- gSysRes.Unlock( pInst->hSeq );
- pInst->hSeq = NULL;
- pInst->pSequence = NULL;
- pInst->isPlaying = FALSE;
- }
- void seqSpawn( int nSeqID, int type, int nXIndex, SEQCALLBACK callback )
- {
- SEQINST *pInst = GetInstance(type, nXIndex);
- RESHANDLE hSeq = gSysRes.Lookup(nSeqID, ".SEQ");
- dassert( hSeq != NULL);
- int i = activeCount;
- if ( pInst->isPlaying )
- {
- // already playing this sequence?
- if (pInst->hSeq == hSeq)
- return;
- UnlockInstance( pInst );
- for (i = 0; i < activeCount; i++)
- {
- if (activeList[i].type == type && activeList[i].index == nXIndex)
- break;
- }
- dassert(i < activeCount); // should have been found
- }
- Seq *pSequence = (Seq *)gSysRes.Lock(hSeq);
- if ( memcmp(pSequence->signature, kSEQSig, sizeof(pSequence->signature)) != 0 )
- ThrowError("Invalid sequence", ES_ERROR);
- if ( (pSequence->version & 0xFF00) != (kSEQVersion & 0xFF00) )
- ThrowError("Obsolete sequence version", ES_ERROR);
- pInst->hSeq = hSeq;
- pInst->pSequence = pSequence;
- pInst->callback = callback;
- pInst->isPlaying = TRUE;
- pInst->timeCounter = pSequence->ticksPerFrame;
- pInst->frameIndex = 0;
- if (i == activeCount)
- {
- dassert(activeCount < kMaxSequences);
- activeList[activeCount].type = (uchar)type;
- activeList[activeCount].index = (short)nXIndex;
- activeCount++;
- }
- pInst->Update(&activeList[i]);
- }
- void seqKill( int type, int nXIndex )
- {
- SEQINST *pInst = GetInstance(type, nXIndex);
- if ( pInst->isPlaying )
- {
- for (int i = 0; i < activeCount; i++)
- {
- if (activeList[i].type == type && activeList[i].index == nXIndex)
- break;
- }
- dassert(i < activeCount);
- // remove it from the active list
- activeList[i] = activeList[--activeCount];
- pInst->isPlaying = FALSE;
- UnlockInstance( pInst );
- }
- }
- void seqKillAll( void )
- {
- int i;
- for (i = 0; i < kMaxXWalls; i++)
- {
- if ( siWall[i].isPlaying )
- UnlockInstance( &siWall[i] );
- if ( siMasked[i].isPlaying )
- UnlockInstance( &siMasked[i] );
- }
- for (i = 0; i < kMaxXSectors; i++)
- {
- if ( siCeiling[i].isPlaying )
- UnlockInstance( &siCeiling[i] );
- if ( siFloor[i].isPlaying )
- UnlockInstance( &siFloor[i] );
- }
- for (i = 0; i < kMaxXSprites; i++)
- {
- if ( siSprite[i].isPlaying )
- UnlockInstance( &siSprite[i] );
- }
- activeCount = 0;
- }
- int seqGetStatus( int type, int nXIndex )
- {
- SEQINST *pInst = GetInstance(type, nXIndex);
- if ( pInst->isPlaying )
- return pInst->frameIndex;
- return -1;
- }
- void seqProcess( int nTicks )
- {
- for (int i = 0; i < activeCount; i++)
- {
- SEQINST *pInst = GetInstance(activeList[i].type, activeList[i].index);
- Seq *pSeq = pInst->pSequence;
- dassert(pInst->frameIndex < pSeq->nFrames);
- pInst->timeCounter -= nTicks;
- while (pInst->timeCounter < 0)
- {
- pInst->timeCounter += pSeq->ticksPerFrame;
- ++pInst->frameIndex;
- if (pInst->frameIndex == pSeq->nFrames)
- {
- if ( pSeq->flags & kSeqLoop )
- pInst->frameIndex = 0;
- else
- {
- UnlockInstance( pInst );
- if ( pSeq->flags & kSeqRemove )
- {
- short nSprite, nWall, nNextWall;
- switch (activeList[i].type)
- {
- case SS_SPRITE:
- nSprite = (short)xsprite[activeList[i].index].reference;
- dassert(nSprite >= 0 && nSprite < kMaxSprites);
- deletesprite(nSprite); // safe to not use actPostSprite here
- break;
- case SS_MASKED:
- nWall = (short)xwall[activeList[i].index].reference;
- dassert(nWall >= 0 && nWall < kMaxWalls);
- wall[nWall].cstat &= ~kWallMasked & ~kWallFlipX & ~kWallOneWay;
- if ((nNextWall = wall[nWall].nextwall) != -1)
- wall[nNextWall].cstat &= ~kWallMasked & ~kWallFlipX & ~kWallOneWay;
- break;
- }
- }
- // remove it from the active list
- activeList[i--] = activeList[--activeCount];
- break;
- }
- }
- pInst->Update(&activeList[i]);
- }
- }
- }
|