mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-16 01:11:44 +00:00
- Blood: cleanup and simplification of SEQ code.
* removed all the large instance arrays. None of this is really necessary, all we need is a single dynamic array with only the active sequences that can expand as needed. * added JSON serialization. With the above change this part now becomes trivial. * renamed all 'atxx' variables in this code.
This commit is contained in:
parent
4aa06ff702
commit
8bfc6d98d4
5 changed files with 685 additions and 673 deletions
|
@ -2488,10 +2488,10 @@ void actInit(bool bSaveLoad) {
|
|||
break;
|
||||
case kThingBloodChunks: {
|
||||
SEQINST *pInst = GetInstance(3, pSprite->extra);
|
||||
if (pInst && pInst->at13) {
|
||||
auto seq = getSequence(pInst->at8);
|
||||
if (pInst) {
|
||||
auto seq = getSequence(pInst->nSeqID);
|
||||
if (!seq) break;
|
||||
seqSpawn(pInst->at8, 3, pSprite->extra);
|
||||
seqSpawn(pInst->nSeqID, 3, pSprite->extra);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1460,9 +1460,9 @@ int getDispersionModifier(spritetype* pSprite, int minDisp, int maxDisp)
|
|||
int disp = 1;
|
||||
if (pSeq != nullptr)
|
||||
{
|
||||
int nFrames = pSeq->nFrames; int ticks = pSeq->at8; int shots = 0;
|
||||
int nFrames = pSeq->nFrames; int ticks = pSeq->ticksPerFrame; int shots = 0;
|
||||
for (int i = 0; i <= pSeq->nFrames; i++) {
|
||||
if (pSeq->frames[i].at5_5) shots++;
|
||||
if (pSeq->frames[i].trigger) shots++;
|
||||
}
|
||||
|
||||
disp = (((shots * 1000) / nFrames) / ticks) * 20;
|
||||
|
@ -2040,7 +2040,7 @@ bool genDudePrepare(spritetype* pSprite, int propId) {
|
|||
{
|
||||
pExtra->forcePunch = true; // required for those who don't have fire trigger in punch seq and for default animation
|
||||
for (int i = 0; i < pSeq->nFrames; i++) {
|
||||
if (!pSeq->frames[i].at5_5) continue;
|
||||
if (!pSeq->frames[i].trigger) continue;
|
||||
pExtra->forcePunch = false;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -476,14 +476,6 @@ void LoadSave::Write(const void *pData, int nSize)
|
|||
|
||||
bool GameInterface::LoadGame()
|
||||
{
|
||||
sndKillAllSounds();
|
||||
sfxKillAllSounds();
|
||||
ambKillAll();
|
||||
seqKillAll();
|
||||
if (gamestate != GS_LEVEL)
|
||||
{
|
||||
memset(xsprite, 0, sizeof(xsprite));
|
||||
}
|
||||
LoadSave::hLFile = ReadSavegameChunk("snapshot.bld");
|
||||
if (!LoadSave::hLFile.isOpen())
|
||||
return false;
|
||||
|
@ -735,7 +727,6 @@ void LevelsLoadSaveConstruct(void);
|
|||
void MessagesLoadSaveConstruct(void);
|
||||
void MirrorLoadSaveConstruct(void);
|
||||
void PlayerLoadSaveConstruct(void);
|
||||
void SeqLoadSaveConstruct(void);
|
||||
void TriggersLoadSaveConstruct(void);
|
||||
void ViewLoadSaveConstruct(void);
|
||||
void WarpLoadSaveConstruct(void);
|
||||
|
@ -754,7 +745,6 @@ void LoadSaveSetup(void)
|
|||
MessagesLoadSaveConstruct();
|
||||
MirrorLoadSaveConstruct();
|
||||
PlayerLoadSaveConstruct();
|
||||
SeqLoadSaveConstruct();
|
||||
TriggersLoadSaveConstruct();
|
||||
ViewLoadSaveConstruct();
|
||||
WarpLoadSaveConstruct();
|
||||
|
@ -765,10 +755,21 @@ void LoadSaveSetup(void)
|
|||
|
||||
|
||||
void SerializeEvents(FSerializer& arc);
|
||||
void SerializeSequences(FSerializer& arc);
|
||||
|
||||
void GameInterface::SerializeGameState(FSerializer& arc)
|
||||
{
|
||||
sndKillAllSounds();
|
||||
sfxKillAllSounds();
|
||||
ambKillAll();
|
||||
seqKillAll();
|
||||
if (gamestate != GS_LEVEL)
|
||||
{
|
||||
memset(xsprite, 0, sizeof(xsprite));
|
||||
}
|
||||
|
||||
SerializeEvents(arc);
|
||||
SerializeSequences(arc);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 Nuke.YKT
|
||||
Copyright (C) 2020 - Christoph Oelckers
|
||||
|
||||
This file is part of NBlood.
|
||||
This file is part of Raze
|
||||
|
||||
NBlood is free software; you can redistribute it and/or
|
||||
Raze is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
|
@ -20,9 +21,11 @@ along with this program; if not, write to the Free Software
|
|||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h" // Must come before everything else!
|
||||
|
||||
#include <string.h>
|
||||
#include "ns.h"
|
||||
#include "filesystem.h"
|
||||
#include "tarray.h"
|
||||
|
||||
#include "build.h"
|
||||
#include "common_game.h"
|
||||
|
||||
|
@ -38,7 +41,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "actor.h"
|
||||
#include "view.h"
|
||||
#include "raze_sound.h"
|
||||
#include "seqcb.h"
|
||||
#include "actor.h"
|
||||
#include "seq.h"
|
||||
|
||||
|
||||
#include "files.h"
|
||||
|
||||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
|
@ -103,14 +111,12 @@ static void (*seqClientCallback[])(int, int) = {
|
|||
MGunOpenSeqCallback,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kMaxSeqClients = 256,
|
||||
kMaxSequences = 1024
|
||||
};
|
||||
|
||||
static ACTIVE activeList[kMaxSequences];
|
||||
static int seqActiveCount = 0;
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void Seq::Preload(void)
|
||||
{
|
||||
|
@ -122,7 +128,7 @@ void Seq::Preload(void)
|
|||
tilePreloadTile(seqGetTile(&frames[i]));
|
||||
}
|
||||
|
||||
void Seq::Precache(HitList &hits)
|
||||
void Seq::Precache(HitList& hits)
|
||||
{
|
||||
if (memcmp(signature, "SEQ\x1a", 4) != 0)
|
||||
I_Error("Invalid sequence");
|
||||
|
@ -132,130 +138,103 @@ void Seq::Precache(HitList &hits)
|
|||
tilePrecacheTile(seqGetTile(&frames[i]), -1, hits);
|
||||
}
|
||||
|
||||
void seqPrecacheId(int id, HitList &hits)
|
||||
void seqPrecacheId(int id, HitList& hits)
|
||||
{
|
||||
auto pSeq = getSequence(id);
|
||||
if (pSeq) pSeq->Precache(hits);
|
||||
}
|
||||
|
||||
SEQINST siWall[kMaxXWalls];
|
||||
SEQINST siCeiling[kMaxXSectors];
|
||||
SEQINST siFloor[kMaxXSectors];
|
||||
SEQINST siSprite[kMaxXSprites];
|
||||
SEQINST siMasked[kMaxXWalls];
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void UpdateSprite(int nXSprite, SEQFRAME *pFrame)
|
||||
void UpdateCeiling(int nXSector, SEQFRAME* pFrame)
|
||||
{
|
||||
assert(nXSprite > 0 && nXSprite < kMaxXSprites);
|
||||
int nSprite = xsprite[nXSprite].reference;
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
spritetype *pSprite = &sprite[nSprite];
|
||||
assert(pSprite->extra == nXSprite);
|
||||
if (pSprite->flags & 2)
|
||||
{
|
||||
if (tilesiz[pSprite->picnum].y != tilesiz[seqGetTile(pFrame)].y || tileTopOffset(pSprite->picnum) != tileTopOffset(seqGetTile(pFrame))
|
||||
|| (pFrame->at3_0 && pFrame->at3_0 != pSprite->yrepeat))
|
||||
pSprite->flags |= 4;
|
||||
}
|
||||
pSprite->picnum = seqGetTile(pFrame);
|
||||
if (pFrame->at5_0)
|
||||
pSprite->pal = pFrame->at5_0;
|
||||
pSprite->shade = pFrame->at4_0;
|
||||
|
||||
int scale = xsprite[nXSprite].scale; // SEQ size scaling
|
||||
if (pFrame->at2_0) {
|
||||
if (scale) pSprite->xrepeat = ClipRange(mulscale8(pFrame->at2_0, scale), 0, 255);
|
||||
else pSprite->xrepeat = pFrame->at2_0;
|
||||
}
|
||||
|
||||
if (pFrame->at3_0) {
|
||||
if (scale) pSprite->yrepeat = ClipRange(mulscale8(pFrame->at3_0, scale), 0, 255);
|
||||
else pSprite->yrepeat = pFrame->at3_0;
|
||||
}
|
||||
|
||||
if (pFrame->at1_4)
|
||||
pSprite->cstat |= 2;
|
||||
else
|
||||
pSprite->cstat &= ~2;
|
||||
if (pFrame->at1_5)
|
||||
pSprite->cstat |= 512;
|
||||
else
|
||||
pSprite->cstat &= ~512;
|
||||
if (pFrame->at1_6)
|
||||
pSprite->cstat |= 1;
|
||||
else
|
||||
pSprite->cstat &= ~1;
|
||||
if (pFrame->at1_7)
|
||||
pSprite->cstat |= 256;
|
||||
else
|
||||
pSprite->cstat &= ~256;
|
||||
if (pFrame->at6_2)
|
||||
pSprite->cstat |= 32768;
|
||||
else
|
||||
pSprite->cstat &= (unsigned short)~32768;
|
||||
if (pFrame->at6_0)
|
||||
pSprite->cstat |= 4096;
|
||||
else
|
||||
pSprite->cstat &= ~4096;
|
||||
if (pFrame->at5_6)
|
||||
pSprite->flags |= 256;
|
||||
else
|
||||
pSprite->flags &= ~256;
|
||||
if (pFrame->at5_7)
|
||||
pSprite->flags |= 8;
|
||||
else
|
||||
pSprite->flags &= ~8;
|
||||
if (pFrame->at6_3)
|
||||
pSprite->flags |= 1024;
|
||||
else
|
||||
pSprite->flags &= ~1024;
|
||||
if (pFrame->at6_4)
|
||||
pSprite->flags |= 2048;
|
||||
else
|
||||
pSprite->flags &= ~2048;
|
||||
assert(nXSector > 0 && nXSector < kMaxXSectors);
|
||||
int nSector = xsector[nXSector].reference;
|
||||
assert(nSector >= 0 && nSector < kMaxSectors);
|
||||
sectortype* pSector = §or[nSector];
|
||||
assert(pSector->extra == nXSector);
|
||||
pSector->ceilingpicnum = seqGetTile(pFrame);
|
||||
pSector->ceilingshade = pFrame->shade;
|
||||
if (pFrame->palette)
|
||||
pSector->ceilingpal = pFrame->palette;
|
||||
}
|
||||
|
||||
void UpdateWall(int nXWall, SEQFRAME *pFrame)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void UpdateFloor(int nXSector, SEQFRAME* pFrame)
|
||||
{
|
||||
assert(nXSector > 0 && nXSector < kMaxXSectors);
|
||||
int nSector = xsector[nXSector].reference;
|
||||
assert(nSector >= 0 && nSector < kMaxSectors);
|
||||
sectortype* pSector = §or[nSector];
|
||||
assert(pSector->extra == nXSector);
|
||||
pSector->floorpicnum = seqGetTile(pFrame);
|
||||
pSector->floorshade = pFrame->shade;
|
||||
if (pFrame->palette)
|
||||
pSector->floorpal = pFrame->palette;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void UpdateWall(int nXWall, SEQFRAME* pFrame)
|
||||
{
|
||||
assert(nXWall > 0 && nXWall < kMaxXWalls);
|
||||
int nWall = xwall[nXWall].reference;
|
||||
assert(nWall >= 0 && nWall < kMaxWalls);
|
||||
walltype *pWall = &wall[nWall];
|
||||
walltype* pWall = &wall[nWall];
|
||||
assert(pWall->extra == nXWall);
|
||||
pWall->picnum = seqGetTile(pFrame);
|
||||
if (pFrame->at5_0)
|
||||
pWall->pal = pFrame->at5_0;
|
||||
if (pFrame->at1_4)
|
||||
if (pFrame->palette)
|
||||
pWall->pal = pFrame->palette;
|
||||
if (pFrame->transparent)
|
||||
pWall->cstat |= 128;
|
||||
else
|
||||
pWall->cstat &= ~128;
|
||||
if (pFrame->at1_5)
|
||||
if (pFrame->transparent2)
|
||||
pWall->cstat |= 512;
|
||||
else
|
||||
pWall->cstat &= ~512;
|
||||
if (pFrame->at1_6)
|
||||
if (pFrame->blockable)
|
||||
pWall->cstat |= 1;
|
||||
else
|
||||
pWall->cstat &= ~1;
|
||||
if (pFrame->at1_7)
|
||||
if (pFrame->hittable)
|
||||
pWall->cstat |= 64;
|
||||
else
|
||||
pWall->cstat &= ~64;
|
||||
}
|
||||
|
||||
void UpdateMasked(int nXWall, SEQFRAME *pFrame)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void UpdateMasked(int nXWall, SEQFRAME* pFrame)
|
||||
{
|
||||
assert(nXWall > 0 && nXWall < kMaxXWalls);
|
||||
int nWall = xwall[nXWall].reference;
|
||||
assert(nWall >= 0 && nWall < kMaxWalls);
|
||||
walltype *pWall = &wall[nWall];
|
||||
walltype* pWall = &wall[nWall];
|
||||
assert(pWall->extra == nXWall);
|
||||
assert(pWall->nextwall >= 0);
|
||||
walltype *pWallNext = &wall[pWall->nextwall];
|
||||
walltype* pWallNext = &wall[pWall->nextwall];
|
||||
pWall->overpicnum = pWallNext->overpicnum = seqGetTile(pFrame);
|
||||
if (pFrame->at5_0)
|
||||
pWall->pal = pWallNext->pal = pFrame->at5_0;
|
||||
if (pFrame->at1_4)
|
||||
if (pFrame->palette)
|
||||
pWall->pal = pWallNext->pal = pFrame->palette;
|
||||
if (pFrame->transparent)
|
||||
{
|
||||
pWall->cstat |= 128;
|
||||
pWallNext->cstat |= 128;
|
||||
|
@ -265,7 +244,7 @@ void UpdateMasked(int nXWall, SEQFRAME *pFrame)
|
|||
pWall->cstat &= ~128;
|
||||
pWallNext->cstat &= ~128;
|
||||
}
|
||||
if (pFrame->at1_5)
|
||||
if (pFrame->transparent2)
|
||||
{
|
||||
pWall->cstat |= 512;
|
||||
pWallNext->cstat |= 512;
|
||||
|
@ -275,7 +254,7 @@ void UpdateMasked(int nXWall, SEQFRAME *pFrame)
|
|||
pWall->cstat &= ~512;
|
||||
pWallNext->cstat &= ~512;
|
||||
}
|
||||
if (pFrame->at1_6)
|
||||
if (pFrame->blockable)
|
||||
{
|
||||
pWall->cstat |= 1;
|
||||
pWallNext->cstat |= 1;
|
||||
|
@ -285,7 +264,7 @@ void UpdateMasked(int nXWall, SEQFRAME *pFrame)
|
|||
pWall->cstat &= ~1;
|
||||
pWallNext->cstat &= ~1;
|
||||
}
|
||||
if (pFrame->at1_7)
|
||||
if (pFrame->hittable)
|
||||
{
|
||||
pWall->cstat |= 64;
|
||||
pWallNext->cstat |= 64;
|
||||
|
@ -297,64 +276,121 @@ void UpdateMasked(int nXWall, SEQFRAME *pFrame)
|
|||
}
|
||||
}
|
||||
|
||||
void UpdateFloor(int nXSector, SEQFRAME *pFrame)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void UpdateSprite(int nXSprite, SEQFRAME* pFrame)
|
||||
{
|
||||
assert(nXSector > 0 && nXSector < kMaxXSectors);
|
||||
int nSector = xsector[nXSector].reference;
|
||||
assert(nSector >= 0 && nSector < kMaxSectors);
|
||||
sectortype *pSector = §or[nSector];
|
||||
assert(pSector->extra == nXSector);
|
||||
pSector->floorpicnum = seqGetTile(pFrame);
|
||||
pSector->floorshade = pFrame->at4_0;
|
||||
if (pFrame->at5_0)
|
||||
pSector->floorpal = pFrame->at5_0;
|
||||
assert(nXSprite > 0 && nXSprite < kMaxXSprites);
|
||||
int nSprite = xsprite[nXSprite].reference;
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
spritetype* pSprite = &sprite[nSprite];
|
||||
assert(pSprite->extra == nXSprite);
|
||||
if (pSprite->flags & 2)
|
||||
{
|
||||
if (tilesiz[pSprite->picnum].y != tilesiz[seqGetTile(pFrame)].y || tileTopOffset(pSprite->picnum) != tileTopOffset(seqGetTile(pFrame))
|
||||
|| (pFrame->yrepeat && pFrame->yrepeat != pSprite->yrepeat))
|
||||
pSprite->flags |= 4;
|
||||
}
|
||||
pSprite->picnum = seqGetTile(pFrame);
|
||||
if (pFrame->palette)
|
||||
pSprite->pal = pFrame->palette;
|
||||
pSprite->shade = pFrame->shade;
|
||||
|
||||
int scale = xsprite[nXSprite].scale; // SEQ size scaling
|
||||
if (pFrame->xrepeat) {
|
||||
if (scale) pSprite->xrepeat = ClipRange(mulscale8(pFrame->xrepeat, scale), 0, 255);
|
||||
else pSprite->xrepeat = pFrame->xrepeat;
|
||||
}
|
||||
|
||||
if (pFrame->yrepeat) {
|
||||
if (scale) pSprite->yrepeat = ClipRange(mulscale8(pFrame->yrepeat, scale), 0, 255);
|
||||
else pSprite->yrepeat = pFrame->yrepeat;
|
||||
}
|
||||
|
||||
if (pFrame->transparent)
|
||||
pSprite->cstat |= 2;
|
||||
else
|
||||
pSprite->cstat &= ~2;
|
||||
if (pFrame->transparent2)
|
||||
pSprite->cstat |= 512;
|
||||
else
|
||||
pSprite->cstat &= ~512;
|
||||
if (pFrame->blockable)
|
||||
pSprite->cstat |= 1;
|
||||
else
|
||||
pSprite->cstat &= ~1;
|
||||
if (pFrame->hittable)
|
||||
pSprite->cstat |= 256;
|
||||
else
|
||||
pSprite->cstat &= ~256;
|
||||
if (pFrame->invisible)
|
||||
pSprite->cstat |= 32768;
|
||||
else
|
||||
pSprite->cstat &= (unsigned short)~32768;
|
||||
if (pFrame->pushable)
|
||||
pSprite->cstat |= 4096;
|
||||
else
|
||||
pSprite->cstat &= ~4096;
|
||||
if (pFrame->smoke)
|
||||
pSprite->flags |= 256;
|
||||
else
|
||||
pSprite->flags &= ~256;
|
||||
if (pFrame->aiming)
|
||||
pSprite->flags |= 8;
|
||||
else
|
||||
pSprite->flags &= ~8;
|
||||
if (pFrame->flipx)
|
||||
pSprite->flags |= 1024;
|
||||
else
|
||||
pSprite->flags &= ~1024;
|
||||
if (pFrame->flipy)
|
||||
pSprite->flags |= 2048;
|
||||
else
|
||||
pSprite->flags &= ~2048;
|
||||
}
|
||||
|
||||
void UpdateCeiling(int nXSector, SEQFRAME *pFrame)
|
||||
{
|
||||
assert(nXSector > 0 && nXSector < kMaxXSectors);
|
||||
int nSector = xsector[nXSector].reference;
|
||||
assert(nSector >= 0 && nSector < kMaxSectors);
|
||||
sectortype *pSector = §or[nSector];
|
||||
assert(pSector->extra == nXSector);
|
||||
pSector->ceilingpicnum = seqGetTile(pFrame);
|
||||
pSector->ceilingshade = pFrame->at4_0;
|
||||
if (pFrame->at5_0)
|
||||
pSector->ceilingpal = pFrame->at5_0;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void SEQINST::Update(ACTIVE *pActive)
|
||||
void SEQINST::Update()
|
||||
{
|
||||
assert(frameIndex < pSequence->nFrames);
|
||||
switch (pActive->type)
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
UpdateWall(pActive->xindex, &pSequence->frames[frameIndex]);
|
||||
UpdateWall(index, &pSequence->frames[frameIndex]);
|
||||
break;
|
||||
case 1:
|
||||
UpdateCeiling(pActive->xindex , &pSequence->frames[frameIndex]);
|
||||
UpdateCeiling(index, &pSequence->frames[frameIndex]);
|
||||
break;
|
||||
case 2:
|
||||
UpdateFloor(pActive->xindex, &pSequence->frames[frameIndex]);
|
||||
UpdateFloor(index, &pSequence->frames[frameIndex]);
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
|
||||
UpdateSprite(pActive->xindex, &pSequence->frames[frameIndex]);
|
||||
if (pSequence->frames[frameIndex].at6_1) {
|
||||
UpdateSprite(index, &pSequence->frames[frameIndex]);
|
||||
if (pSequence->frames[frameIndex].playsound) {
|
||||
|
||||
int sound = pSequence->ata;
|
||||
int sound = pSequence->soundId;
|
||||
|
||||
// by NoOne: add random sound range feature
|
||||
if (!VanillaMode() && pSequence->frames[frameIndex].soundRange > 0)
|
||||
sound += Random(((pSequence->frames[frameIndex].soundRange == 1) ? 2 : pSequence->frames[frameIndex].soundRange));
|
||||
|
||||
sfxPlay3DSound(&sprite[xsprite[pActive->xindex].reference], sound, -1, 0);
|
||||
sfxPlay3DSound(&sprite[xsprite[index].reference], sound, -1, 0);
|
||||
}
|
||||
|
||||
|
||||
// by NoOne: add surfaceSound trigger feature
|
||||
spritetype* pSprite = &sprite[xsprite[pActive->xindex].reference];
|
||||
spritetype* pSprite = &sprite[xsprite[index].reference];
|
||||
if (!VanillaMode() && pSequence->frames[frameIndex].surfaceSound && zvel[pSprite->index] == 0 && xvel[pSprite->index] != 0) {
|
||||
|
||||
if (gUpperLink[pSprite->sectnum] >= 0) break; // don't play surface sound for stacked sectors
|
||||
|
@ -390,300 +426,123 @@ void SEQINST::Update(ACTIVE *pActive)
|
|||
break;
|
||||
}
|
||||
case 4:
|
||||
UpdateMasked(pActive->xindex, &pSequence->frames[frameIndex]);
|
||||
UpdateMasked(index, &pSequence->frames[frameIndex]);
|
||||
break;
|
||||
}
|
||||
if (pSequence->frames[frameIndex].at5_5 && atc != -1)
|
||||
seqClientCallback[atc](pActive->type, pActive->xindex);
|
||||
if (pSequence->frames[frameIndex].trigger && callback != -1)
|
||||
seqClientCallback[callback](type, index);
|
||||
}
|
||||
|
||||
SEQINST * GetInstance(int a1, int a2)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
struct ActiveList
|
||||
{
|
||||
switch (a1)
|
||||
TArray<SEQINST> list;
|
||||
|
||||
void clear() { list.Clear(); }
|
||||
int getSize() { return list.Size(); }
|
||||
SEQINST* getInst(int num) { return &list[num]; }
|
||||
int getIndex(int num) { return list[num].index; }
|
||||
int getType(int num) { return list[num].type; }
|
||||
|
||||
void remove(int num)
|
||||
{
|
||||
case 0:
|
||||
if (a2 > 0 && a2 < kMaxXWalls) return &siWall[a2];
|
||||
break;
|
||||
case 1:
|
||||
if (a2 > 0 && a2 < kMaxXSectors) return &siCeiling[a2];
|
||||
break;
|
||||
case 2:
|
||||
if (a2 > 0 && a2 < kMaxXSectors) return &siFloor[a2];
|
||||
break;
|
||||
case 3:
|
||||
if (a2 > 0 && a2 < kMaxXSprites) return &siSprite[a2];
|
||||
break;
|
||||
case 4:
|
||||
if (a2 > 0 && a2 < kMaxWalls) return &siMasked[a2];
|
||||
break;
|
||||
list[num] = list.Last();
|
||||
list.Pop();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void UnlockInstance(SEQINST *pInst)
|
||||
{
|
||||
assert(pInst != NULL);
|
||||
assert(pInst->pSequence != NULL);
|
||||
pInst->pSequence = NULL;
|
||||
pInst->at13 = 0;
|
||||
}
|
||||
|
||||
void seqSpawn(int a1, int a2, int a3, int a4)
|
||||
{
|
||||
SEQINST *pInst = GetInstance(a2, a3);
|
||||
if (!pInst) return;
|
||||
|
||||
auto pSeq = getSequence(a1);
|
||||
if (!pSeq)
|
||||
I_Error("Missing sequence #%d", a1);
|
||||
|
||||
int i = seqActiveCount;
|
||||
if (pInst->at13)
|
||||
SEQINST* getNew()
|
||||
{
|
||||
if (pSeq == pInst->pSequence)
|
||||
list.Reserve(1);
|
||||
return &list.Last();
|
||||
}
|
||||
|
||||
SEQINST* get(int type, int index)
|
||||
{
|
||||
for (auto& n : list)
|
||||
{
|
||||
if (n.type == type && n.index == index) return &n;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void remove(int type, int index)
|
||||
{
|
||||
for (unsigned i = 0; i < list.Size(); i++)
|
||||
{
|
||||
auto& n = list[i];
|
||||
if (n.type == type && n.index == index)
|
||||
{
|
||||
remove(i);
|
||||
return;
|
||||
UnlockInstance(pInst);
|
||||
for (i = 0; i < seqActiveCount; i++)
|
||||
{
|
||||
if (activeList[i].type == a2 && activeList[i].xindex == a3)
|
||||
break;
|
||||
}
|
||||
assert(i < seqActiveCount);
|
||||
}
|
||||
if (memcmp(pSeq->signature, "SEQ\x1a", 4) != 0)
|
||||
I_Error("Invalid sequence %d", a1);
|
||||
if ((pSeq->version & 0xff00) != 0x300)
|
||||
I_Error("Sequence %d is obsolete version", a1);
|
||||
if ((pSeq->version & 0xff) == 0x00)
|
||||
{
|
||||
for (int i = 0; i < pSeq->nFrames; i++)
|
||||
pSeq->frames[i].tile2 = 0;
|
||||
}
|
||||
pInst->at13 = 1;
|
||||
pInst->pSequence = pSeq;
|
||||
pInst->at8 = a1;
|
||||
pInst->atc = a4;
|
||||
pInst->at10 = pSeq->at8;
|
||||
pInst->frameIndex = 0;
|
||||
if (i == seqActiveCount)
|
||||
{
|
||||
assert(seqActiveCount < kMaxSequences);
|
||||
activeList[seqActiveCount].type = a2;
|
||||
activeList[seqActiveCount].xindex = a3;
|
||||
seqActiveCount++;
|
||||
}
|
||||
pInst->Update(&activeList[i]);
|
||||
}
|
||||
|
||||
void seqKill(int a1, int a2)
|
||||
{
|
||||
SEQINST *pInst = GetInstance(a1, a2);
|
||||
if (!pInst || !pInst->at13)
|
||||
return;
|
||||
int i;
|
||||
for (i = 0; i < seqActiveCount; i++)
|
||||
{
|
||||
if (activeList[i].type == a1 && activeList[i].xindex == a2)
|
||||
break;
|
||||
}
|
||||
assert(i < seqActiveCount);
|
||||
seqActiveCount--;
|
||||
activeList[i] = activeList[seqActiveCount];
|
||||
pInst->at13 = 0;
|
||||
UnlockInstance(pInst);
|
||||
}
|
||||
|
||||
void seqKillAll(void)
|
||||
{
|
||||
for (int i = 0; i < kMaxXWalls; i++)
|
||||
{
|
||||
if (siWall[i].at13)
|
||||
UnlockInstance(&siWall[i]);
|
||||
if (siMasked[i].at13)
|
||||
UnlockInstance(&siMasked[i]);
|
||||
}
|
||||
for (int i = 0; i < kMaxXSectors; i++)
|
||||
{
|
||||
if (siCeiling[i].at13)
|
||||
UnlockInstance(&siCeiling[i]);
|
||||
if (siFloor[i].at13)
|
||||
UnlockInstance(&siFloor[i]);
|
||||
}
|
||||
for (int i = 0; i < kMaxXSprites; i++)
|
||||
{
|
||||
if (siSprite[i].at13)
|
||||
UnlockInstance(&siSprite[i]);
|
||||
}
|
||||
seqActiveCount = 0;
|
||||
}
|
||||
|
||||
int seqGetStatus(int a1, int a2)
|
||||
{
|
||||
SEQINST *pInst = GetInstance(a1, a2);
|
||||
if (pInst && pInst->at13)
|
||||
return pInst->frameIndex;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int seqGetID(int a1, int a2)
|
||||
{
|
||||
SEQINST *pInst = GetInstance(a1, a2);
|
||||
if (pInst)
|
||||
return pInst->at8;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void seqProcess(int a1)
|
||||
{
|
||||
for (int i = 0; i < seqActiveCount; i++)
|
||||
{
|
||||
SEQINST *pInst = GetInstance(activeList[i].type, activeList[i].xindex);
|
||||
Seq *pSeq = pInst->pSequence;
|
||||
assert(pInst->frameIndex < pSeq->nFrames);
|
||||
pInst->at10 -= a1;
|
||||
while (pInst->at10 < 0)
|
||||
{
|
||||
pInst->at10 += pSeq->at8;
|
||||
pInst->frameIndex++;
|
||||
if (pInst->frameIndex == pSeq->nFrames)
|
||||
{
|
||||
if (pSeq->atc & 1)
|
||||
pInst->frameIndex = 0;
|
||||
else
|
||||
{
|
||||
UnlockInstance(pInst);
|
||||
if (pSeq->atc & 2)
|
||||
{
|
||||
switch (activeList[i].type)
|
||||
{
|
||||
case 3:
|
||||
{
|
||||
int nXSprite = activeList[i].xindex;
|
||||
int nSprite = xsprite[nXSprite].reference;
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
evKill(nSprite, 3);
|
||||
if ((sprite[nSprite].flags & kHitagRespawn) && sprite[nSprite].inittype >= kDudeBase && sprite[nSprite].inittype < kDudeMax)
|
||||
evPost(nSprite, 3, gGameOptions.nMonsterRespawnTime, kCallbackRespawn);
|
||||
else
|
||||
DeleteSprite(nSprite);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
int nXWall = activeList[i].xindex;
|
||||
int nWall = xwall[nXWall].reference;
|
||||
assert(nWall >= 0 && nWall < kMaxWalls);
|
||||
wall[nWall].cstat &= ~(8 + 16 + 32);
|
||||
if (wall[nWall].nextwall != -1)
|
||||
wall[wall[nWall].nextwall].cstat &= ~(8 + 16 + 32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
activeList[i--] = activeList[--seqActiveCount];
|
||||
break;
|
||||
}
|
||||
}
|
||||
pInst->Update(&activeList[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SeqLoadSave : public LoadSave {
|
||||
virtual void Load(void);
|
||||
virtual void Save(void);
|
||||
};
|
||||
|
||||
void SeqLoadSave::Load(void)
|
||||
static ActiveList activeList;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
SEQINST* GetInstance(int type, int nXIndex)
|
||||
{
|
||||
Read(&siWall, sizeof(siWall));
|
||||
Read(&siMasked, sizeof(siMasked));
|
||||
Read(&siCeiling, sizeof(siCeiling));
|
||||
Read(&siFloor, sizeof(siFloor));
|
||||
Read(&siSprite, sizeof(siSprite));
|
||||
Read(&activeList, sizeof(activeList));
|
||||
Read(&seqActiveCount, sizeof(seqActiveCount));
|
||||
for (int i = 0; i < kMaxXWalls; i++)
|
||||
{
|
||||
siWall[i].pSequence = NULL;
|
||||
siMasked[i].pSequence = NULL;
|
||||
}
|
||||
for (int i = 0; i < kMaxXSectors; i++)
|
||||
{
|
||||
siCeiling[i].pSequence = NULL;
|
||||
siFloor[i].pSequence = NULL;
|
||||
}
|
||||
for (int i = 0; i < kMaxXSprites; i++)
|
||||
{
|
||||
siSprite[i].pSequence = NULL;
|
||||
}
|
||||
for (int i = 0; i < seqActiveCount; i++)
|
||||
{
|
||||
SEQINST *pInst = GetInstance(activeList[i].type, activeList[i].xindex);
|
||||
if (pInst->at13)
|
||||
{
|
||||
int nSeq = pInst->at8;
|
||||
auto pSeq = getSequence(nSeq);
|
||||
if (!pSeq) {
|
||||
I_Error("Missing sequence #%d", nSeq);
|
||||
continue;
|
||||
}
|
||||
if (memcmp(pSeq->signature, "SEQ\x1a", 4) != 0)
|
||||
I_Error("Invalid sequence %d", nSeq);
|
||||
if ((pSeq->version & 0xff00) != 0x300)
|
||||
I_Error("Sequence %d is obsolete version", nSeq);
|
||||
pInst->pSequence = pSeq;
|
||||
}
|
||||
}
|
||||
return activeList.get(type, nXIndex);
|
||||
}
|
||||
|
||||
void SeqLoadSave::Save(void)
|
||||
void seqKill(int type, int nXIndex)
|
||||
{
|
||||
Write(&siWall, sizeof(siWall));
|
||||
Write(&siMasked, sizeof(siMasked));
|
||||
Write(&siCeiling, sizeof(siCeiling));
|
||||
Write(&siFloor, sizeof(siFloor));
|
||||
Write(&siSprite, sizeof(siSprite));
|
||||
Write(&activeList, sizeof(activeList));
|
||||
Write(&seqActiveCount, sizeof(seqActiveCount));
|
||||
activeList.remove(type, nXIndex);
|
||||
}
|
||||
|
||||
void SeqLoadSaveConstruct(void)
|
||||
void seqKillAll()
|
||||
{
|
||||
new SeqLoadSave();
|
||||
activeList.clear();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void ByteSwapSEQ(Seq* pSeq)
|
||||
{
|
||||
#if B_BIG_ENDIAN == 1
|
||||
#if 1//B_BIG_ENDIAN == 1
|
||||
pSeq->version = LittleShort(pSeq->version);
|
||||
pSeq->nFrames = LittleShort(pSeq->nFrames);
|
||||
pSeq->at8 = LittleShort(pSeq->at8);
|
||||
pSeq->ata = LittleShort(pSeq->ata);
|
||||
pSeq->atc = LittleLong(pSeq->atc);
|
||||
pSeq->ticksPerFrame = LittleShort(pSeq->ticksPerFrame);
|
||||
pSeq->soundId = LittleShort(pSeq->soundId);
|
||||
pSeq->flags = LittleLong(pSeq->flags);
|
||||
for (int i = 0; i < pSeq->nFrames; i++)
|
||||
{
|
||||
SEQFRAME* pFrame = &pSeq->frames[i];
|
||||
BitReader bitReader((char*)pFrame, sizeof(SEQFRAME));
|
||||
SEQFRAME swapFrame;
|
||||
swapFrame.tile = bitReader.readUnsigned(12);
|
||||
swapFrame.at1_4 = bitReader.readBit();
|
||||
swapFrame.at1_5 = bitReader.readBit();
|
||||
swapFrame.at1_6 = bitReader.readBit();
|
||||
swapFrame.at1_7 = bitReader.readBit();
|
||||
swapFrame.at2_0 = bitReader.readUnsigned(8);
|
||||
swapFrame.at3_0 = bitReader.readUnsigned(8);
|
||||
swapFrame.at4_0 = bitReader.readSigned(8);
|
||||
swapFrame.at5_0 = bitReader.readUnsigned(5);
|
||||
swapFrame.at5_5 = bitReader.readBit();
|
||||
swapFrame.at5_6 = bitReader.readBit();
|
||||
swapFrame.at5_7 = bitReader.readBit();
|
||||
swapFrame.at6_0 = bitReader.readBit();
|
||||
swapFrame.at6_1 = bitReader.readBit();
|
||||
swapFrame.at6_2 = bitReader.readBit();
|
||||
swapFrame.at6_3 = bitReader.readBit();
|
||||
swapFrame.at6_4 = bitReader.readBit();
|
||||
swapFrame.transparent = bitReader.readBit();
|
||||
swapFrame.transparent2 = bitReader.readBit();
|
||||
swapFrame.blockable = bitReader.readBit();
|
||||
swapFrame.hittable = bitReader.readBit();
|
||||
swapFrame.xrepeat = bitReader.readUnsigned(8);
|
||||
swapFrame.yrepeat = bitReader.readUnsigned(8);
|
||||
swapFrame.shade = bitReader.readSigned(8);
|
||||
swapFrame.palette = bitReader.readUnsigned(5);
|
||||
swapFrame.trigger = bitReader.readBit();
|
||||
swapFrame.smoke = bitReader.readBit();
|
||||
swapFrame.aiming = bitReader.readBit();
|
||||
swapFrame.pushable = bitReader.readBit();
|
||||
swapFrame.playsound = bitReader.readBit();
|
||||
swapFrame.invisible = bitReader.readBit();
|
||||
swapFrame.flipx = bitReader.readBit();
|
||||
swapFrame.flipy = bitReader.readBit();
|
||||
swapFrame.tile2 = bitReader.readUnsigned(4);
|
||||
swapFrame.soundRange = bitReader.readUnsigned(4);
|
||||
swapFrame.surfaceSound = bitReader.readBit();
|
||||
|
@ -693,10 +552,6 @@ static void ByteSwapSEQ(Seq* pSeq)
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
// This is to eliminate a huge design issue in NBlood that was apparently copied verbatim from the DOS-Version.
|
||||
// Sequences were cached in the resource and directly returned from there in writable form, with byte swapping directly performed in the cache on Big Endian systems.
|
||||
// To avoid such unsafe operations this caches the read data separately in static memory that's guaranteed not to be touched by the file system.
|
||||
FMemArena seqcache;
|
||||
static TMap<int, Seq*> sequences;
|
||||
Seq* getSequence(int res_id)
|
||||
|
@ -717,4 +572,148 @@ Seq* getSequence(int res_id)
|
|||
return seqdata;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void seqSpawn(int nSeqID, int type, int nXIndex, int callback)
|
||||
{
|
||||
Seq* pSequence = getSequence(nSeqID);
|
||||
|
||||
if (pSequence == nullptr) return;
|
||||
|
||||
SEQINST* pInst = activeList.get(type, nXIndex);
|
||||
if (!pInst)
|
||||
{
|
||||
pInst = activeList.getNew();
|
||||
}
|
||||
else
|
||||
{
|
||||
// already playing this sequence?
|
||||
if (pInst->nSeqID == nSeqID)
|
||||
return;
|
||||
}
|
||||
|
||||
pInst->pSequence = pSequence;
|
||||
pInst->nSeqID = nSeqID;
|
||||
pInst->callback = callback;
|
||||
pInst->timeCounter = (short)pSequence->ticksPerFrame;
|
||||
pInst->frameIndex = 0;
|
||||
pInst->type = type;
|
||||
pInst->index = nXIndex;
|
||||
pInst->Update();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int seqGetStatus(int type, int nXIndex)
|
||||
{
|
||||
SEQINST* pInst = activeList.get(type, nXIndex);
|
||||
if (pInst) return pInst->frameIndex;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int seqGetID(int type, int nXIndex)
|
||||
{
|
||||
SEQINST* pInst = activeList.get(type, nXIndex);
|
||||
if (pInst) return pInst->nSeqID;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void seqProcess(int nTicks)
|
||||
{
|
||||
for (int i = 0; i < activeList.getSize(); i++)
|
||||
{
|
||||
SEQINST* pInst = activeList.getInst(i);
|
||||
Seq* pSeq = pInst->pSequence;
|
||||
int index = pInst->index;
|
||||
|
||||
assert(pInst->frameIndex < pSeq->nFrames);
|
||||
|
||||
pInst->timeCounter -= nTicks;
|
||||
while (pInst->timeCounter < 0)
|
||||
{
|
||||
pInst->timeCounter += pSeq->ticksPerFrame;
|
||||
++pInst->frameIndex;
|
||||
|
||||
if (pInst->frameIndex == pSeq->nFrames)
|
||||
{
|
||||
if (!pSeq->isLooping())
|
||||
{
|
||||
if (pSeq->isRemovable())
|
||||
{
|
||||
if (pInst->type == SS_SPRITE)
|
||||
{
|
||||
short nSprite = (short)xsprite[index].reference;
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
evKill(nSprite, SS_SPRITE);
|
||||
if ((sprite[nSprite].hitag & kAttrRespawn) != 0 && (sprite[nSprite].zvel >= kDudeBase && sprite[nSprite].zvel < kDudeMax))
|
||||
evPost(nSprite, 3, gGameOptions.nMonsterRespawnTime, kCallbackRespawn);
|
||||
else deletesprite(nSprite); // safe to not use actPostSprite here
|
||||
}
|
||||
|
||||
if (pInst->type == SS_MASKED)
|
||||
{
|
||||
int nWall = xwall[index].reference;
|
||||
assert(nWall >= 0 && nWall < kMaxWalls);
|
||||
wall[nWall].cstat &= ~(8 + 16 + 32);
|
||||
if (wall[nWall].nextwall != -1)
|
||||
wall[wall[nWall].nextwall].cstat &= ~(8 + 16 + 32);
|
||||
}
|
||||
}
|
||||
|
||||
// remove it from the active list
|
||||
activeList.remove(i--);
|
||||
break;
|
||||
}
|
||||
else pInst->frameIndex = 0;
|
||||
}
|
||||
|
||||
pInst->Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
FSerializer& Serialize(FSerializer& arc, const char* keyname, SEQINST& w, SEQINST* def)
|
||||
{
|
||||
if (arc.BeginObject(keyname))
|
||||
{
|
||||
arc("index", w.index)
|
||||
("type", w.type)
|
||||
("callback", w.callback)
|
||||
("seqid", w.nSeqID)
|
||||
("timecounter", w.timeCounter)
|
||||
("frameindex", w.frameIndex)
|
||||
.EndObject();
|
||||
}
|
||||
if (arc.isReading())
|
||||
{
|
||||
w.pSequence = getSequence(w.nSeqID);
|
||||
}
|
||||
return arc;
|
||||
}
|
||||
|
||||
void SerializeSequences(FSerializer& arc)
|
||||
{
|
||||
arc("sequences", activeList.list);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -26,24 +26,25 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
BEGIN_BLD_NS
|
||||
|
||||
|
||||
struct SEQFRAME {
|
||||
struct SEQFRAME
|
||||
{
|
||||
unsigned int tile : 12;
|
||||
unsigned int at1_4 : 1; // transparent
|
||||
unsigned int at1_5 : 1; // transparent
|
||||
unsigned int at1_6 : 1; // blockable
|
||||
unsigned int at1_7 : 1; // hittable
|
||||
unsigned int at2_0 : 8; // xrepeat
|
||||
unsigned int at3_0 : 8; // yrepeat
|
||||
signed int at4_0 : 8; // shade
|
||||
unsigned int at5_0 : 5; // palette
|
||||
unsigned int at5_5 : 1; //
|
||||
unsigned int at5_6 : 1; //
|
||||
unsigned int at5_7 : 1; //
|
||||
unsigned int at6_0 : 1; //
|
||||
unsigned int at6_1 : 1; //
|
||||
unsigned int at6_2 : 1; // invisible
|
||||
unsigned int at6_3 : 1; //
|
||||
unsigned int at6_4 : 1; //
|
||||
unsigned int transparent : 1;
|
||||
unsigned int transparent2 : 1;
|
||||
unsigned int blockable : 1;
|
||||
unsigned int hittable : 1;
|
||||
unsigned int xrepeat : 8;
|
||||
unsigned int yrepeat : 8;
|
||||
signed int shade : 8;
|
||||
unsigned int palette : 5;
|
||||
unsigned int trigger : 1;
|
||||
unsigned int smoke : 1;
|
||||
unsigned int aiming : 1;
|
||||
unsigned int pushable : 1;
|
||||
unsigned int playsound : 1;
|
||||
unsigned int invisible : 1;// invisible
|
||||
unsigned int flipx : 1;
|
||||
unsigned int flipy : 1;
|
||||
unsigned int tile2 : 4;
|
||||
unsigned soundRange : 4; // (by NoOne) random sound range relative to global SEQ sound
|
||||
unsigned surfaceSound : 1; // (by NoOne) trigger surface sound when moving / touching
|
||||
|
@ -53,13 +54,23 @@ struct SEQFRAME {
|
|||
struct Seq {
|
||||
char signature[4];
|
||||
short version;
|
||||
short nFrames; // at6
|
||||
short at8;
|
||||
short ata;
|
||||
int atc;
|
||||
short nFrames;
|
||||
short ticksPerFrame;
|
||||
short soundId;
|
||||
int flags;
|
||||
SEQFRAME frames[1];
|
||||
void Preload(void);
|
||||
void Precache(HitList &);
|
||||
void Precache(HitList&);
|
||||
|
||||
bool isLooping()
|
||||
{
|
||||
return (flags & 1) != 0;
|
||||
}
|
||||
|
||||
bool isRemovable()
|
||||
{
|
||||
return (flags & 2) != 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct ACTIVE
|
||||
|
@ -70,24 +81,25 @@ struct ACTIVE
|
|||
|
||||
struct SEQINST
|
||||
{
|
||||
Seq *pSequence;
|
||||
int at8;
|
||||
int atc;
|
||||
short at10;
|
||||
Seq* pSequence;
|
||||
int index, type;
|
||||
|
||||
int nSeqID;
|
||||
int callback;
|
||||
short timeCounter;
|
||||
unsigned char frameIndex;
|
||||
char at13;
|
||||
void Update(ACTIVE *pActive);
|
||||
void Update();
|
||||
};
|
||||
|
||||
inline int seqGetTile(SEQFRAME* pFrame)
|
||||
{
|
||||
return pFrame->tile+(pFrame->tile2<<12);
|
||||
return pFrame->tile + (pFrame->tile2 << 12);
|
||||
}
|
||||
|
||||
int seqRegisterClient(void(*pClient)(int, int));
|
||||
void seqPrecacheId(int id, HitList &hits);
|
||||
SEQINST * GetInstance(int a1, int a2);
|
||||
void UnlockInstance(SEQINST *pInst);
|
||||
void seqPrecacheId(int id, HitList& hits);
|
||||
SEQINST* GetInstance(int a1, int a2);
|
||||
void UnlockInstance(SEQINST* pInst);
|
||||
void seqSpawn(int a1, int a2, int a3, int a4 = -1);
|
||||
void seqKill(int a1, int a2);
|
||||
void seqKillAll(void);
|
||||
|
|
Loading…
Reference in a new issue