mirror of
https://github.com/ZDoom/Raze.git
synced 2025-02-27 13:50:49 +00:00
rework of the SEQ code.
Mostly redone by integrating Raze's changes into Blood-RE's version. The BitReader was replaced with an independent implementation that's not integrated into the backend. Most importantly this decouples the internal representation of SEQs from Blood's file format so a format redesign is doable.
This commit is contained in:
parent
eb7d3c542e
commit
9eef6c42cb
17 changed files with 479 additions and 603 deletions
|
@ -4,3 +4,4 @@
|
||||||
using FileSys::FileReader;
|
using FileSys::FileReader;
|
||||||
using FileSys::FileWriter;
|
using FileSys::FileWriter;
|
||||||
using FileSys::BufferWriter;
|
using FileSys::BufferWriter;
|
||||||
|
using FileSys::BitReader;
|
|
@ -362,6 +362,42 @@ public:
|
||||||
TArray<unsigned char>&& TakeBuffer() { return std::move(mBuffer); }
|
TArray<unsigned char>&& TakeBuffer() { return std::move(mBuffer); }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
class BitReader
|
||||||
|
{
|
||||||
|
const uint8_t* buffer;
|
||||||
|
const size_t size; // counts in bits, not bytes
|
||||||
|
size_t bitofs;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BitReader(const uint8_t* data, uint32_t _size) : buffer(data), size(_size * 8), bitofs(0) { }
|
||||||
|
~BitReader() = default;
|
||||||
|
uint32_t getBit()
|
||||||
|
{
|
||||||
|
if (bitofs > size) return ~0u;
|
||||||
|
// maintaining a byte offset costs more than doing this shift for every bit so skip it.
|
||||||
|
uint32_t ret = (buffer[bitofs >> 3] >> (bitofs & 7)) & 1;
|
||||||
|
bitofs++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
uint32_t getBits(uint32_t n)
|
||||||
|
{
|
||||||
|
if (bitofs > size - n || n > 32) return ~0u;
|
||||||
|
uint32_t ret;
|
||||||
|
for (uint32_t i = 0; i < n; i++) ret |= getBit() << i;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
int32_t getBitsSigned(uint32_t n)
|
||||||
|
{
|
||||||
|
uint32_t notn = 32 - n;
|
||||||
|
return (((int)getBits(n)) << notn) >> notn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void skipBits(uint32_t n)
|
||||||
|
{
|
||||||
|
bitofs += n;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,6 +39,7 @@ void MarkVerticesForSector(int sector);
|
||||||
static constexpr double zmaptoworld = (1 / 256.); // this for necessary conversions to convert map data to floating point representation.
|
static constexpr double zmaptoworld = (1 / 256.); // this for necessary conversions to convert map data to floating point representation.
|
||||||
static constexpr double maptoworld = (1 / 16.); // this for necessary conversions to convert map data to floating point representation.
|
static constexpr double maptoworld = (1 / 16.); // this for necessary conversions to convert map data to floating point representation.
|
||||||
static constexpr double REPEAT_SCALE = (1 / 64.); // map's 'repeat' values use 2.6 fixed point.
|
static constexpr double REPEAT_SCALE = (1 / 64.); // map's 'repeat' values use 2.6 fixed point.
|
||||||
|
static constexpr float REPEAT_SCALEF = (1 / 64.f); // map's 'repeat' values use 2.6 fixed point.
|
||||||
static constexpr double INV_REPEAT_SCALE = 64;
|
static constexpr double INV_REPEAT_SCALE = 64;
|
||||||
|
|
||||||
// These are refactoring markers that should be eliminated.
|
// These are refactoring markers that should be eliminated.
|
||||||
|
@ -170,7 +171,7 @@ enum ESpriteBits // names mostly from SW.
|
||||||
|
|
||||||
// Blood flags
|
// Blood flags
|
||||||
CSTAT_SPRITE_BLOOD_BIT2 = 1024, // Both of these get set but not checked directly, so no idea what they mean...
|
CSTAT_SPRITE_BLOOD_BIT2 = 1024, // Both of these get set but not checked directly, so no idea what they mean...
|
||||||
CSTAT_SPRITE_BLOOD_BIT1 = 4096,
|
CSTAT_SPRITE_BLOOD_PUSHABLE = 4096,
|
||||||
CSTAT_SPRITE_MOVE_FORWARD = 8192,
|
CSTAT_SPRITE_MOVE_FORWARD = 8192,
|
||||||
CSTAT_SPRITE_MOVE_REVERSE = 16384,
|
CSTAT_SPRITE_MOVE_REVERSE = 16384,
|
||||||
CSTAT_SPRITE_MOVE_MASK = CSTAT_SPRITE_MOVE_FORWARD | CSTAT_SPRITE_MOVE_REVERSE,
|
CSTAT_SPRITE_MOVE_MASK = CSTAT_SPRITE_MOVE_FORWARD | CSTAT_SPRITE_MOVE_REVERSE,
|
||||||
|
|
|
@ -894,7 +894,7 @@ static void actInitDudes()
|
||||||
if (!act->IsPlayerActor())
|
if (!act->IsPlayerActor())
|
||||||
{
|
{
|
||||||
act->clipdist = act->fClipDist();
|
act->clipdist = act->fClipDist();
|
||||||
act->spr.cstat |= CSTAT_SPRITE_BLOOD_BIT1 | CSTAT_SPRITE_BLOCK_ALL;
|
act->spr.cstat |= CSTAT_SPRITE_BLOOD_PUSHABLE | CSTAT_SPRITE_BLOCK_ALL;
|
||||||
act->vel.Zero();
|
act->vel.Zero();
|
||||||
|
|
||||||
if ((currentLevel->featureflags & kFeatureEnemyAttacks) && act->xspr.sysData2 > 0)
|
if ((currentLevel->featureflags & kFeatureEnemyAttacks) && act->xspr.sysData2 > 0)
|
||||||
|
@ -4138,7 +4138,7 @@ DBloodActor* actSpawnDude(DBloodActor* source, int nType, double dist)
|
||||||
spawned->spr.Angles.Yaw = angle;
|
spawned->spr.Angles.Yaw = angle;
|
||||||
SetActor(spawned, pos);
|
SetActor(spawned, pos);
|
||||||
|
|
||||||
spawned->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL | CSTAT_SPRITE_BLOOD_BIT1;
|
spawned->spr.cstat |= CSTAT_SPRITE_BLOCK_ALL | CSTAT_SPRITE_BLOOD_PUSHABLE;
|
||||||
spawned->clipdist = spawned->fClipDist();
|
spawned->clipdist = spawned->fClipDist();
|
||||||
spawned->xspr.health = spawned->startHealth() << 4;
|
spawned->xspr.health = spawned->startHealth() << 4;
|
||||||
spawned->xspr.respawn = 1;
|
spawned->xspr.respawn = 1;
|
||||||
|
|
|
@ -689,15 +689,15 @@ void viewProcessSprites(tspriteArray& tsprites, const DVector3& cPos, DAngle cA,
|
||||||
{
|
{
|
||||||
pTSprite->shade = ClipRange(pTSprite->shade - 16 - QRandom(8), -128, 127);
|
pTSprite->shade = ClipRange(pTSprite->shade - 16 - QRandom(8), -128, 127);
|
||||||
}
|
}
|
||||||
if (pTSprite->flags & 256)
|
if (pTSprite->flags & kHitagSmoke)
|
||||||
{
|
{
|
||||||
viewAddEffect(tsprites, nTSprite, kViewEffectSmokeHigh);
|
viewAddEffect(tsprites, nTSprite, kViewEffectSmokeHigh);
|
||||||
}
|
}
|
||||||
if (pTSprite->flags & 1024)
|
if (pTSprite->flags & kHitagFlipX)
|
||||||
{
|
{
|
||||||
pTSprite->cstat |= CSTAT_SPRITE_XFLIP;
|
pTSprite->cstat |= CSTAT_SPRITE_XFLIP;
|
||||||
}
|
}
|
||||||
if (pTSprite->flags & 2048)
|
if (pTSprite->flags & kHitagFlipY)
|
||||||
{
|
{
|
||||||
pTSprite->cstat |= CSTAT_SPRITE_YFLIP;
|
pTSprite->cstat |= CSTAT_SPRITE_YFLIP;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "actor.h"
|
#include "actor.h"
|
||||||
#include "ai.h"
|
#include "ai.h"
|
||||||
#include "aiunicult.h"
|
#include "aiunicult.h"
|
||||||
#include "callback.h"
|
|
||||||
#include "db.h"
|
#include "db.h"
|
||||||
#include "endgame.h"
|
#include "endgame.h"
|
||||||
#include "eventq.h"
|
#include "eventq.h"
|
||||||
|
@ -318,10 +317,6 @@ inline bool DemoRecordStatus(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool VanillaMode()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
void sndPlaySpecialMusicOrNothing(int nMusic);
|
void sndPlaySpecialMusicOrNothing(int nMusic);
|
||||||
|
|
||||||
struct GameInterface : public ::GameInterface
|
struct GameInterface : public ::GameInterface
|
||||||
|
|
|
@ -283,7 +283,7 @@ void Respawn(DBloodActor* actor) // 9
|
||||||
if (actor->IsDudeActor())
|
if (actor->IsDudeActor())
|
||||||
{
|
{
|
||||||
actor->spr.pos = actor->basePoint;
|
actor->spr.pos = actor->basePoint;
|
||||||
actor->spr.cstat |= CSTAT_SPRITE_BLOOD_BIT1 | CSTAT_SPRITE_BLOCK_ALL;
|
actor->spr.cstat |= CSTAT_SPRITE_BLOOD_PUSHABLE | CSTAT_SPRITE_BLOCK_ALL;
|
||||||
#ifdef NOONE_EXTENSIONS
|
#ifdef NOONE_EXTENSIONS
|
||||||
if (!gModernMap || actor->xspr.sysData2 <= 0) actor->xspr.health = actor->startHealth() << 4;
|
if (!gModernMap || actor->xspr.sysData2 <= 0) actor->xspr.health = actor->startHealth() << 4;
|
||||||
else actor->xspr.health = ClipRange(actor->xspr.sysData2 << 4, 1, 65535);
|
else actor->xspr.health = ClipRange(actor->xspr.sysData2 << 4, 1, 65535);
|
||||||
|
@ -493,6 +493,7 @@ void fxTeslaAlt(DBloodActor* actor) // 15
|
||||||
|
|
||||||
static const int tommySleeveSnd[] = { 608, 609, 611 }; // unused?
|
static const int tommySleeveSnd[] = { 608, 609, 611 }; // unused?
|
||||||
static const int sawedOffSleeveSnd[] = { 610, 612 };
|
static const int sawedOffSleeveSnd[] = { 610, 612 };
|
||||||
|
void sleeveStopBouncing(DBloodActor* pSprite);
|
||||||
|
|
||||||
void fxBouncingSleeve(DBloodActor* actor) // 16
|
void fxBouncingSleeve(DBloodActor* actor) // 16
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
/*
|
|
||||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
|
||||||
Copyright (C) 2019 Nuke.YKT
|
|
||||||
|
|
||||||
This file is part of NBlood.
|
|
||||||
|
|
||||||
NBlood 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.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
BEGIN_BLD_NS
|
|
||||||
void sleeveStopBouncing(DBloodActor* pSprite);
|
|
||||||
|
|
||||||
END_BLD_NS
|
|
|
@ -27,12 +27,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "seqcb.h"
|
|
||||||
#include "coreactor.h"
|
#include "coreactor.h"
|
||||||
#include "vectors.h"
|
#include "vectors.h"
|
||||||
|
|
||||||
BEGIN_BLD_NS
|
BEGIN_BLD_NS
|
||||||
|
|
||||||
|
inline bool VanillaMode()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void QuitGame(void);
|
void QuitGame(void);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -434,16 +438,23 @@ enum {
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// sprite physics attributes
|
||||||
|
kPhysMove = 0x0001, // affected by movement physics
|
||||||
|
kPhysGravity = 0x0002, // affected by gravity
|
||||||
|
kPhysFalling = 0x0004, // currently in z-motion
|
||||||
|
|
||||||
// sprite attributes
|
// sprite attributes
|
||||||
kHitagAutoAim = 0x0008,
|
kHitagAutoAim = 0x0008,
|
||||||
kHitagRespawn = 0x0010,
|
kHitagRespawn = 0x0010,
|
||||||
kHitagFree = 0x0020,
|
kHitagFree = 0x0020,
|
||||||
kHitagSmoke = 0x0100,
|
kHitagSmoke = 0x0100,
|
||||||
|
|
||||||
// sprite physics attributes
|
// why are these needed? They seem redunant.
|
||||||
kPhysMove = 0x0001, // affected by movement physics
|
kHitagFlipX = 1024,
|
||||||
kPhysGravity = 0x0002, // affected by gravity
|
kHitagFlipY = 2048,
|
||||||
kPhysFalling = 0x0004, // currently in z-motion
|
|
||||||
|
|
||||||
|
|
||||||
kAng5 = 28,
|
kAng5 = 28,
|
||||||
kAng15 = 85,
|
kAng15 = 85,
|
||||||
|
@ -660,52 +671,4 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BitReader {
|
|
||||||
public:
|
|
||||||
int nBitPos;
|
|
||||||
int nSize;
|
|
||||||
uint8_t* pBuffer;
|
|
||||||
BitReader(uint8_t* _pBuffer, int _nSize, int _nBitPos) { pBuffer = _pBuffer; nSize = _nSize; nBitPos = _nBitPos; nSize -= nBitPos >> 3; }
|
|
||||||
BitReader(uint8_t* _pBuffer, int _nSize) { pBuffer = _pBuffer; nSize = _nSize; nBitPos = 0; }
|
|
||||||
int readBit()
|
|
||||||
{
|
|
||||||
if (nSize <= 0)
|
|
||||||
I_Error("Buffer overflow in BitReader");
|
|
||||||
int bit = ((*pBuffer) >> nBitPos) & 1;
|
|
||||||
if (++nBitPos >= 8)
|
|
||||||
{
|
|
||||||
nBitPos = 0;
|
|
||||||
pBuffer++;
|
|
||||||
nSize--;
|
|
||||||
}
|
|
||||||
return bit;
|
|
||||||
}
|
|
||||||
void skipBits(int nBits)
|
|
||||||
{
|
|
||||||
nBitPos += nBits;
|
|
||||||
pBuffer += nBitPos >> 3;
|
|
||||||
nSize -= nBitPos >> 3;
|
|
||||||
nBitPos &= 7;
|
|
||||||
if ((nSize == 0 && nBitPos > 0) || nSize < 0)
|
|
||||||
I_Error("Buffer overflow in BitReader");
|
|
||||||
}
|
|
||||||
unsigned int readUnsigned(int nBits)
|
|
||||||
{
|
|
||||||
unsigned int n = 0;
|
|
||||||
assert(nBits <= 32);
|
|
||||||
for (int i = 0; i < nBits; i++)
|
|
||||||
n += readBit() << i;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
int readSigned(int nBits)
|
|
||||||
{
|
|
||||||
assert(nBits <= 32);
|
|
||||||
int n = (int)readUnsigned(nBits);
|
|
||||||
n <<= 32 - nBits;
|
|
||||||
n >>= 32 - nBits;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
END_BLD_NS
|
END_BLD_NS
|
||||||
|
|
|
@ -314,83 +314,83 @@ void dbLoadMap(const char* pPath, DVector3& pos, short* pAngle, sectortype** cur
|
||||||
assert(nCount <= nXSectorSize);
|
assert(nCount <= nXSectorSize);
|
||||||
fr.Read(pBuffer, nCount);
|
fr.Read(pBuffer, nCount);
|
||||||
BitReader bitReader(pBuffer, nCount);
|
BitReader bitReader(pBuffer, nCount);
|
||||||
/*pXSector->reference =*/ bitReader.readSigned(14);
|
/*pXSector->reference =*/ bitReader.getBitsSigned(14);
|
||||||
pXSector->state = bitReader.readUnsigned(1);
|
pXSector->state = bitReader.getBits(1);
|
||||||
pXSector->busy = bitReader.readUnsigned(17);
|
pXSector->busy = bitReader.getBits(17);
|
||||||
pXSector->data = bitReader.readUnsigned(16);
|
pXSector->data = bitReader.getBits(16);
|
||||||
pXSector->txID = bitReader.readUnsigned(10);
|
pXSector->txID = bitReader.getBits(10);
|
||||||
pXSector->busyWaveA = bitReader.readUnsigned(3);
|
pXSector->busyWaveA = bitReader.getBits(3);
|
||||||
pXSector->busyWaveB = bitReader.readUnsigned(3);
|
pXSector->busyWaveB = bitReader.getBits(3);
|
||||||
pXSector->rxID = bitReader.readUnsigned(10);
|
pXSector->rxID = bitReader.getBits(10);
|
||||||
pXSector->command = bitReader.readUnsigned(8);
|
pXSector->command = bitReader.getBits(8);
|
||||||
pXSector->triggerOn = bitReader.readUnsigned(1);
|
pXSector->triggerOn = bitReader.getBits(1);
|
||||||
pXSector->triggerOff = bitReader.readUnsigned(1);
|
pXSector->triggerOff = bitReader.getBits(1);
|
||||||
pXSector->busyTimeA = bitReader.readUnsigned(12);
|
pXSector->busyTimeA = bitReader.getBits(12);
|
||||||
pXSector->waitTimeA = bitReader.readUnsigned(12);
|
pXSector->waitTimeA = bitReader.getBits(12);
|
||||||
pXSector->restState = bitReader.readUnsigned(1);
|
pXSector->restState = bitReader.getBits(1);
|
||||||
pXSector->interruptable = bitReader.readUnsigned(1);
|
pXSector->interruptable = bitReader.getBits(1);
|
||||||
pXSector->amplitude = bitReader.readSigned(8);
|
pXSector->amplitude = bitReader.getBitsSigned(8);
|
||||||
pXSector->freq = bitReader.readUnsigned(8);
|
pXSector->freq = bitReader.getBits(8);
|
||||||
pXSector->reTriggerA = bitReader.readUnsigned(1);
|
pXSector->reTriggerA = bitReader.getBits(1);
|
||||||
pXSector->reTriggerB = bitReader.readUnsigned(1);
|
pXSector->reTriggerB = bitReader.getBits(1);
|
||||||
pXSector->phase = bitReader.readUnsigned(8);
|
pXSector->phase = bitReader.getBits(8);
|
||||||
pXSector->wave = bitReader.readUnsigned(4);
|
pXSector->wave = bitReader.getBits(4);
|
||||||
pXSector->shadeAlways = bitReader.readUnsigned(1);
|
pXSector->shadeAlways = bitReader.getBits(1);
|
||||||
pXSector->shadeFloor = bitReader.readUnsigned(1);
|
pXSector->shadeFloor = bitReader.getBits(1);
|
||||||
pXSector->shadeCeiling = bitReader.readUnsigned(1);
|
pXSector->shadeCeiling = bitReader.getBits(1);
|
||||||
pXSector->shadeWalls = bitReader.readUnsigned(1);
|
pXSector->shadeWalls = bitReader.getBits(1);
|
||||||
pXSector->shade = bitReader.readSigned(8);
|
pXSector->shade = bitReader.getBitsSigned(8);
|
||||||
pXSector->panAlways = bitReader.readUnsigned(1);
|
pXSector->panAlways = bitReader.getBits(1);
|
||||||
pXSector->panFloor = bitReader.readUnsigned(1);
|
pXSector->panFloor = bitReader.getBits(1);
|
||||||
pXSector->panCeiling = bitReader.readUnsigned(1);
|
pXSector->panCeiling = bitReader.getBits(1);
|
||||||
pXSector->Drag = bitReader.readUnsigned(1);
|
pXSector->Drag = bitReader.getBits(1);
|
||||||
pXSector->Underwater = bitReader.readUnsigned(1);
|
pXSector->Underwater = bitReader.getBits(1);
|
||||||
pXSector->Depth = bitReader.readUnsigned(3);
|
pXSector->Depth = bitReader.getBits(3);
|
||||||
pXSector->panVel = bitReader.readUnsigned(8);
|
pXSector->panVel = bitReader.getBits(8);
|
||||||
pXSector->panAngle = mapangle(bitReader.readUnsigned(11));
|
pXSector->panAngle = mapangle(bitReader.getBits(11));
|
||||||
pXSector->pauseMotion = bitReader.readUnsigned(1);
|
pXSector->pauseMotion = bitReader.getBits(1);
|
||||||
pXSector->decoupled = bitReader.readUnsigned(1);
|
pXSector->decoupled = bitReader.getBits(1);
|
||||||
pXSector->triggerOnce = bitReader.readUnsigned(1);
|
pXSector->triggerOnce = bitReader.getBits(1);
|
||||||
pXSector->isTriggered = bitReader.readUnsigned(1);
|
pXSector->isTriggered = bitReader.getBits(1);
|
||||||
pXSector->Key = bitReader.readUnsigned(3);
|
pXSector->Key = bitReader.getBits(3);
|
||||||
pXSector->Push = bitReader.readUnsigned(1);
|
pXSector->Push = bitReader.getBits(1);
|
||||||
pXSector->Vector = bitReader.readUnsigned(1);
|
pXSector->Vector = bitReader.getBits(1);
|
||||||
pXSector->Reserved = bitReader.readUnsigned(1);
|
pXSector->Reserved = bitReader.getBits(1);
|
||||||
pXSector->Enter = bitReader.readUnsigned(1);
|
pXSector->Enter = bitReader.getBits(1);
|
||||||
pXSector->Exit = bitReader.readUnsigned(1);
|
pXSector->Exit = bitReader.getBits(1);
|
||||||
pXSector->Wallpush = bitReader.readUnsigned(1);
|
pXSector->Wallpush = bitReader.getBits(1);
|
||||||
pXSector->color = bitReader.readUnsigned(1);
|
pXSector->color = bitReader.getBits(1);
|
||||||
/*pXSector->unused2 =*/ bitReader.readUnsigned(1);
|
/*pXSector->unused2 =*/ bitReader.getBits(1);
|
||||||
pXSector->busyTimeB = bitReader.readUnsigned(12);
|
pXSector->busyTimeB = bitReader.getBits(12);
|
||||||
pXSector->waitTimeB = bitReader.readUnsigned(12);
|
pXSector->waitTimeB = bitReader.getBits(12);
|
||||||
pXSector->stopOn = bitReader.readUnsigned(1);
|
pXSector->stopOn = bitReader.getBits(1);
|
||||||
pXSector->stopOff = bitReader.readUnsigned(1);
|
pXSector->stopOff = bitReader.getBits(1);
|
||||||
pXSector->ceilpal = bitReader.readUnsigned(4);
|
pXSector->ceilpal = bitReader.getBits(4);
|
||||||
pXSector->offCeilZ = bitReader.readSigned(32) * zmaptoworld;
|
pXSector->offCeilZ = bitReader.getBitsSigned(32) * zmaptoworld;
|
||||||
pXSector->onCeilZ = bitReader.readSigned(32) * zmaptoworld;
|
pXSector->onCeilZ = bitReader.getBitsSigned(32) * zmaptoworld;
|
||||||
pXSector->offFloorZ = bitReader.readSigned(32) * zmaptoworld;
|
pXSector->offFloorZ = bitReader.getBitsSigned(32) * zmaptoworld;
|
||||||
pXSector->onFloorZ = bitReader.readSigned(32) * zmaptoworld;
|
pXSector->onFloorZ = bitReader.getBitsSigned(32) * zmaptoworld;
|
||||||
/*pXSector->marker0 =*/ bitReader.readUnsigned(16);
|
/*pXSector->marker0 =*/ bitReader.getBits(16);
|
||||||
/*pXSector->marker1 =*/ bitReader.readUnsigned(16);
|
/*pXSector->marker1 =*/ bitReader.getBits(16);
|
||||||
pXSector->Crush = bitReader.readUnsigned(1);
|
pXSector->Crush = bitReader.getBits(1);
|
||||||
pSector->ceilingxpan_ += bitReader.readUnsigned(8) / 256.f;
|
pSector->ceilingxpan_ += bitReader.getBits(8) / 256.f;
|
||||||
pSector->ceilingypan_ += bitReader.readUnsigned(8) / 256.f;
|
pSector->ceilingypan_ += bitReader.getBits(8) / 256.f;
|
||||||
pSector->floorxpan_ += bitReader.readUnsigned(8) / 256.f;
|
pSector->floorxpan_ += bitReader.getBits(8) / 256.f;
|
||||||
pXSector->damageType = bitReader.readUnsigned(3);
|
pXSector->damageType = bitReader.getBits(3);
|
||||||
pXSector->floorpal = bitReader.readUnsigned(4);
|
pXSector->floorpal = bitReader.getBits(4);
|
||||||
pSector->floorypan_ += bitReader.readUnsigned(8) / 256.f;
|
pSector->floorypan_ += bitReader.getBits(8) / 256.f;
|
||||||
pXSector->locked = bitReader.readUnsigned(1);
|
pXSector->locked = bitReader.getBits(1);
|
||||||
pXSector->windVel = bitReader.readUnsigned(10);
|
pXSector->windVel = bitReader.getBits(10);
|
||||||
pXSector->windAng = mapangle(bitReader.readUnsigned(11));
|
pXSector->windAng = mapangle(bitReader.getBits(11));
|
||||||
pXSector->windAlways = bitReader.readUnsigned(1);
|
pXSector->windAlways = bitReader.getBits(1);
|
||||||
pXSector->dudeLockout = bitReader.readUnsigned(1);
|
pXSector->dudeLockout = bitReader.getBits(1);
|
||||||
pXSector->bobTheta = bitReader.readUnsigned(11);
|
pXSector->bobTheta = bitReader.getBits(11);
|
||||||
pXSector->bobZRange = bitReader.readUnsigned(5);
|
pXSector->bobZRange = bitReader.getBits(5);
|
||||||
pXSector->bobSpeed = bitReader.readSigned(12);
|
pXSector->bobSpeed = bitReader.getBitsSigned(12);
|
||||||
pXSector->bobAlways = bitReader.readUnsigned(1);
|
pXSector->bobAlways = bitReader.getBits(1);
|
||||||
pXSector->bobFloor = bitReader.readUnsigned(1);
|
pXSector->bobFloor = bitReader.getBits(1);
|
||||||
pXSector->bobCeiling = bitReader.readUnsigned(1);
|
pXSector->bobCeiling = bitReader.getBits(1);
|
||||||
pXSector->bobRotate = bitReader.readUnsigned(1);
|
pXSector->bobRotate = bitReader.getBits(1);
|
||||||
pXSector->busy = IntToFixed(pXSector->state);
|
pXSector->busy = IntToFixed(pXSector->state);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -441,37 +441,37 @@ void dbLoadMap(const char* pPath, DVector3& pos, short* pAngle, sectortype** cur
|
||||||
assert(nCount <= nXWallSize);
|
assert(nCount <= nXWallSize);
|
||||||
fr.Read(pBuffer, nCount);
|
fr.Read(pBuffer, nCount);
|
||||||
BitReader bitReader(pBuffer, nCount);
|
BitReader bitReader(pBuffer, nCount);
|
||||||
/*pXWall->reference =*/ bitReader.readSigned(14);
|
/*pXWall->reference =*/ bitReader.getBitsSigned(14);
|
||||||
pXWall->state = bitReader.readUnsigned(1);
|
pXWall->state = bitReader.getBits(1);
|
||||||
pXWall->busy = bitReader.readUnsigned(17);
|
pXWall->busy = bitReader.getBits(17);
|
||||||
pXWall->data = bitReader.readSigned(16);
|
pXWall->data = bitReader.getBitsSigned(16);
|
||||||
pXWall->txID = bitReader.readUnsigned(10);
|
pXWall->txID = bitReader.getBits(10);
|
||||||
bitReader.readUnsigned(6);
|
bitReader.getBits(6);
|
||||||
pXWall->rxID = bitReader.readUnsigned(10);
|
pXWall->rxID = bitReader.getBits(10);
|
||||||
pXWall->command = bitReader.readUnsigned(8);
|
pXWall->command = bitReader.getBits(8);
|
||||||
pXWall->triggerOn = bitReader.readUnsigned(1);
|
pXWall->triggerOn = bitReader.getBits(1);
|
||||||
pXWall->triggerOff = bitReader.readUnsigned(1);
|
pXWall->triggerOff = bitReader.getBits(1);
|
||||||
pXWall->busyTime = bitReader.readUnsigned(12);
|
pXWall->busyTime = bitReader.getBits(12);
|
||||||
pXWall->waitTime = bitReader.readUnsigned(12);
|
pXWall->waitTime = bitReader.getBits(12);
|
||||||
pXWall->restState = bitReader.readUnsigned(1);
|
pXWall->restState = bitReader.getBits(1);
|
||||||
pXWall->interruptable = bitReader.readUnsigned(1);
|
pXWall->interruptable = bitReader.getBits(1);
|
||||||
pXWall->panAlways = bitReader.readUnsigned(1);
|
pXWall->panAlways = bitReader.getBits(1);
|
||||||
pXWall->panVel.X = bitReader.readSigned(8);
|
pXWall->panVel.X = bitReader.getBitsSigned(8);
|
||||||
pXWall->panVel.Y = bitReader.readSigned(8);
|
pXWall->panVel.Y = bitReader.getBitsSigned(8);
|
||||||
pXWall->decoupled = bitReader.readUnsigned(1);
|
pXWall->decoupled = bitReader.getBits(1);
|
||||||
pXWall->triggerOnce = bitReader.readUnsigned(1);
|
pXWall->triggerOnce = bitReader.getBits(1);
|
||||||
pXWall->isTriggered = bitReader.readUnsigned(1);
|
pXWall->isTriggered = bitReader.getBits(1);
|
||||||
pXWall->key = bitReader.readUnsigned(3);
|
pXWall->key = bitReader.getBits(3);
|
||||||
pXWall->triggerPush = bitReader.readUnsigned(1);
|
pXWall->triggerPush = bitReader.getBits(1);
|
||||||
pXWall->triggerVector = bitReader.readUnsigned(1);
|
pXWall->triggerVector = bitReader.getBits(1);
|
||||||
pXWall->triggerTouch = bitReader.readUnsigned(1);
|
pXWall->triggerTouch = bitReader.getBits(1);
|
||||||
bitReader.readUnsigned(2);
|
bitReader.getBits(2);
|
||||||
pWall->xpan_ += bitReader.readUnsigned(8) / 256.f;
|
pWall->xpan_ += bitReader.getBits(8) / 256.f;
|
||||||
pWall->ypan_ += bitReader.readUnsigned(8) / 256.f;
|
pWall->ypan_ += bitReader.getBits(8) / 256.f;
|
||||||
pXWall->locked = bitReader.readUnsigned(1);
|
pXWall->locked = bitReader.getBits(1);
|
||||||
pXWall->dudeLockout = bitReader.readUnsigned(1);
|
pXWall->dudeLockout = bitReader.getBits(1);
|
||||||
bitReader.readUnsigned(4);
|
bitReader.getBits(4);
|
||||||
bitReader.readUnsigned(32);
|
bitReader.getBits(32);
|
||||||
pXWall->busy = IntToFixed(pXWall->state);
|
pXWall->busy = IntToFixed(pXWall->state);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -529,66 +529,66 @@ void dbLoadMap(const char* pPath, DVector3& pos, short* pAngle, sectortype** cur
|
||||||
assert(nCount <= nXSpriteSize);
|
assert(nCount <= nXSpriteSize);
|
||||||
fr.Read(pBuffer, nCount);
|
fr.Read(pBuffer, nCount);
|
||||||
BitReader bitReader(pBuffer, nCount);
|
BitReader bitReader(pBuffer, nCount);
|
||||||
/*pXSprite->reference =*/ bitReader.readSigned(14);
|
/*pXSprite->reference =*/ bitReader.getBitsSigned(14);
|
||||||
pXSprite->state = bitReader.readUnsigned(1);
|
pXSprite->state = bitReader.getBits(1);
|
||||||
pXSprite->busy = bitReader.readUnsigned(17);
|
pXSprite->busy = bitReader.getBits(17);
|
||||||
pXSprite->txID = bitReader.readUnsigned(10);
|
pXSprite->txID = bitReader.getBits(10);
|
||||||
pXSprite->rxID = bitReader.readUnsigned(10);
|
pXSprite->rxID = bitReader.getBits(10);
|
||||||
pXSprite->command = bitReader.readUnsigned(8);
|
pXSprite->command = bitReader.getBits(8);
|
||||||
pXSprite->triggerOn = bitReader.readUnsigned(1);
|
pXSprite->triggerOn = bitReader.getBits(1);
|
||||||
pXSprite->triggerOff = bitReader.readUnsigned(1);
|
pXSprite->triggerOff = bitReader.getBits(1);
|
||||||
pXSprite->wave = bitReader.readUnsigned(2);
|
pXSprite->wave = bitReader.getBits(2);
|
||||||
pXSprite->busyTime = bitReader.readUnsigned(12);
|
pXSprite->busyTime = bitReader.getBits(12);
|
||||||
pXSprite->waitTime = bitReader.readUnsigned(12);
|
pXSprite->waitTime = bitReader.getBits(12);
|
||||||
pXSprite->restState = bitReader.readUnsigned(1);
|
pXSprite->restState = bitReader.getBits(1);
|
||||||
pXSprite->Interrutable = bitReader.readUnsigned(1);
|
pXSprite->Interrutable = bitReader.getBits(1);
|
||||||
pXSprite->modernFlags = bitReader.readUnsigned(2);
|
pXSprite->modernFlags = bitReader.getBits(2);
|
||||||
pXSprite->respawnPending = bitReader.readUnsigned(2);
|
pXSprite->respawnPending = bitReader.getBits(2);
|
||||||
pXSprite->patrolstate = bitReader.readUnsigned(1);
|
pXSprite->patrolstate = bitReader.getBits(1);
|
||||||
pXSprite->lT = bitReader.readUnsigned(1);
|
pXSprite->lT = bitReader.getBits(1);
|
||||||
pXSprite->dropMsg = bitReader.readUnsigned(8);
|
pXSprite->dropMsg = bitReader.getBits(8);
|
||||||
pXSprite->Decoupled = bitReader.readUnsigned(1);
|
pXSprite->Decoupled = bitReader.getBits(1);
|
||||||
pXSprite->triggerOnce = bitReader.readUnsigned(1);
|
pXSprite->triggerOnce = bitReader.getBits(1);
|
||||||
pXSprite->isTriggered = bitReader.readUnsigned(1);
|
pXSprite->isTriggered = bitReader.getBits(1);
|
||||||
pXSprite->key = bitReader.readUnsigned(3);
|
pXSprite->key = bitReader.getBits(3);
|
||||||
pXSprite->Push = bitReader.readUnsigned(1);
|
pXSprite->Push = bitReader.getBits(1);
|
||||||
pXSprite->Vector = bitReader.readUnsigned(1);
|
pXSprite->Vector = bitReader.getBits(1);
|
||||||
pXSprite->Impact = bitReader.readUnsigned(1);
|
pXSprite->Impact = bitReader.getBits(1);
|
||||||
pXSprite->Pickup = bitReader.readUnsigned(1);
|
pXSprite->Pickup = bitReader.getBits(1);
|
||||||
pXSprite->Touch = bitReader.readUnsigned(1);
|
pXSprite->Touch = bitReader.getBits(1);
|
||||||
pXSprite->Sight = bitReader.readUnsigned(1);
|
pXSprite->Sight = bitReader.getBits(1);
|
||||||
pXSprite->Proximity = bitReader.readUnsigned(1);
|
pXSprite->Proximity = bitReader.getBits(1);
|
||||||
pXSprite->sightstuff = bitReader.readUnsigned(2);
|
pXSprite->sightstuff = bitReader.getBits(2);
|
||||||
pXSprite->lSkill = bitReader.readUnsigned(5);
|
pXSprite->lSkill = bitReader.getBits(5);
|
||||||
pXSprite->lS = bitReader.readUnsigned(1);
|
pXSprite->lS = bitReader.getBits(1);
|
||||||
pXSprite->lB = bitReader.readUnsigned(1);
|
pXSprite->lB = bitReader.getBits(1);
|
||||||
pXSprite->lC = bitReader.readUnsigned(1);
|
pXSprite->lC = bitReader.getBits(1);
|
||||||
pXSprite->DudeLockout = bitReader.readUnsigned(1);
|
pXSprite->DudeLockout = bitReader.getBits(1);
|
||||||
pXSprite->data1 = bitReader.readSigned(16);
|
pXSprite->data1 = bitReader.getBitsSigned(16);
|
||||||
pXSprite->data2 = bitReader.readSigned(16);
|
pXSprite->data2 = bitReader.getBitsSigned(16);
|
||||||
pXSprite->data3 = bitReader.readSigned(16);
|
pXSprite->data3 = bitReader.getBitsSigned(16);
|
||||||
pXSprite->goalAng = mapangle(bitReader.readUnsigned(11));
|
pXSprite->goalAng = mapangle(bitReader.getBits(11));
|
||||||
pXSprite->dodgeDir = bitReader.readSigned(2);
|
pXSprite->dodgeDir = bitReader.getBitsSigned(2);
|
||||||
pXSprite->locked = bitReader.readUnsigned(1);
|
pXSprite->locked = bitReader.getBits(1);
|
||||||
pXSprite->medium = bitReader.readUnsigned(2);
|
pXSprite->medium = bitReader.getBits(2);
|
||||||
pXSprite->respawn = bitReader.readUnsigned(2);
|
pXSprite->respawn = bitReader.getBits(2);
|
||||||
pXSprite->data4 = bitReader.readUnsigned(16);
|
pXSprite->data4 = bitReader.getBits(16);
|
||||||
pXSprite->patrolturndelay = bitReader.readUnsigned(6);
|
pXSprite->patrolturndelay = bitReader.getBits(6);
|
||||||
pXSprite->lockMsg = bitReader.readUnsigned(8);
|
pXSprite->lockMsg = bitReader.getBits(8);
|
||||||
pXSprite->health = bitReader.readUnsigned(12);
|
pXSprite->health = bitReader.getBits(12);
|
||||||
pXSprite->dudeDeaf = bitReader.readUnsigned(1);
|
pXSprite->dudeDeaf = bitReader.getBits(1);
|
||||||
pXSprite->dudeAmbush = bitReader.readUnsigned(1);
|
pXSprite->dudeAmbush = bitReader.getBits(1);
|
||||||
pXSprite->dudeGuard = bitReader.readUnsigned(1);
|
pXSprite->dudeGuard = bitReader.getBits(1);
|
||||||
pXSprite->dudeFlag4 = bitReader.readUnsigned(1);
|
pXSprite->dudeFlag4 = bitReader.getBits(1);
|
||||||
/*pXSprite->target_i = */ bitReader.readSigned(16);
|
/*pXSprite->target_i = */ bitReader.getBitsSigned(16);
|
||||||
int tx = bitReader.readSigned(32);
|
int tx = bitReader.getBitsSigned(32);
|
||||||
int ty = bitReader.readSigned(32);
|
int ty = bitReader.getBitsSigned(32);
|
||||||
int tz = bitReader.readSigned(32);
|
int tz = bitReader.getBitsSigned(32);
|
||||||
pXSprite->TargetPos = {tx * maptoworld, ty * maptoworld, tz * zmaptoworld };
|
pXSprite->TargetPos = {tx * maptoworld, ty * maptoworld, tz * zmaptoworld };
|
||||||
pXSprite->burnTime = bitReader.readUnsigned(16);
|
pXSprite->burnTime = bitReader.getBits(16);
|
||||||
/*pXSprite->burnSource =*/ bitReader.readSigned(16);
|
/*pXSprite->burnSource =*/ bitReader.getBitsSigned(16);
|
||||||
pXSprite->height = bitReader.readUnsigned(16);
|
pXSprite->height = bitReader.getBits(16);
|
||||||
pXSprite->stateTimer = bitReader.readUnsigned(16);
|
pXSprite->stateTimer = bitReader.getBits(16);
|
||||||
pXSprite->aiState = NULL;
|
pXSprite->aiState = NULL;
|
||||||
bitReader.skipBits(32);
|
bitReader.skipBits(32);
|
||||||
pXSprite->busy = IntToFixed(pXSprite->state);
|
pXSprite->busy = IntToFixed(pXSprite->state);
|
||||||
|
|
|
@ -28,17 +28,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
BEGIN_BLD_NS
|
BEGIN_BLD_NS
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
kAttrMove = 0x0001, // is affected by movement physics
|
|
||||||
kAttrGravity = 0x0002, // is affected by gravity
|
|
||||||
kAttrFalling = 0x0004, // in z motion
|
|
||||||
kAttrAiming = 0x0008,
|
|
||||||
kAttrRespawn = 0x0010,
|
|
||||||
kAttrFree = 0x0020,
|
|
||||||
kAttrSmoke = 0x0100, // receives tsprite smoke/steam
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "callback.h"
|
|
||||||
|
|
||||||
BEGIN_BLD_NS
|
BEGIN_BLD_NS
|
||||||
|
|
||||||
|
|
|
@ -1,61 +1,51 @@
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
* Copyright (C) 2018, 2022 nukeykt
|
||||||
Copyright (C) 2019 Nuke.YKT
|
* Copyright (C) 2020-2023 Christoph Oelckers
|
||||||
Copyright (C) 2020 - Christoph Oelckers
|
*
|
||||||
|
* This file is part of Raze
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
This file is part of Raze
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
See the GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
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"
|
#include "ns.h"
|
||||||
#include "filesystem.h"
|
#include "filesystem.h"
|
||||||
#include "tarray.h"
|
#include "tarray.h"
|
||||||
|
#include "files.h"
|
||||||
|
|
||||||
#include "build.h"
|
#include "build.h"
|
||||||
|
|
||||||
#include "blood.h"
|
#include "blood.h"
|
||||||
#include "files.h"
|
|
||||||
#include "eventq.h"
|
#include "eventq.h"
|
||||||
#include "callback.h"
|
|
||||||
|
|
||||||
|
|
||||||
BEGIN_BLD_NS
|
BEGIN_BLD_NS
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
FMemArena seqcache; // also used by QAVs.
|
||||||
//
|
static TMap<int64_t, Seq*> sequences;
|
||||||
//
|
|
||||||
//
|
|
||||||
//---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void Seq::Precache(int palette)
|
//---------------------------------------------------------------------------
|
||||||
{
|
//
|
||||||
if (memcmp(signature, "SEQ\x1a", 4) != 0)
|
//
|
||||||
I_Error("Invalid sequence");
|
//
|
||||||
if ((version & 0xff00) != 0x300)
|
//---------------------------------------------------------------------------
|
||||||
I_Error("Obsolete sequence version");
|
|
||||||
for (int i = 0; i < nFrames; i++)
|
|
||||||
tilePrecacheTile(seqGetTexture(&frames[i]), -1, palette);
|
|
||||||
}
|
|
||||||
|
|
||||||
void seqPrecacheId(FName name, int id, int palette)
|
void seqPrecacheId(FName name, int id, int palette)
|
||||||
{
|
{
|
||||||
auto pSeq = getSequence(name, id);
|
if (auto pSeq = getSequence(name, id))
|
||||||
if (pSeq) pSeq->Precache(palette);
|
{
|
||||||
|
for (const auto& frame : pSeq->frames)
|
||||||
|
tilePrecacheTile(frame.texture, -1, palette);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -64,12 +54,10 @@ void seqPrecacheId(FName name, int id, int palette)
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void UpdateCeiling(sectortype* pSector, SEQFRAME* pFrame)
|
template<class T, class U> void SetFlag(T& flagvar, U bit, bool condition)
|
||||||
{
|
{
|
||||||
pSector->setceilingtexture(seqGetTexture(pFrame));
|
if (condition) flagvar |= bit;
|
||||||
pSector->ceilingshade = pFrame->shade;
|
else flagvar &= ~bit;
|
||||||
if (pFrame->palette)
|
|
||||||
pSector->ceilingpal = pFrame->palette;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -78,12 +66,49 @@ void UpdateCeiling(sectortype* pSector, SEQFRAME* pFrame)
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void UpdateFloor(sectortype* pSector, SEQFRAME* pFrame)
|
void UpdateSprite(DBloodActor* actor, SeqFrame* pFrame)
|
||||||
{
|
{
|
||||||
pSector->setfloortexture(seqGetTexture(pFrame));
|
assert(actor->hasX());
|
||||||
pSector->floorshade = pFrame->shade;
|
if (actor->spr.flags & kPhysGravity)
|
||||||
if (pFrame->palette)
|
{
|
||||||
pSector->floorpal = pFrame->palette;
|
auto atex = TexMan.GetGameTexture(actor->spr.spritetexture());
|
||||||
|
auto stex = TexMan.GetGameTexture(pFrame->texture);
|
||||||
|
if (atex->GetDisplayHeight() != stex->GetDisplayHeight() || atex->GetDisplayTopOffset() != stex->GetDisplayTopOffset()
|
||||||
|
|| (pFrame->scale.Y && pFrame->scale.Y != actor->spr.scale.Y))
|
||||||
|
actor->spr.flags |= kPhysFalling;
|
||||||
|
}
|
||||||
|
actor->spr.setspritetexture(pFrame->texture);
|
||||||
|
|
||||||
|
if (pFrame->palette) actor->spr.pal = pFrame->palette;
|
||||||
|
actor->spr.shade = pFrame->shade;
|
||||||
|
|
||||||
|
double scale = VanillaMode() ? 0 : actor->xspr.scale / 256.; // SEQ size scaling (nnext feature)
|
||||||
|
if (pFrame->scale.X)
|
||||||
|
{
|
||||||
|
double s = pFrame->scale.X;
|
||||||
|
if (scale) s = clamp(s * scale, 0., 4.); // Q: Do we need the clamp to 4 here?
|
||||||
|
actor->spr.scale.X = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pFrame->scale.Y)
|
||||||
|
{
|
||||||
|
double s = pFrame->scale.Y * REPEAT_SCALE;
|
||||||
|
if (scale) s = clamp(s * scale, 0., 4.);
|
||||||
|
actor->spr.scale.Y = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetFlag(actor->spr.cstat, CSTAT_SPRITE_TRANSLUCENT, pFrame->transparent);
|
||||||
|
|
||||||
|
SetFlag(actor->spr.cstat, CSTAT_SPRITE_TRANS_FLIP, pFrame->transparent2);
|
||||||
|
SetFlag(actor->spr.cstat, CSTAT_SPRITE_BLOCK, pFrame->blockable);
|
||||||
|
SetFlag(actor->spr.cstat, CSTAT_SPRITE_BLOCK_HITSCAN, pFrame->hittable);
|
||||||
|
SetFlag(actor->spr.cstat, CSTAT_SPRITE_INVISIBLE, pFrame->invisible);
|
||||||
|
SetFlag(actor->spr.cstat, CSTAT_SPRITE_BLOOD_PUSHABLE, pFrame->pushable);
|
||||||
|
|
||||||
|
SetFlag(actor->spr.flags, kHitagSmoke, pFrame->smoke);
|
||||||
|
SetFlag(actor->spr.flags, kHitagAutoAim, pFrame->aiming);
|
||||||
|
SetFlag(actor->spr.flags, kHitagFlipX, pFrame->flipx);
|
||||||
|
SetFlag(actor->spr.flags, kHitagFlipY, pFrame->flipy);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -92,28 +117,16 @@ void UpdateFloor(sectortype* pSector, SEQFRAME* pFrame)
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void UpdateWall(walltype* pWall, SEQFRAME* pFrame)
|
void UpdateWall(walltype* pWall, SeqFrame* pFrame)
|
||||||
{
|
{
|
||||||
assert(pWall->hasX());
|
assert(pWall->hasX());
|
||||||
pWall->setwalltexture(seqGetTexture(pFrame));
|
pWall->setwalltexture(pFrame->texture);
|
||||||
if (pFrame->palette)
|
if (pFrame->palette) pWall->pal = pFrame->palette;
|
||||||
pWall->pal = pFrame->palette;
|
|
||||||
if (pFrame->transparent)
|
SetFlag(pWall->cstat, CSTAT_WALL_TRANSLUCENT, pFrame->transparent);
|
||||||
pWall->cstat |= CSTAT_WALL_TRANSLUCENT;
|
SetFlag(pWall->cstat, CSTAT_WALL_TRANS_FLIP, pFrame->transparent2);
|
||||||
else
|
SetFlag(pWall->cstat, CSTAT_WALL_BLOCK, pFrame->blockable);
|
||||||
pWall->cstat &= ~CSTAT_WALL_TRANSLUCENT;
|
SetFlag(pWall->cstat, CSTAT_WALL_BLOCK_HITSCAN, pFrame->hittable);
|
||||||
if (pFrame->transparent2)
|
|
||||||
pWall->cstat |= CSTAT_WALL_TRANS_FLIP;
|
|
||||||
else
|
|
||||||
pWall->cstat &= ~CSTAT_WALL_TRANS_FLIP;
|
|
||||||
if (pFrame->blockable)
|
|
||||||
pWall->cstat |= CSTAT_WALL_BLOCK;
|
|
||||||
else
|
|
||||||
pWall->cstat &= ~CSTAT_WALL_BLOCK;
|
|
||||||
if (pFrame->hittable)
|
|
||||||
pWall->cstat |= CSTAT_WALL_BLOCK_HITSCAN;
|
|
||||||
else
|
|
||||||
pWall->cstat &= ~CSTAT_WALL_BLOCK_HITSCAN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -122,135 +135,50 @@ void UpdateWall(walltype* pWall, SEQFRAME* pFrame)
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
void UpdateMasked(walltype* pWall, SEQFRAME* pFrame)
|
void UpdateFloor(sectortype* pSector, SeqFrame* pFrame)
|
||||||
|
{
|
||||||
|
pSector->setfloortexture(pFrame->texture);
|
||||||
|
pSector->floorshade = pFrame->shade;
|
||||||
|
if (pFrame->palette) pSector->floorpal = pFrame->palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void UpdateCeiling(sectortype* pSector, SeqFrame* pFrame)
|
||||||
|
{
|
||||||
|
pSector->setceilingtexture(pFrame->texture);
|
||||||
|
pSector->ceilingshade = pFrame->shade;
|
||||||
|
if (pFrame->palette) pSector->ceilingpal = pFrame->palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void UpdateMasked(walltype* pWall, SeqFrame* pFrame)
|
||||||
{
|
{
|
||||||
assert(pWall->hasX());
|
assert(pWall->hasX());
|
||||||
walltype* pWallNext = pWall->nextWall();
|
walltype* pWallNext = pWall->nextWall();
|
||||||
auto texid = seqGetTexture(pFrame);
|
auto texid = pFrame->texture;
|
||||||
pWall->setovertexture(texid);
|
pWall->setovertexture(texid);
|
||||||
pWallNext->setovertexture(texid);
|
pWallNext->setovertexture(texid);
|
||||||
if (pFrame->palette)
|
if (pFrame->palette)
|
||||||
pWall->pal = pWallNext->pal = pFrame->palette;
|
pWall->pal = pWallNext->pal = pFrame->palette;
|
||||||
if (pFrame->transparent)
|
|
||||||
{
|
|
||||||
pWall->cstat |= CSTAT_WALL_TRANSLUCENT;
|
|
||||||
pWallNext->cstat |= CSTAT_WALL_TRANSLUCENT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pWall->cstat &= ~CSTAT_WALL_TRANSLUCENT;
|
|
||||||
pWallNext->cstat &= ~CSTAT_WALL_TRANSLUCENT;
|
|
||||||
}
|
|
||||||
if (pFrame->transparent2)
|
|
||||||
{
|
|
||||||
pWall->cstat |= CSTAT_WALL_TRANS_FLIP;
|
|
||||||
pWallNext->cstat |= CSTAT_WALL_TRANS_FLIP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pWall->cstat &= ~CSTAT_WALL_TRANS_FLIP;
|
|
||||||
pWallNext->cstat &= ~CSTAT_WALL_TRANS_FLIP;
|
|
||||||
}
|
|
||||||
if (pFrame->blockable)
|
|
||||||
{
|
|
||||||
pWall->cstat |= CSTAT_WALL_BLOCK;
|
|
||||||
pWallNext->cstat |= CSTAT_WALL_BLOCK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pWall->cstat &= ~CSTAT_WALL_BLOCK;
|
|
||||||
pWallNext->cstat &= ~CSTAT_WALL_BLOCK;
|
|
||||||
}
|
|
||||||
if (pFrame->hittable)
|
|
||||||
{
|
|
||||||
pWall->cstat |= CSTAT_WALL_BLOCK_HITSCAN;
|
|
||||||
pWallNext->cstat |= CSTAT_WALL_BLOCK_HITSCAN;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pWall->cstat &= ~CSTAT_WALL_BLOCK_HITSCAN;
|
|
||||||
pWallNext->cstat &= ~CSTAT_WALL_BLOCK_HITSCAN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
SetFlag(pWall->cstat, CSTAT_WALL_TRANSLUCENT, pFrame->transparent);
|
||||||
//
|
SetFlag(pWallNext->cstat, CSTAT_WALL_TRANSLUCENT, pFrame->transparent);
|
||||||
//
|
SetFlag(pWall->cstat, CSTAT_WALL_TRANS_FLIP, pFrame->transparent2);
|
||||||
//
|
SetFlag(pWallNext->cstat, CSTAT_WALL_TRANS_FLIP, pFrame->transparent2);
|
||||||
//---------------------------------------------------------------------------
|
SetFlag(pWall->cstat, CSTAT_WALL_BLOCK, pFrame->blockable);
|
||||||
|
SetFlag(pWallNext->cstat, CSTAT_WALL_BLOCK, pFrame->blockable);
|
||||||
void UpdateSprite(DBloodActor* actor, SEQFRAME* pFrame)
|
SetFlag(pWall->cstat, CSTAT_WALL_BLOCK_HITSCAN, pFrame->hittable);
|
||||||
{
|
SetFlag(pWallNext->cstat, CSTAT_WALL_BLOCK_HITSCAN, pFrame->hittable);
|
||||||
assert(actor->hasX());
|
|
||||||
if (actor->spr.flags & 2)
|
|
||||||
{
|
|
||||||
auto atex = TexMan.GetGameTexture(actor->spr.spritetexture());
|
|
||||||
auto stex = TexMan.GetGameTexture(seqGetTexture(pFrame));
|
|
||||||
if (atex->GetDisplayHeight() != stex->GetDisplayHeight() || atex->GetDisplayTopOffset() != stex->GetDisplayTopOffset()
|
|
||||||
|| (pFrame->scaley && pFrame->scaley != int(actor->spr.scale.Y * INV_REPEAT_SCALE)))
|
|
||||||
actor->spr.flags |= 4;
|
|
||||||
}
|
|
||||||
actor->spr.setspritetexture(seqGetTexture(pFrame));
|
|
||||||
if (pFrame->palette)
|
|
||||||
actor->spr.pal = pFrame->palette;
|
|
||||||
actor->spr.shade = pFrame->shade;
|
|
||||||
|
|
||||||
int scale = actor->xspr.scale; // SEQ size scaling
|
|
||||||
if (pFrame->scalex)
|
|
||||||
{
|
|
||||||
int s;
|
|
||||||
if (scale) s = ClipRange(MulScale(pFrame->scalex, scale, 8), 0, 255);
|
|
||||||
else s = pFrame->scalex;
|
|
||||||
actor->spr.scale.X = (s * REPEAT_SCALE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pFrame->scaley) {
|
|
||||||
int s;
|
|
||||||
if (scale) s = ClipRange(MulScale(pFrame->scaley, scale, 8), 0, 255);
|
|
||||||
else s = pFrame->scaley;
|
|
||||||
actor->spr.scale.Y = (s * REPEAT_SCALE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pFrame->transparent)
|
|
||||||
actor->spr.cstat |= CSTAT_SPRITE_TRANSLUCENT;
|
|
||||||
else
|
|
||||||
actor->spr.cstat &= ~CSTAT_SPRITE_TRANSLUCENT;
|
|
||||||
if (pFrame->transparent2)
|
|
||||||
actor->spr.cstat |= CSTAT_SPRITE_TRANS_FLIP;
|
|
||||||
else
|
|
||||||
actor->spr.cstat &= ~CSTAT_SPRITE_TRANS_FLIP;
|
|
||||||
if (pFrame->blockable)
|
|
||||||
actor->spr.cstat |= CSTAT_SPRITE_BLOCK;
|
|
||||||
else
|
|
||||||
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK;
|
|
||||||
if (pFrame->hittable)
|
|
||||||
actor->spr.cstat |= CSTAT_SPRITE_BLOCK_HITSCAN;
|
|
||||||
else
|
|
||||||
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_HITSCAN;
|
|
||||||
if (pFrame->invisible)
|
|
||||||
actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
|
|
||||||
else
|
|
||||||
actor->spr.cstat &= ~CSTAT_SPRITE_INVISIBLE;
|
|
||||||
if (pFrame->pushable)
|
|
||||||
actor->spr.cstat |= CSTAT_SPRITE_BLOOD_BIT1;
|
|
||||||
else
|
|
||||||
actor->spr.cstat &= ~CSTAT_SPRITE_BLOOD_BIT1;
|
|
||||||
if (pFrame->smoke)
|
|
||||||
actor->spr.flags |= 256;
|
|
||||||
else
|
|
||||||
actor->spr.flags &= ~256;
|
|
||||||
if (pFrame->aiming)
|
|
||||||
actor->spr.flags |= 8;
|
|
||||||
else
|
|
||||||
actor->spr.flags &= ~8;
|
|
||||||
if (pFrame->flipx)
|
|
||||||
actor->spr.flags |= 1024;
|
|
||||||
else
|
|
||||||
actor->spr.flags &= ~1024;
|
|
||||||
if (pFrame->flipy)
|
|
||||||
actor->spr.flags |= 2048;
|
|
||||||
else
|
|
||||||
actor->spr.flags &= ~2048;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -261,7 +189,7 @@ void UpdateSprite(DBloodActor* actor, SEQFRAME* pFrame)
|
||||||
|
|
||||||
void SEQINST::Update()
|
void SEQINST::Update()
|
||||||
{
|
{
|
||||||
assert(frameIndex < pSequence->nFrames);
|
assert(frameIndex < pSequence->frames.Size());
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case SS_WALL:
|
case SS_WALL:
|
||||||
|
@ -282,50 +210,22 @@ void SEQINST::Update()
|
||||||
auto actor = target.actor();
|
auto actor = target.actor();
|
||||||
if (!actor) break;
|
if (!actor) break;
|
||||||
UpdateSprite(actor, &pSequence->frames[frameIndex]);
|
UpdateSprite(actor, &pSequence->frames[frameIndex]);
|
||||||
if (pSequence->frames[frameIndex].playsound) {
|
sfxPlay3DSound(actor, pSequence->getSound(frameIndex), -1, 0);
|
||||||
|
|
||||||
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(actor, sound, -1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// by NoOne: add surfaceSound trigger feature
|
|
||||||
if (!VanillaMode() && pSequence->frames[frameIndex].surfaceSound && actor->vel.Z == 0 && actor->vel.X != 0) {
|
|
||||||
|
|
||||||
|
// NBlood's surfaceSound trigger feature - needs to be reviewed because this never checks if the actor touches the floor!
|
||||||
|
if (!VanillaMode() && pSequence->frames[frameIndex].surfaceSound && actor->vel.Z == 0 && actor->vel.X != 0)
|
||||||
|
{
|
||||||
if (actor->sector()->upperLink) break; // don't play surface sound for stacked sectors
|
if (actor->sector()->upperLink) break; // don't play surface sound for stacked sectors
|
||||||
int surf = GetExtInfo(actor->sector()->floortexture).surftype;
|
int surf = tilesurface(actor->sector()->floortexture);
|
||||||
if (!surf) break;
|
if (surf <= kSurfNone || surf >= kSurfMax) break;
|
||||||
static int surfSfxMove[15][4] = {
|
|
||||||
/* {snd1, snd2, gameVolume, myVolume} */
|
|
||||||
{800,801,80,25},
|
|
||||||
{802,803,80,25},
|
|
||||||
{804,805,80,25},
|
|
||||||
{806,807,80,25},
|
|
||||||
{808,809,80,25},
|
|
||||||
{810,811,80,25},
|
|
||||||
{812,813,80,25},
|
|
||||||
{814,815,80,25},
|
|
||||||
{816,817,80,25},
|
|
||||||
{818,819,80,25},
|
|
||||||
{820,821,80,25},
|
|
||||||
{822,823,80,25},
|
|
||||||
{824,825,80,25},
|
|
||||||
{826,827,80,25},
|
|
||||||
{828,829,80,25},
|
|
||||||
};
|
|
||||||
|
|
||||||
int sndId = surfSfxMove[surf][Random(2)];
|
int sndId = 800 + surf * 2 + Random(2);
|
||||||
auto snd = soundEngine->FindSoundByResID(sndId);
|
auto snd = soundEngine->FindSoundByResID(sndId);
|
||||||
if (snd.isvalid())
|
if (snd.isvalid())
|
||||||
{
|
{
|
||||||
auto udata = soundEngine->GetSfx(snd);
|
auto udata = soundEngine->GetSfx(snd);
|
||||||
int relVol = udata ? udata->UserVal : 80;
|
int relVol = udata ? udata->UserVal : 80;
|
||||||
sfxPlay3DSoundVolume(actor, sndId, -1, 0, 0, (surfSfxMove[surf][2] != relVol) ? relVol : surfSfxMove[surf][3]);
|
sfxPlay3DSoundVolume(actor, snd, -1, 0, 0, (relVol != 80) ? relVol : 25); // some weird shit logic here with the volume...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -336,10 +236,9 @@ void SEQINST::Update()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all seq callbacks are for sprites, but there's no sanity checks here that what gets passed is meant to be for a sprite...
|
// all seq callbacks are for sprites, so skip for other types.
|
||||||
if (pSequence->frames[frameIndex].trigger && callback != nullptr)
|
if (type == SS_SPRITE && pSequence->frames[frameIndex].trigger && callback != nullptr)
|
||||||
{
|
{
|
||||||
assert(type == SS_SPRITE);
|
|
||||||
if (target.isActor()) callActorFunction(callback, target.actor());
|
if (target.isActor()) callActorFunction(callback, target.actor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,45 +367,77 @@ void seqKill(DBloodActor* actor)
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
static void ByteSwapSEQ(Seq* pSeq)
|
static Seq* ReadSEQ(int index)
|
||||||
{
|
{
|
||||||
pSeq->version = LittleShort(pSeq->version);
|
auto fr = fileSystem.OpenFileReader(index);
|
||||||
pSeq->nFrames = LittleShort(pSeq->nFrames);
|
if (!fr.isOpen())
|
||||||
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];
|
Printf("%s: unable to open", fileSystem.GetFileFullName(index));
|
||||||
BitReader bitReader((uint8_t*)pFrame, sizeof(SEQFRAME));
|
return nullptr;
|
||||||
SEQFRAME swapFrame;
|
|
||||||
swapFrame.tile = bitReader.readUnsigned(12);
|
|
||||||
swapFrame.transparent = bitReader.readBit();
|
|
||||||
swapFrame.transparent2 = bitReader.readBit();
|
|
||||||
swapFrame.blockable = bitReader.readBit();
|
|
||||||
swapFrame.hittable = bitReader.readBit();
|
|
||||||
swapFrame.scalex = bitReader.readUnsigned(8);
|
|
||||||
swapFrame.scaley = 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();
|
|
||||||
swapFrame.reserved = bitReader.readUnsigned(2);
|
|
||||||
*pFrame = swapFrame;
|
|
||||||
}
|
}
|
||||||
|
char header[4];
|
||||||
|
fr.Read(header, 4);
|
||||||
|
if (memcmp(&header[0], "SEQ\x1a", 4) != 0)
|
||||||
|
{
|
||||||
|
Printf("%s: Invalid sequence", fileSystem.GetFileFullName(index));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
int version = fr.ReadInt16();
|
||||||
|
if ((version & 0xff00) != 0x300)
|
||||||
|
{
|
||||||
|
Printf("%s: Obsolete sequence version", fileSystem.GetFileFullName(index));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int frames = fr.ReadUInt16();
|
||||||
|
int ticks = fr.ReadUInt16();
|
||||||
|
int soundid = fr.ReadUInt16();
|
||||||
|
int flags = fr.ReadInt32();
|
||||||
|
// allocate both buffers off our memory arena.
|
||||||
|
auto seqdata = (Seq*)seqcache.Alloc(sizeof(Seq));
|
||||||
|
seqdata->frames.Set((SeqFrame*)seqcache.Alloc(sizeof(SeqFrame) * frames), frames);
|
||||||
|
seqdata->flags = flags;
|
||||||
|
seqdata->ticksPerFrame = ticks;
|
||||||
|
seqdata->soundResId = soundid;
|
||||||
|
seqdata->soundId = soundEngine->FindSoundByResID(soundid);
|
||||||
|
|
||||||
|
|
||||||
|
for (auto& frame : seqdata->frames)
|
||||||
|
{
|
||||||
|
uint8_t framebuf[8];
|
||||||
|
fr.Read(framebuf, 8);
|
||||||
|
BitReader bitReader(framebuf, sizeof(framebuf));
|
||||||
|
int tile = bitReader.getBits(12);
|
||||||
|
frame.transparent = bitReader.getBit();
|
||||||
|
frame.transparent2 = bitReader.getBit();
|
||||||
|
frame.blockable = bitReader.getBit();
|
||||||
|
frame.hittable = bitReader.getBit();
|
||||||
|
frame.scale.X = bitReader.getBits(8) * REPEAT_SCALEF;
|
||||||
|
frame.scale.Y = bitReader.getBits(8) * REPEAT_SCALEF;
|
||||||
|
frame.shade = bitReader.getBitsSigned(8);
|
||||||
|
frame.palette = bitReader.getBits(5);
|
||||||
|
frame.trigger = bitReader.getBit();
|
||||||
|
frame.smoke = bitReader.getBit();
|
||||||
|
frame.aiming = bitReader.getBit();
|
||||||
|
frame.pushable = bitReader.getBit();
|
||||||
|
frame.playsound = bitReader.getBit();
|
||||||
|
frame.invisible = bitReader.getBit();
|
||||||
|
frame.flipx = bitReader.getBit();
|
||||||
|
frame.flipy = bitReader.getBit();
|
||||||
|
tile += bitReader.getBits(4) << 12;;
|
||||||
|
frame.soundRange = bitReader.getBits(4);
|
||||||
|
frame.surfaceSound = bitReader.getBit();
|
||||||
|
frame.texture = tileGetTextureID(tile);
|
||||||
|
}
|
||||||
|
return seqdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
FMemArena seqcache;
|
//---------------------------------------------------------------------------
|
||||||
static TMap<int64_t, Seq*> sequences;
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
Seq* getSequence(FName res_name, int res_id)
|
Seq* getSequence(FName res_name, int res_id)
|
||||||
{
|
{
|
||||||
int64_t key = ((int64_t)res_name.GetIndex() << 32) | res_id;
|
int64_t key = ((int64_t)res_name.GetIndex() << 32) | res_id;
|
||||||
|
@ -529,14 +460,13 @@ Seq* getSequence(FName res_name, int res_id)
|
||||||
|
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
{
|
{
|
||||||
|
if (res_name != NAME_None) Printf("%s: sequence not found", res_name.GetChars());
|
||||||
|
sequences.Insert(key, nullptr); // even store null entries to avoid repeated lookup for them.
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fr = fileSystem.OpenFileReader(index);
|
auto seqdata = ReadSEQ(index);
|
||||||
auto seqdata = (Seq*)seqcache.Alloc(fr.GetLength());
|
|
||||||
fr.Read(seqdata, fr.GetLength());
|
|
||||||
sequences.Insert(key, seqdata);
|
sequences.Insert(key, seqdata);
|
||||||
ByteSwapSEQ(seqdata);
|
|
||||||
return seqdata;
|
return seqdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,11 +494,11 @@ void seqSpawn_(FName name, int nSeqID, int type, const EventObject& eob, VMFunct
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pInst->pSequence = pSequence;
|
|
||||||
pInst->nSeqID = nSeqID;
|
pInst->nSeqID = nSeqID;
|
||||||
|
pInst->pSequence = pSequence;
|
||||||
pInst->nName = name;
|
pInst->nName = name;
|
||||||
pInst->callback = callback;
|
pInst->callback = callback;
|
||||||
pInst->timeCounter = (short)pSequence->ticksPerFrame;
|
pInst->timeCounter = pSequence->ticksPerFrame;
|
||||||
pInst->frameIndex = 0;
|
pInst->frameIndex = 0;
|
||||||
pInst->type = type;
|
pInst->type = type;
|
||||||
pInst->target = eob;
|
pInst->target = eob;
|
||||||
|
@ -672,7 +602,7 @@ void seqProcess(int nTicks)
|
||||||
Seq* pSeq = pInst->pSequence;
|
Seq* pSeq = pInst->pSequence;
|
||||||
auto target = pInst->target;
|
auto target = pInst->target;
|
||||||
|
|
||||||
assert(pInst->frameIndex < pSeq->nFrames);
|
assert(pInst->frameIndex < pSeq->frames.Size());
|
||||||
|
|
||||||
pInst->timeCounter -= nTicks;
|
pInst->timeCounter -= nTicks;
|
||||||
while (pInst->timeCounter < 0)
|
while (pInst->timeCounter < 0)
|
||||||
|
@ -680,7 +610,7 @@ void seqProcess(int nTicks)
|
||||||
pInst->timeCounter += pSeq->ticksPerFrame;
|
pInst->timeCounter += pSeq->ticksPerFrame;
|
||||||
++pInst->frameIndex;
|
++pInst->frameIndex;
|
||||||
|
|
||||||
if (pInst->frameIndex == pSeq->nFrames)
|
if (pInst->frameIndex == pSeq->frames.Size())
|
||||||
{
|
{
|
||||||
if (!pSeq->isLooping())
|
if (!pSeq->isLooping())
|
||||||
{
|
{
|
||||||
|
@ -693,7 +623,7 @@ void seqProcess(int nTicks)
|
||||||
if (actor)
|
if (actor)
|
||||||
{
|
{
|
||||||
evKillActor(actor);
|
evKillActor(actor);
|
||||||
if ((actor->spr.hitag & kAttrRespawn) != 0 && actor->WasDudeActor())
|
if ((actor->spr.hitag & kHitagRespawn) != 0 && actor->WasDudeActor())
|
||||||
evPostActor(actor, gGameOptions.nMonsterRespawnTime, AF(Respawn));
|
evPostActor(actor, gGameOptions.nMonsterRespawnTime, AF(Respawn));
|
||||||
else DeleteSprite(actor); // safe to not use actPostSprite here
|
else DeleteSprite(actor); // safe to not use actPostSprite here
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,65 +1,56 @@
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
* Copyright (C) 2018, 2022 nukeykt
|
||||||
Copyright (C) 2019 Nuke.YKT
|
* Copyright (C) 2020-2023 Christoph Oelckers
|
||||||
|
*
|
||||||
This file is part of NBlood.
|
* This file is part of Raze
|
||||||
|
*
|
||||||
NBlood is free software; you can redistribute it and/or
|
* This program 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
|
||||||
as published by the Free Software Foundation.
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
This program is distributed in the hope that it will be useful,
|
*
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* This program is distributed in the hope that it will be useful,
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
See the GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
You should have received a copy of the GNU General Public License
|
*/
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "common_game.h"
|
||||||
BEGIN_BLD_NS
|
BEGIN_BLD_NS
|
||||||
|
|
||||||
|
|
||||||
struct SEQFRAME
|
struct SeqFrame
|
||||||
{
|
{
|
||||||
unsigned int tile : 12;
|
FVector2 scale;
|
||||||
|
FTextureID texture;
|
||||||
|
uint8_t palette;
|
||||||
|
int8_t shade;
|
||||||
|
int8_t soundRange;
|
||||||
unsigned int transparent : 1;
|
unsigned int transparent : 1;
|
||||||
unsigned int transparent2 : 1;
|
unsigned int transparent2 : 1;
|
||||||
unsigned int blockable : 1;
|
unsigned int blockable : 1;
|
||||||
unsigned int hittable : 1;
|
unsigned int hittable : 1;
|
||||||
unsigned int scalex : 8;
|
|
||||||
unsigned int scaley : 8;
|
|
||||||
signed int shade : 8;
|
|
||||||
unsigned int palette : 5;
|
|
||||||
unsigned int trigger : 1;
|
unsigned int trigger : 1;
|
||||||
unsigned int smoke : 1;
|
unsigned int smoke : 1;
|
||||||
unsigned int aiming : 1;
|
unsigned int aiming : 1;
|
||||||
unsigned int pushable : 1;
|
unsigned int pushable : 1;
|
||||||
unsigned int playsound : 1;
|
unsigned int playsound : 1;
|
||||||
unsigned int invisible : 1;// invisible
|
unsigned int invisible : 1;
|
||||||
unsigned int flipx : 1;
|
unsigned int flipx : 1;
|
||||||
unsigned int flipy : 1;
|
unsigned int flipy : 1;
|
||||||
unsigned int tile2 : 4;
|
unsigned int surfaceSound : 1; // (by NoOne) trigger surface sound when moving / touching
|
||||||
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 reserved : 2;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Seq {
|
struct Seq
|
||||||
char signature[4];
|
{
|
||||||
int16_t version;
|
TArrayView<SeqFrame> frames;
|
||||||
int16_t nFrames;
|
int ticksPerFrame;
|
||||||
int16_t ticksPerFrame;
|
FSoundID soundId;
|
||||||
int16_t soundId;
|
int soundResId; // still needed for the soundRange feature
|
||||||
int flags;
|
int flags;
|
||||||
SEQFRAME frames[1];
|
|
||||||
void Precache(int palette);
|
|
||||||
|
|
||||||
bool isLooping()
|
bool isLooping()
|
||||||
{
|
{
|
||||||
|
@ -70,6 +61,15 @@ struct Seq {
|
||||||
{
|
{
|
||||||
return (flags & 2) != 0;
|
return (flags & 2) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSoundID getSound(int frame)
|
||||||
|
{
|
||||||
|
if (!frames[frame].playsound) return NO_SOUND;
|
||||||
|
int range = frames[frame].soundRange;
|
||||||
|
if (VanillaMode() || range <= 0) return soundId;
|
||||||
|
return soundEngine->FindSoundByResID(soundResId + Random(max(2, range)));
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DBloodActor;
|
class DBloodActor;
|
||||||
|
@ -77,21 +77,16 @@ struct SEQINST
|
||||||
{
|
{
|
||||||
Seq* pSequence;
|
Seq* pSequence;
|
||||||
EventObject target;
|
EventObject target;
|
||||||
int type;
|
VMFunction* callback;
|
||||||
|
|
||||||
|
int type;
|
||||||
int nSeqID; // only one of these two may be set
|
int nSeqID; // only one of these two may be set
|
||||||
FName nName;
|
FName nName;
|
||||||
VMFunction* callback;
|
|
||||||
int16_t timeCounter;
|
int16_t timeCounter;
|
||||||
uint8_t frameIndex;
|
uint16_t frameIndex;
|
||||||
void Update();
|
void Update();
|
||||||
};
|
};
|
||||||
|
|
||||||
inline FTextureID seqGetTexture(SEQFRAME* pFrame)
|
|
||||||
{
|
|
||||||
return tileGetTextureID(pFrame->tile + (pFrame->tile2 << 12));
|
|
||||||
}
|
|
||||||
|
|
||||||
void seqPrecacheId(FName name, int id, int palette);
|
void seqPrecacheId(FName name, int id, int palette);
|
||||||
|
|
||||||
inline void seqPrecacheId(int id, int palette)
|
inline void seqPrecacheId(int id, int palette)
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
BEGIN_BLD_NS
|
|
||||||
|
|
||||||
|
|
||||||
END_BLD_NS
|
|
|
@ -2395,7 +2395,7 @@ void trInit(TArray<DBloodActor*>& actors)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (actor->xspr.Vector) actor->spr.cstat |= CSTAT_SPRITE_BLOCK_HITSCAN;
|
if (actor->xspr.Vector) actor->spr.cstat |= CSTAT_SPRITE_BLOCK_HITSCAN;
|
||||||
if (actor->xspr.Push) actor->spr.cstat |= CSTAT_SPRITE_BLOOD_BIT1;
|
if (actor->xspr.Push) actor->spr.cstat |= CSTAT_SPRITE_BLOOD_PUSHABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1997,7 +1997,7 @@ void AltFireLifeLeech(int, DBloodPlayer* pPlayer)
|
||||||
auto missile = playerFireThing(pPlayer, 0, -4730 / 65536., kThingDroppedLifeLeech, 1.6);
|
auto missile = playerFireThing(pPlayer, 0, -4730 / 65536., kThingDroppedLifeLeech, 1.6);
|
||||||
if (missile)
|
if (missile)
|
||||||
{
|
{
|
||||||
missile->spr.cstat |= CSTAT_SPRITE_BLOOD_BIT1;
|
missile->spr.cstat |= CSTAT_SPRITE_BLOOD_PUSHABLE;
|
||||||
missile->xspr.Push = 1;
|
missile->xspr.Push = 1;
|
||||||
missile->xspr.Proximity = 1;
|
missile->xspr.Proximity = 1;
|
||||||
missile->xspr.DudeLockout = 1;
|
missile->xspr.DudeLockout = 1;
|
||||||
|
|
Loading…
Reference in a new issue