mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-01 14:11:01 +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;
|
break;
|
||||||
case kThingBloodChunks: {
|
case kThingBloodChunks: {
|
||||||
SEQINST *pInst = GetInstance(3, pSprite->extra);
|
SEQINST *pInst = GetInstance(3, pSprite->extra);
|
||||||
if (pInst && pInst->at13) {
|
if (pInst) {
|
||||||
auto seq = getSequence(pInst->at8);
|
auto seq = getSequence(pInst->nSeqID);
|
||||||
if (!seq) break;
|
if (!seq) break;
|
||||||
seqSpawn(pInst->at8, 3, pSprite->extra);
|
seqSpawn(pInst->nSeqID, 3, pSprite->extra);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1460,9 +1460,9 @@ int getDispersionModifier(spritetype* pSprite, int minDisp, int maxDisp)
|
||||||
int disp = 1;
|
int disp = 1;
|
||||||
if (pSeq != nullptr)
|
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++) {
|
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;
|
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
|
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++) {
|
for (int i = 0; i < pSeq->nFrames; i++) {
|
||||||
if (!pSeq->frames[i].at5_5) continue;
|
if (!pSeq->frames[i].trigger) continue;
|
||||||
pExtra->forcePunch = false;
|
pExtra->forcePunch = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,14 +476,6 @@ void LoadSave::Write(const void *pData, int nSize)
|
||||||
|
|
||||||
bool GameInterface::LoadGame()
|
bool GameInterface::LoadGame()
|
||||||
{
|
{
|
||||||
sndKillAllSounds();
|
|
||||||
sfxKillAllSounds();
|
|
||||||
ambKillAll();
|
|
||||||
seqKillAll();
|
|
||||||
if (gamestate != GS_LEVEL)
|
|
||||||
{
|
|
||||||
memset(xsprite, 0, sizeof(xsprite));
|
|
||||||
}
|
|
||||||
LoadSave::hLFile = ReadSavegameChunk("snapshot.bld");
|
LoadSave::hLFile = ReadSavegameChunk("snapshot.bld");
|
||||||
if (!LoadSave::hLFile.isOpen())
|
if (!LoadSave::hLFile.isOpen())
|
||||||
return false;
|
return false;
|
||||||
|
@ -735,7 +727,6 @@ void LevelsLoadSaveConstruct(void);
|
||||||
void MessagesLoadSaveConstruct(void);
|
void MessagesLoadSaveConstruct(void);
|
||||||
void MirrorLoadSaveConstruct(void);
|
void MirrorLoadSaveConstruct(void);
|
||||||
void PlayerLoadSaveConstruct(void);
|
void PlayerLoadSaveConstruct(void);
|
||||||
void SeqLoadSaveConstruct(void);
|
|
||||||
void TriggersLoadSaveConstruct(void);
|
void TriggersLoadSaveConstruct(void);
|
||||||
void ViewLoadSaveConstruct(void);
|
void ViewLoadSaveConstruct(void);
|
||||||
void WarpLoadSaveConstruct(void);
|
void WarpLoadSaveConstruct(void);
|
||||||
|
@ -754,7 +745,6 @@ void LoadSaveSetup(void)
|
||||||
MessagesLoadSaveConstruct();
|
MessagesLoadSaveConstruct();
|
||||||
MirrorLoadSaveConstruct();
|
MirrorLoadSaveConstruct();
|
||||||
PlayerLoadSaveConstruct();
|
PlayerLoadSaveConstruct();
|
||||||
SeqLoadSaveConstruct();
|
|
||||||
TriggersLoadSaveConstruct();
|
TriggersLoadSaveConstruct();
|
||||||
ViewLoadSaveConstruct();
|
ViewLoadSaveConstruct();
|
||||||
WarpLoadSaveConstruct();
|
WarpLoadSaveConstruct();
|
||||||
|
@ -765,10 +755,21 @@ void LoadSaveSetup(void)
|
||||||
|
|
||||||
|
|
||||||
void SerializeEvents(FSerializer& arc);
|
void SerializeEvents(FSerializer& arc);
|
||||||
|
void SerializeSequences(FSerializer& arc);
|
||||||
|
|
||||||
void GameInterface::SerializeGameState(FSerializer& arc)
|
void GameInterface::SerializeGameState(FSerializer& arc)
|
||||||
{
|
{
|
||||||
|
sndKillAllSounds();
|
||||||
|
sfxKillAllSounds();
|
||||||
|
ambKillAll();
|
||||||
|
seqKillAll();
|
||||||
|
if (gamestate != GS_LEVEL)
|
||||||
|
{
|
||||||
|
memset(xsprite, 0, sizeof(xsprite));
|
||||||
|
}
|
||||||
|
|
||||||
SerializeEvents(arc);
|
SerializeEvents(arc);
|
||||||
|
SerializeSequences(arc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||||
Copyright (C) 2019 Nuke.YKT
|
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
|
modify it under the terms of the GNU General Public License version 2
|
||||||
as published by the Free Software Foundation.
|
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.
|
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 "build.h"
|
||||||
#include "common_game.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 "actor.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "raze_sound.h"
|
#include "raze_sound.h"
|
||||||
#include "seqcb.h"
|
#include "actor.h"
|
||||||
|
#include "seq.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "files.h"
|
||||||
|
|
||||||
|
|
||||||
BEGIN_BLD_NS
|
BEGIN_BLD_NS
|
||||||
|
|
||||||
|
@ -103,14 +111,12 @@ static void (*seqClientCallback[])(int, int) = {
|
||||||
MGunOpenSeqCallback,
|
MGunOpenSeqCallback,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
kMaxSeqClients = 256,
|
|
||||||
kMaxSequences = 1024
|
|
||||||
};
|
|
||||||
|
|
||||||
static ACTIVE activeList[kMaxSequences];
|
//---------------------------------------------------------------------------
|
||||||
static int seqActiveCount = 0;
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void Seq::Preload(void)
|
void Seq::Preload(void)
|
||||||
{
|
{
|
||||||
|
@ -138,82 +144,49 @@ void seqPrecacheId(int id, HitList &hits)
|
||||||
if (pSeq) pSeq->Precache(hits);
|
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);
|
assert(nXSector > 0 && nXSector < kMaxXSectors);
|
||||||
int nSprite = xsprite[nXSprite].reference;
|
int nSector = xsector[nXSector].reference;
|
||||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
assert(nSector >= 0 && nSector < kMaxSectors);
|
||||||
spritetype *pSprite = &sprite[nSprite];
|
sectortype* pSector = §or[nSector];
|
||||||
assert(pSprite->extra == nXSprite);
|
assert(pSector->extra == nXSector);
|
||||||
if (pSprite->flags & 2)
|
pSector->ceilingpicnum = seqGetTile(pFrame);
|
||||||
|
pSector->ceilingshade = pFrame->shade;
|
||||||
|
if (pFrame->palette)
|
||||||
|
pSector->ceilingpal = pFrame->palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void UpdateFloor(int nXSector, SEQFRAME* pFrame)
|
||||||
{
|
{
|
||||||
if (tilesiz[pSprite->picnum].y != tilesiz[seqGetTile(pFrame)].y || tileTopOffset(pSprite->picnum) != tileTopOffset(seqGetTile(pFrame))
|
assert(nXSector > 0 && nXSector < kMaxXSectors);
|
||||||
|| (pFrame->at3_0 && pFrame->at3_0 != pSprite->yrepeat))
|
int nSector = xsector[nXSector].reference;
|
||||||
pSprite->flags |= 4;
|
assert(nSector >= 0 && nSector < kMaxSectors);
|
||||||
}
|
sectortype* pSector = §or[nSector];
|
||||||
pSprite->picnum = seqGetTile(pFrame);
|
assert(pSector->extra == nXSector);
|
||||||
if (pFrame->at5_0)
|
pSector->floorpicnum = seqGetTile(pFrame);
|
||||||
pSprite->pal = pFrame->at5_0;
|
pSector->floorshade = pFrame->shade;
|
||||||
pSprite->shade = pFrame->at4_0;
|
if (pFrame->palette)
|
||||||
|
pSector->floorpal = pFrame->palette;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateWall(int nXWall, SEQFRAME* pFrame)
|
void UpdateWall(int nXWall, SEQFRAME* pFrame)
|
||||||
{
|
{
|
||||||
|
@ -223,26 +196,32 @@ void UpdateWall(int nXWall, SEQFRAME *pFrame)
|
||||||
walltype* pWall = &wall[nWall];
|
walltype* pWall = &wall[nWall];
|
||||||
assert(pWall->extra == nXWall);
|
assert(pWall->extra == nXWall);
|
||||||
pWall->picnum = seqGetTile(pFrame);
|
pWall->picnum = seqGetTile(pFrame);
|
||||||
if (pFrame->at5_0)
|
if (pFrame->palette)
|
||||||
pWall->pal = pFrame->at5_0;
|
pWall->pal = pFrame->palette;
|
||||||
if (pFrame->at1_4)
|
if (pFrame->transparent)
|
||||||
pWall->cstat |= 128;
|
pWall->cstat |= 128;
|
||||||
else
|
else
|
||||||
pWall->cstat &= ~128;
|
pWall->cstat &= ~128;
|
||||||
if (pFrame->at1_5)
|
if (pFrame->transparent2)
|
||||||
pWall->cstat |= 512;
|
pWall->cstat |= 512;
|
||||||
else
|
else
|
||||||
pWall->cstat &= ~512;
|
pWall->cstat &= ~512;
|
||||||
if (pFrame->at1_6)
|
if (pFrame->blockable)
|
||||||
pWall->cstat |= 1;
|
pWall->cstat |= 1;
|
||||||
else
|
else
|
||||||
pWall->cstat &= ~1;
|
pWall->cstat &= ~1;
|
||||||
if (pFrame->at1_7)
|
if (pFrame->hittable)
|
||||||
pWall->cstat |= 64;
|
pWall->cstat |= 64;
|
||||||
else
|
else
|
||||||
pWall->cstat &= ~64;
|
pWall->cstat &= ~64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void UpdateMasked(int nXWall, SEQFRAME* pFrame)
|
void UpdateMasked(int nXWall, SEQFRAME* pFrame)
|
||||||
{
|
{
|
||||||
assert(nXWall > 0 && nXWall < kMaxXWalls);
|
assert(nXWall > 0 && nXWall < kMaxXWalls);
|
||||||
|
@ -253,9 +232,9 @@ void UpdateMasked(int nXWall, SEQFRAME *pFrame)
|
||||||
assert(pWall->nextwall >= 0);
|
assert(pWall->nextwall >= 0);
|
||||||
walltype* pWallNext = &wall[pWall->nextwall];
|
walltype* pWallNext = &wall[pWall->nextwall];
|
||||||
pWall->overpicnum = pWallNext->overpicnum = seqGetTile(pFrame);
|
pWall->overpicnum = pWallNext->overpicnum = seqGetTile(pFrame);
|
||||||
if (pFrame->at5_0)
|
if (pFrame->palette)
|
||||||
pWall->pal = pWallNext->pal = pFrame->at5_0;
|
pWall->pal = pWallNext->pal = pFrame->palette;
|
||||||
if (pFrame->at1_4)
|
if (pFrame->transparent)
|
||||||
{
|
{
|
||||||
pWall->cstat |= 128;
|
pWall->cstat |= 128;
|
||||||
pWallNext->cstat |= 128;
|
pWallNext->cstat |= 128;
|
||||||
|
@ -265,7 +244,7 @@ void UpdateMasked(int nXWall, SEQFRAME *pFrame)
|
||||||
pWall->cstat &= ~128;
|
pWall->cstat &= ~128;
|
||||||
pWallNext->cstat &= ~128;
|
pWallNext->cstat &= ~128;
|
||||||
}
|
}
|
||||||
if (pFrame->at1_5)
|
if (pFrame->transparent2)
|
||||||
{
|
{
|
||||||
pWall->cstat |= 512;
|
pWall->cstat |= 512;
|
||||||
pWallNext->cstat |= 512;
|
pWallNext->cstat |= 512;
|
||||||
|
@ -275,7 +254,7 @@ void UpdateMasked(int nXWall, SEQFRAME *pFrame)
|
||||||
pWall->cstat &= ~512;
|
pWall->cstat &= ~512;
|
||||||
pWallNext->cstat &= ~512;
|
pWallNext->cstat &= ~512;
|
||||||
}
|
}
|
||||||
if (pFrame->at1_6)
|
if (pFrame->blockable)
|
||||||
{
|
{
|
||||||
pWall->cstat |= 1;
|
pWall->cstat |= 1;
|
||||||
pWallNext->cstat |= 1;
|
pWallNext->cstat |= 1;
|
||||||
|
@ -285,7 +264,7 @@ void UpdateMasked(int nXWall, SEQFRAME *pFrame)
|
||||||
pWall->cstat &= ~1;
|
pWall->cstat &= ~1;
|
||||||
pWallNext->cstat &= ~1;
|
pWallNext->cstat &= ~1;
|
||||||
}
|
}
|
||||||
if (pFrame->at1_7)
|
if (pFrame->hittable)
|
||||||
{
|
{
|
||||||
pWall->cstat |= 64;
|
pWall->cstat |= 64;
|
||||||
pWallNext->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);
|
assert(nXSprite > 0 && nXSprite < kMaxXSprites);
|
||||||
int nSector = xsector[nXSector].reference;
|
int nSprite = xsprite[nXSprite].reference;
|
||||||
assert(nSector >= 0 && nSector < kMaxSectors);
|
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||||
sectortype *pSector = §or[nSector];
|
spritetype* pSprite = &sprite[nSprite];
|
||||||
assert(pSector->extra == nXSector);
|
assert(pSprite->extra == nXSprite);
|
||||||
pSector->floorpicnum = seqGetTile(pFrame);
|
if (pSprite->flags & 2)
|
||||||
pSector->floorshade = pFrame->at4_0;
|
{
|
||||||
if (pFrame->at5_0)
|
if (tilesiz[pSprite->picnum].y != tilesiz[seqGetTile(pFrame)].y || tileTopOffset(pSprite->picnum) != tileTopOffset(seqGetTile(pFrame))
|
||||||
pSector->floorpal = pFrame->at5_0;
|
|| (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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateCeiling(int nXSector, SEQFRAME *pFrame)
|
if (pFrame->yrepeat) {
|
||||||
{
|
if (scale) pSprite->yrepeat = ClipRange(mulscale8(pFrame->yrepeat, scale), 0, 255);
|
||||||
assert(nXSector > 0 && nXSector < kMaxXSectors);
|
else pSprite->yrepeat = pFrame->yrepeat;
|
||||||
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)
|
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 SEQINST::Update()
|
||||||
{
|
{
|
||||||
assert(frameIndex < pSequence->nFrames);
|
assert(frameIndex < pSequence->nFrames);
|
||||||
switch (pActive->type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
UpdateWall(pActive->xindex, &pSequence->frames[frameIndex]);
|
UpdateWall(index, &pSequence->frames[frameIndex]);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
UpdateCeiling(pActive->xindex , &pSequence->frames[frameIndex]);
|
UpdateCeiling(index, &pSequence->frames[frameIndex]);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
UpdateFloor(pActive->xindex, &pSequence->frames[frameIndex]);
|
UpdateFloor(index, &pSequence->frames[frameIndex]);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
{
|
{
|
||||||
|
|
||||||
UpdateSprite(pActive->xindex, &pSequence->frames[frameIndex]);
|
UpdateSprite(index, &pSequence->frames[frameIndex]);
|
||||||
if (pSequence->frames[frameIndex].at6_1) {
|
if (pSequence->frames[frameIndex].playsound) {
|
||||||
|
|
||||||
int sound = pSequence->ata;
|
int sound = pSequence->soundId;
|
||||||
|
|
||||||
// by NoOne: add random sound range feature
|
// by NoOne: add random sound range feature
|
||||||
if (!VanillaMode() && pSequence->frames[frameIndex].soundRange > 0)
|
if (!VanillaMode() && pSequence->frames[frameIndex].soundRange > 0)
|
||||||
sound += Random(((pSequence->frames[frameIndex].soundRange == 1) ? 2 : pSequence->frames[frameIndex].soundRange));
|
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
|
// 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 (!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
|
if (gUpperLink[pSprite->sectnum] >= 0) break; // don't play surface sound for stacked sectors
|
||||||
|
@ -390,300 +426,123 @@ void SEQINST::Update(ACTIVE *pActive)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4:
|
case 4:
|
||||||
UpdateMasked(pActive->xindex, &pSequence->frames[frameIndex]);
|
UpdateMasked(index, &pSequence->frames[frameIndex]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (pSequence->frames[frameIndex].at5_5 && atc != -1)
|
if (pSequence->frames[frameIndex].trigger && callback != -1)
|
||||||
seqClientCallback[atc](pActive->type, pActive->xindex);
|
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:
|
list[num] = list.Last();
|
||||||
if (a2 > 0 && a2 < kMaxXWalls) return &siWall[a2];
|
list.Pop();
|
||||||
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;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnlockInstance(SEQINST *pInst)
|
SEQINST* getNew()
|
||||||
{
|
{
|
||||||
assert(pInst != NULL);
|
list.Reserve(1);
|
||||||
assert(pInst->pSequence != NULL);
|
return &list.Last();
|
||||||
pInst->pSequence = NULL;
|
|
||||||
pInst->at13 = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void seqSpawn(int a1, int a2, int a3, int a4)
|
SEQINST* get(int type, int index)
|
||||||
{
|
{
|
||||||
SEQINST *pInst = GetInstance(a2, a3);
|
for (auto& n : list)
|
||||||
if (!pInst) return;
|
|
||||||
|
|
||||||
auto pSeq = getSequence(a1);
|
|
||||||
if (!pSeq)
|
|
||||||
I_Error("Missing sequence #%d", a1);
|
|
||||||
|
|
||||||
int i = seqActiveCount;
|
|
||||||
if (pInst->at13)
|
|
||||||
{
|
{
|
||||||
if (pSeq == pInst->pSequence)
|
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;
|
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));
|
return activeList.get(type, nXIndex);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeqLoadSave::Save(void)
|
void seqKill(int type, int nXIndex)
|
||||||
{
|
{
|
||||||
Write(&siWall, sizeof(siWall));
|
activeList.remove(type, nXIndex);
|
||||||
Write(&siMasked, sizeof(siMasked));
|
|
||||||
Write(&siCeiling, sizeof(siCeiling));
|
|
||||||
Write(&siFloor, sizeof(siFloor));
|
|
||||||
Write(&siSprite, sizeof(siSprite));
|
|
||||||
Write(&activeList, sizeof(activeList));
|
|
||||||
Write(&seqActiveCount, sizeof(seqActiveCount));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SeqLoadSaveConstruct(void)
|
void seqKillAll()
|
||||||
{
|
{
|
||||||
new SeqLoadSave();
|
activeList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
static void ByteSwapSEQ(Seq* pSeq)
|
static void ByteSwapSEQ(Seq* pSeq)
|
||||||
{
|
{
|
||||||
#if B_BIG_ENDIAN == 1
|
#if 1//B_BIG_ENDIAN == 1
|
||||||
pSeq->version = LittleShort(pSeq->version);
|
pSeq->version = LittleShort(pSeq->version);
|
||||||
pSeq->nFrames = LittleShort(pSeq->nFrames);
|
pSeq->nFrames = LittleShort(pSeq->nFrames);
|
||||||
pSeq->at8 = LittleShort(pSeq->at8);
|
pSeq->ticksPerFrame = LittleShort(pSeq->ticksPerFrame);
|
||||||
pSeq->ata = LittleShort(pSeq->ata);
|
pSeq->soundId = LittleShort(pSeq->soundId);
|
||||||
pSeq->atc = LittleLong(pSeq->atc);
|
pSeq->flags = LittleLong(pSeq->flags);
|
||||||
for (int i = 0; i < pSeq->nFrames; i++)
|
for (int i = 0; i < pSeq->nFrames; i++)
|
||||||
{
|
{
|
||||||
SEQFRAME* pFrame = &pSeq->frames[i];
|
SEQFRAME* pFrame = &pSeq->frames[i];
|
||||||
BitReader bitReader((char*)pFrame, sizeof(SEQFRAME));
|
BitReader bitReader((char*)pFrame, sizeof(SEQFRAME));
|
||||||
SEQFRAME swapFrame;
|
SEQFRAME swapFrame;
|
||||||
swapFrame.tile = bitReader.readUnsigned(12);
|
swapFrame.tile = bitReader.readUnsigned(12);
|
||||||
swapFrame.at1_4 = bitReader.readBit();
|
swapFrame.transparent = bitReader.readBit();
|
||||||
swapFrame.at1_5 = bitReader.readBit();
|
swapFrame.transparent2 = bitReader.readBit();
|
||||||
swapFrame.at1_6 = bitReader.readBit();
|
swapFrame.blockable = bitReader.readBit();
|
||||||
swapFrame.at1_7 = bitReader.readBit();
|
swapFrame.hittable = bitReader.readBit();
|
||||||
swapFrame.at2_0 = bitReader.readUnsigned(8);
|
swapFrame.xrepeat = bitReader.readUnsigned(8);
|
||||||
swapFrame.at3_0 = bitReader.readUnsigned(8);
|
swapFrame.yrepeat = bitReader.readUnsigned(8);
|
||||||
swapFrame.at4_0 = bitReader.readSigned(8);
|
swapFrame.shade = bitReader.readSigned(8);
|
||||||
swapFrame.at5_0 = bitReader.readUnsigned(5);
|
swapFrame.palette = bitReader.readUnsigned(5);
|
||||||
swapFrame.at5_5 = bitReader.readBit();
|
swapFrame.trigger = bitReader.readBit();
|
||||||
swapFrame.at5_6 = bitReader.readBit();
|
swapFrame.smoke = bitReader.readBit();
|
||||||
swapFrame.at5_7 = bitReader.readBit();
|
swapFrame.aiming = bitReader.readBit();
|
||||||
swapFrame.at6_0 = bitReader.readBit();
|
swapFrame.pushable = bitReader.readBit();
|
||||||
swapFrame.at6_1 = bitReader.readBit();
|
swapFrame.playsound = bitReader.readBit();
|
||||||
swapFrame.at6_2 = bitReader.readBit();
|
swapFrame.invisible = bitReader.readBit();
|
||||||
swapFrame.at6_3 = bitReader.readBit();
|
swapFrame.flipx = bitReader.readBit();
|
||||||
swapFrame.at6_4 = bitReader.readBit();
|
swapFrame.flipy = bitReader.readBit();
|
||||||
swapFrame.tile2 = bitReader.readUnsigned(4);
|
swapFrame.tile2 = bitReader.readUnsigned(4);
|
||||||
swapFrame.soundRange = bitReader.readUnsigned(4);
|
swapFrame.soundRange = bitReader.readUnsigned(4);
|
||||||
swapFrame.surfaceSound = bitReader.readBit();
|
swapFrame.surfaceSound = bitReader.readBit();
|
||||||
|
@ -693,10 +552,6 @@ static void ByteSwapSEQ(Seq* pSeq)
|
||||||
#endif
|
#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;
|
FMemArena seqcache;
|
||||||
static TMap<int, Seq*> sequences;
|
static TMap<int, Seq*> sequences;
|
||||||
Seq* getSequence(int res_id)
|
Seq* getSequence(int res_id)
|
||||||
|
@ -717,4 +572,148 @@ Seq* getSequence(int res_id)
|
||||||
return seqdata;
|
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
|
END_BLD_NS
|
||||||
|
|
|
@ -26,24 +26,25 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
BEGIN_BLD_NS
|
BEGIN_BLD_NS
|
||||||
|
|
||||||
|
|
||||||
struct SEQFRAME {
|
struct SEQFRAME
|
||||||
|
{
|
||||||
unsigned int tile : 12;
|
unsigned int tile : 12;
|
||||||
unsigned int at1_4 : 1; // transparent
|
unsigned int transparent : 1;
|
||||||
unsigned int at1_5 : 1; // transparent
|
unsigned int transparent2 : 1;
|
||||||
unsigned int at1_6 : 1; // blockable
|
unsigned int blockable : 1;
|
||||||
unsigned int at1_7 : 1; // hittable
|
unsigned int hittable : 1;
|
||||||
unsigned int at2_0 : 8; // xrepeat
|
unsigned int xrepeat : 8;
|
||||||
unsigned int at3_0 : 8; // yrepeat
|
unsigned int yrepeat : 8;
|
||||||
signed int at4_0 : 8; // shade
|
signed int shade : 8;
|
||||||
unsigned int at5_0 : 5; // palette
|
unsigned int palette : 5;
|
||||||
unsigned int at5_5 : 1; //
|
unsigned int trigger : 1;
|
||||||
unsigned int at5_6 : 1; //
|
unsigned int smoke : 1;
|
||||||
unsigned int at5_7 : 1; //
|
unsigned int aiming : 1;
|
||||||
unsigned int at6_0 : 1; //
|
unsigned int pushable : 1;
|
||||||
unsigned int at6_1 : 1; //
|
unsigned int playsound : 1;
|
||||||
unsigned int at6_2 : 1; // invisible
|
unsigned int invisible : 1;// invisible
|
||||||
unsigned int at6_3 : 1; //
|
unsigned int flipx : 1;
|
||||||
unsigned int at6_4 : 1; //
|
unsigned int flipy : 1;
|
||||||
unsigned int tile2 : 4;
|
unsigned int tile2 : 4;
|
||||||
unsigned soundRange : 4; // (by NoOne) random sound range relative to global SEQ sound
|
unsigned soundRange : 4; // (by NoOne) random sound range relative to global SEQ sound
|
||||||
unsigned surfaceSound : 1; // (by NoOne) trigger surface sound when moving / touching
|
unsigned surfaceSound : 1; // (by NoOne) trigger surface sound when moving / touching
|
||||||
|
@ -53,13 +54,23 @@ struct SEQFRAME {
|
||||||
struct Seq {
|
struct Seq {
|
||||||
char signature[4];
|
char signature[4];
|
||||||
short version;
|
short version;
|
||||||
short nFrames; // at6
|
short nFrames;
|
||||||
short at8;
|
short ticksPerFrame;
|
||||||
short ata;
|
short soundId;
|
||||||
int atc;
|
int flags;
|
||||||
SEQFRAME frames[1];
|
SEQFRAME frames[1];
|
||||||
void Preload(void);
|
void Preload(void);
|
||||||
void Precache(HitList&);
|
void Precache(HitList&);
|
||||||
|
|
||||||
|
bool isLooping()
|
||||||
|
{
|
||||||
|
return (flags & 1) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isRemovable()
|
||||||
|
{
|
||||||
|
return (flags & 2) != 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ACTIVE
|
struct ACTIVE
|
||||||
|
@ -71,12 +82,13 @@ struct ACTIVE
|
||||||
struct SEQINST
|
struct SEQINST
|
||||||
{
|
{
|
||||||
Seq* pSequence;
|
Seq* pSequence;
|
||||||
int at8;
|
int index, type;
|
||||||
int atc;
|
|
||||||
short at10;
|
int nSeqID;
|
||||||
|
int callback;
|
||||||
|
short timeCounter;
|
||||||
unsigned char frameIndex;
|
unsigned char frameIndex;
|
||||||
char at13;
|
void Update();
|
||||||
void Update(ACTIVE *pActive);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int seqGetTile(SEQFRAME* pFrame)
|
inline int seqGetTile(SEQFRAME* pFrame)
|
||||||
|
|
Loading…
Reference in a new issue