mirror of
https://github.com/DrBeef/Raze.git
synced 2025-03-28 20:00:44 +00:00
- migrated the actors to DObjects.
No GC yet, only the classes have been altered and some GC-related features been added. Full switchover will require adding GC support to all data in the game.
This commit is contained in:
parent
8606045689
commit
588f88c9cc
29 changed files with 209 additions and 184 deletions
|
@ -395,9 +395,11 @@ int DeleteActor(DCoreActor* actor)
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
// code below will go away or be changed once
|
||||
// we can use real DObject life cycle management.
|
||||
//
|
||||
//==========================================================================
|
||||
static DCoreActor* actorArray[16384];
|
||||
|
||||
void InitSpriteLists()
|
||||
{
|
||||
|
@ -445,3 +447,25 @@ void SetActorZ(DCoreActor* actor, const vec3_t* newpos)
|
|||
}
|
||||
|
||||
|
||||
IMPLEMENT_CLASS(DCoreActor, false, false)
|
||||
|
||||
size_t DCoreActor::PropagateMark()
|
||||
{
|
||||
GC::Mark(prevStat);
|
||||
GC::Mark(nextStat);
|
||||
GC::Mark(prevSect);
|
||||
GC::Mark(nextSect);
|
||||
return 4 + Super::PropagateMark();
|
||||
}
|
||||
|
||||
void SetupActors(PClass* clstype)
|
||||
{
|
||||
// this is temporary until we have added proper tracking to all pointers in the games.
|
||||
// Until then we have to keep a static array of actors to avoid stale references to deallocated memory.
|
||||
for (int i = 0; i < 16384; i++)
|
||||
{
|
||||
actorArray[i] = static_cast<DCoreActor*>(clstype->CreateNew());
|
||||
actorArray[i]->index = i;
|
||||
actorArray[i]->Release(); // no GC for this static array.
|
||||
}
|
||||
}
|
|
@ -3,11 +3,14 @@
|
|||
#include <stdint.h>
|
||||
#include "build.h"
|
||||
|
||||
class DCoreActor
|
||||
class DCoreActor : public DObject
|
||||
{
|
||||
DECLARE_CLASS(DCoreActor, DObject)
|
||||
HAS_OBJECT_POINTERS
|
||||
// common part of the game actors
|
||||
protected:
|
||||
int index;
|
||||
//protected:
|
||||
public:
|
||||
int index; // this will go away very soon.
|
||||
|
||||
public:
|
||||
|
||||
|
@ -21,8 +24,11 @@ public:
|
|||
spriteext_t sprext;
|
||||
spritesmooth_t spsmooth;
|
||||
|
||||
|
||||
DCoreActor() = default;
|
||||
virtual ~DCoreActor() = default;
|
||||
DCoreActor(const DCoreActor& other) = delete; // we also do not want to allow copies.
|
||||
DCoreActor& operator=(const DCoreActor& other) = delete;
|
||||
|
||||
virtual void Serialize(FSerializer& arc);
|
||||
// This may only be called when all actor lists are clean.
|
||||
virtual void ClearContent()
|
||||
|
@ -33,6 +39,8 @@ public:
|
|||
spr = {};
|
||||
}
|
||||
|
||||
size_t PropagateMark() override;
|
||||
|
||||
bool exists() const
|
||||
{
|
||||
return (unsigned)s().statnum < MAXSTATUS;
|
||||
|
@ -93,7 +101,6 @@ public:
|
|||
};
|
||||
|
||||
// holds pointers to the game-side actors.
|
||||
inline DCoreActor* actorArray[16384];
|
||||
extern TArray<sectortype> sector;
|
||||
extern TArray<walltype> wall;
|
||||
|
||||
|
@ -115,14 +122,6 @@ enum EHitBits
|
|||
|
||||
};
|
||||
|
||||
inline FSerializer& Serialize(FSerializer& arc, const char* keyname, DCoreActor*& w, DCoreActor** def)
|
||||
{
|
||||
int index = w ? w->GetSpriteIndex() : -1;
|
||||
Serialize(arc, keyname, index, nullptr);
|
||||
if (arc.isReading()) w = index == -1 ? nullptr : actorArray[index];
|
||||
return arc;
|
||||
}
|
||||
|
||||
// This serves as input/output for all functions dealing with collisions, hits, etc.
|
||||
// Not all utilities use all variables.
|
||||
struct HitInfoBase
|
||||
|
@ -222,7 +221,22 @@ struct CollisionBase
|
|||
template<class T>
|
||||
struct TCollision : public CollisionBase
|
||||
{
|
||||
T* actor() const { return static_cast<T*>(hitActor); }
|
||||
T* actor() const
|
||||
{
|
||||
return static_cast<T*>(hitActor);
|
||||
}
|
||||
|
||||
// normally collision data is short lived, this is only needed in some very rare circumstances.
|
||||
T* safeActor()
|
||||
{
|
||||
return static_cast<T*>(GC::ReadBarrier(hitActor));
|
||||
}
|
||||
|
||||
auto operator=(const CollisionBase& other)
|
||||
{
|
||||
*(CollisionBase*)this = other;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -339,6 +353,7 @@ int DeleteActor(DCoreActor* actor);
|
|||
void ChangeActorSect(DCoreActor* actor, sectortype* sector, bool forcetail = false);
|
||||
int ChangeActorStat(DCoreActor* actor, int nStatus, bool forcetail = false);
|
||||
void InitSpriteLists();
|
||||
void SetupActors(PClass* clstype);
|
||||
|
||||
|
||||
void SetActorZ(DCoreActor* actor, const vec3_t* newpos);
|
||||
|
|
|
@ -4205,15 +4205,15 @@ static void checkCeilHit(DBloodActor* actor)
|
|||
auto pSprite = &actor->s();
|
||||
auto pXSprite = actor->hasX() ? &actor->x() : nullptr;
|
||||
|
||||
const auto& coll = actor->hit.ceilhit;
|
||||
auto& coll = actor->hit.ceilhit;
|
||||
switch (coll.type)
|
||||
{
|
||||
case kHitWall:
|
||||
break;
|
||||
case kHitSprite:
|
||||
if (coll.actor()->hasX())
|
||||
auto actor2 = coll.actor();
|
||||
if (actor2 && actor2->hasX())
|
||||
{
|
||||
auto actor2 = coll.actor();
|
||||
spritetype* pSprite2 = &actor2->s();
|
||||
XSPRITE* pXSprite2 = &actor2->x();
|
||||
if ((pSprite2->statnum == kStatThing || pSprite2->statnum == kStatDude) && (actor->xvel != 0 || actor->yvel != 0 || actor->zvel != 0))
|
||||
|
@ -4524,7 +4524,7 @@ static void ProcessTouchObjects(DBloodActor* actor)
|
|||
if (gModernMap && actor->IsDudeActor())
|
||||
{
|
||||
DBloodActor* actor2 = nullptr;
|
||||
for (Collision* coll : { &actor->hit.hit, &actor->hit.florhit, &actor->hit.ceilhit})
|
||||
for (auto* coll : { &actor->hit.hit, &actor->hit.florhit, &actor->hit.ceilhit})
|
||||
{
|
||||
if (coll->type == kHitSprite)
|
||||
{
|
||||
|
@ -4627,7 +4627,7 @@ static Collision MoveThing(DBloodActor* actor)
|
|||
ChangeActorSect(actor, pSector);
|
||||
}
|
||||
|
||||
Collision &coll = actor->hit.hit;
|
||||
auto &coll = actor->hit.hit;
|
||||
if (coll.type == kHitWall)
|
||||
{
|
||||
actWallBounceVector(&actor->xvel, &actor->yvel, coll.hitWall, pThingInfo->elastic);
|
||||
|
@ -4859,7 +4859,7 @@ void MoveDude(DBloodActor* actor)
|
|||
assert(pSector);
|
||||
pSprite->cstat = bakCstat;
|
||||
}
|
||||
const Collision& coll = actor->hit.hit;
|
||||
auto& coll = actor->hit.hit;
|
||||
switch (coll.type)
|
||||
{
|
||||
case kHitSprite:
|
||||
|
|
|
@ -51,6 +51,33 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
|
||||
IMPLEMENT_CLASS(DBloodActor, false, true)
|
||||
IMPLEMENT_POINTERS_START(DBloodActor)
|
||||
IMPLEMENT_POINTER(prevmarker)
|
||||
IMPLEMENT_POINTER(ownerActor)
|
||||
IMPLEMENT_POINTER(hit.hit.hitActor)
|
||||
IMPLEMENT_POINTER(hit.ceilhit.hitActor)
|
||||
IMPLEMENT_POINTER(hit.florhit.hitActor)
|
||||
IMPLEMENT_POINTER(genDudeExtra.pLifeLeech)
|
||||
IMPLEMENT_POINTER(genDudeExtra.slave[0])
|
||||
IMPLEMENT_POINTER(genDudeExtra.slave[1])
|
||||
IMPLEMENT_POINTER(genDudeExtra.slave[2])
|
||||
IMPLEMENT_POINTER(genDudeExtra.slave[3])
|
||||
IMPLEMENT_POINTER(genDudeExtra.slave[4])
|
||||
IMPLEMENT_POINTER(genDudeExtra.slave[5])
|
||||
IMPLEMENT_POINTER(genDudeExtra.slave[6])
|
||||
IMPLEMENT_POINTER(xsprite.burnSource)
|
||||
IMPLEMENT_POINTER(xsprite.target)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
size_t DBloodActor::PropagateMark()
|
||||
{
|
||||
condition[0].Mark();
|
||||
condition[1].Mark();
|
||||
return 2;
|
||||
}
|
||||
|
||||
void InitCheats();
|
||||
|
||||
bool bNoDemo = false;
|
||||
|
@ -490,10 +517,7 @@ void GameInterface::loadPalette(void)
|
|||
|
||||
void GameInterface::app_init()
|
||||
{
|
||||
for (int i = 0; i < MAXSPRITES; i++)
|
||||
{
|
||||
actorArray[i] = &bloodActors[i];
|
||||
}
|
||||
SetupActors(RUNTIME_CLASS(DBloodActor));
|
||||
InitCheats();
|
||||
memcpy(&gGameOptions, &gSingleGameOptions, sizeof(GAMEOPTIONS));
|
||||
gGameOptions.nMonsterSettings = !userConfig.nomonsters;
|
||||
|
|
|
@ -8,13 +8,14 @@ class DBloodActor;
|
|||
|
||||
struct SPRITEHIT
|
||||
{
|
||||
// These must use read barriers as they can live longer and need proper GC maintenance.
|
||||
Collision hit, ceilhit, florhit;
|
||||
};
|
||||
|
||||
class DBloodActor : public DCoreActor
|
||||
{
|
||||
using Super = DCoreActor;
|
||||
DBloodActor* base();
|
||||
DECLARE_CLASS(DBloodActor, DCoreActor)
|
||||
HAS_OBJECT_POINTERS
|
||||
|
||||
public:
|
||||
int dudeSlope;
|
||||
|
@ -35,12 +36,9 @@ public:
|
|||
int cumulDamage;
|
||||
bool interpolated;
|
||||
|
||||
DBloodActor()
|
||||
{
|
||||
index = (int(this - base()));
|
||||
}
|
||||
|
||||
DBloodActor() = default;
|
||||
void Serialize(FSerializer& arc) override;
|
||||
size_t PropagateMark() override;
|
||||
|
||||
DBloodActor& operator=(const DBloodActor& other) = default;
|
||||
|
||||
|
@ -165,10 +163,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
extern DBloodActor bloodActors[kMaxSprites];
|
||||
|
||||
inline DBloodActor* DBloodActor::base() { return bloodActors; }
|
||||
|
||||
// subclassed to add a game specific actor() method
|
||||
|
||||
extern HitInfo gHitInfo;
|
||||
|
|
|
@ -38,9 +38,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
DBloodActor bloodActors[kMaxSprites];
|
||||
|
||||
|
||||
DBloodActor* InsertSprite(sectortype* pSector, int nStat)
|
||||
{
|
||||
auto act = static_cast<DBloodActor*>(::InsertActor(pSector, nStat));
|
||||
|
|
|
@ -55,7 +55,7 @@ FString EventObject::description() const
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static int GetBucketChannel(const EventObject* pBucket)
|
||||
static int GetBucketChannel(EventObject* pBucket)
|
||||
{
|
||||
if (pBucket->isSector())
|
||||
{
|
||||
|
@ -85,7 +85,7 @@ static int GetBucketChannel(const EventObject* pBucket)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static int CompareChannels(const EventObject* ref1, const EventObject* ref2)
|
||||
static int CompareChannels(EventObject* ref1, EventObject* ref2)
|
||||
{
|
||||
return GetBucketChannel(ref1) - GetBucketChannel(ref2);
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ void evInit(TArray<DBloodActor*>& actors)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static bool evGetSourceState(const EventObject& eob)
|
||||
static bool evGetSourceState(EventObject& eob)
|
||||
{
|
||||
if (eob.isSector())
|
||||
{
|
||||
|
@ -349,7 +349,7 @@ static bool evGetSourceState(const EventObject& eob)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void evSend(const EventObject& eob, int rxId, COMMAND_ID command)
|
||||
void evSend(EventObject& eob, int rxId, COMMAND_ID command)
|
||||
{
|
||||
switch (command) {
|
||||
case kCmdState:
|
||||
|
@ -509,7 +509,7 @@ void evSend(const EventObject& eob, int rxId, COMMAND_ID command)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void evPost_(const EventObject& eob, unsigned int nDelta, COMMAND_ID command)
|
||||
void evPost_(EventObject& eob, unsigned int nDelta, COMMAND_ID command)
|
||||
{
|
||||
assert(command != kCmdCallback);
|
||||
if (command == kCmdState) command = evGetSourceState(eob) ? kCmdOn : kCmdOff;
|
||||
|
@ -527,7 +527,8 @@ void evPost_(const EventObject& eob, unsigned int nDelta, CALLBACK_ID callback)
|
|||
|
||||
void evPostActor(DBloodActor* actor, unsigned int nDelta, COMMAND_ID command)
|
||||
{
|
||||
evPost_(EventObject(actor), nDelta, command);
|
||||
auto ev = EventObject(actor);
|
||||
evPost_(ev, nDelta, command);
|
||||
}
|
||||
|
||||
void evPostActor(DBloodActor* actor, unsigned int nDelta, CALLBACK_ID callback)
|
||||
|
@ -537,7 +538,8 @@ void evPostActor(DBloodActor* actor, unsigned int nDelta, CALLBACK_ID callback)
|
|||
|
||||
void evPostSector(sectortype* sect, unsigned int nDelta, COMMAND_ID command)
|
||||
{
|
||||
evPost_(EventObject(sect), nDelta, command);
|
||||
auto ev = EventObject(sect);
|
||||
evPost_(ev, nDelta, command);
|
||||
}
|
||||
|
||||
void evPostSector(sectortype* sect, unsigned int nDelta, CALLBACK_ID callback)
|
||||
|
@ -547,7 +549,8 @@ void evPostSector(sectortype* sect, unsigned int nDelta, CALLBACK_ID callback)
|
|||
|
||||
void evPostWall(walltype* wal, unsigned int nDelta, COMMAND_ID command)
|
||||
{
|
||||
evPost_(EventObject(wal), nDelta, command);
|
||||
auto ev = EventObject(wal);
|
||||
evPost_(ev, nDelta, command);
|
||||
}
|
||||
|
||||
|
||||
|
@ -598,22 +601,26 @@ void evKillSector(sectortype* sec)
|
|||
// these have no target.
|
||||
void evSendGame(int rxId, COMMAND_ID command)
|
||||
{
|
||||
evSend(EventObject(nullptr), rxId, command);
|
||||
auto ev = EventObject(nullptr);
|
||||
evSend(ev, rxId, command);
|
||||
}
|
||||
|
||||
void evSendActor(DBloodActor* actor, int rxId, COMMAND_ID command)
|
||||
{
|
||||
evSend(EventObject(actor), rxId, command);
|
||||
auto ev = EventObject(actor);
|
||||
evSend(ev, rxId, command);
|
||||
}
|
||||
|
||||
void evSendSector(sectortype* sect, int rxId, COMMAND_ID command)
|
||||
{
|
||||
evSend(EventObject(sect), rxId, command);
|
||||
auto ev = EventObject(sect);
|
||||
evSend(ev, rxId, command);
|
||||
}
|
||||
|
||||
void evSendWall(walltype* wal, int rxId, COMMAND_ID command)
|
||||
{
|
||||
evSend(EventObject(wal), rxId, command);
|
||||
auto ev = EventObject(wal);
|
||||
evSend(ev, rxId, command);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -43,7 +43,7 @@ class EventObject
|
|||
public:
|
||||
EventObject() = default;
|
||||
explicit EventObject(std::nullptr_t) { index = -1; }
|
||||
explicit EventObject(DBloodActor* actor_) { ActorP = actor_; assert(isActor()); /* GC:WriteBarrier(actor);*/ }
|
||||
explicit EventObject(DBloodActor* actor_) { ActorP = actor_; assert(isActor()); }
|
||||
explicit EventObject(sectortype *sect) { index = (sectnum(sect) << 8) | Sector; }
|
||||
explicit EventObject(walltype* wall) { index = (wallnum(wall) << 8) | Wall; }
|
||||
|
||||
|
@ -51,26 +51,20 @@ public:
|
|||
bool isSector() const { return (index&7) == Sector; }
|
||||
bool isWall() const { return (index&7) == Wall; }
|
||||
|
||||
DBloodActor* actor() const { assert(isActor()); return /*GC::ReadBarrier*/(ActorP); }
|
||||
sectortype* sector() const { assert(isSector()); return &::sector[index >> 8]; }
|
||||
walltype* wall() const { assert(isWall()); return &::wall[index >> 8]; }
|
||||
int rawindex() const { return index >> 8; }
|
||||
DBloodActor* actor() { assert(isActor()); return GC::ReadBarrier(ActorP); }
|
||||
sectortype* sector() { assert(isSector()); return &::sector[index >> 8]; }
|
||||
walltype* wall() { assert(isWall()); return &::wall[index >> 8]; }
|
||||
int rawindex() { return index >> 8; }
|
||||
|
||||
bool operator==(const EventObject& other) const { return index == other.index; }
|
||||
bool operator!=(const EventObject& other) const { return index != other.index; }
|
||||
|
||||
FString description() const;
|
||||
|
||||
// refactoring helper
|
||||
/*
|
||||
[[deprecated]] void fromElements(int type, int index, DBloodActor* act)
|
||||
void Mark()
|
||||
{
|
||||
if (type == 0) *this = &::wall[index];
|
||||
else if (type == 6) *this = &::sector[index];
|
||||
else if (type == 3) *this = act;
|
||||
else assert(false);
|
||||
if (isActor()) GC::Mark(ActorP);
|
||||
}
|
||||
*/
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -220,19 +214,19 @@ struct EVENT
|
|||
return target.isWall();
|
||||
}
|
||||
|
||||
DBloodActor* getActor() const
|
||||
DBloodActor* getActor()
|
||||
{
|
||||
assert(isActor());
|
||||
return target.actor();
|
||||
}
|
||||
|
||||
sectortype* getSector() const
|
||||
sectortype* getSector()
|
||||
{
|
||||
assert(isSector());
|
||||
return target.sector();
|
||||
}
|
||||
|
||||
walltype* getWall() const
|
||||
walltype* getWall()
|
||||
{
|
||||
assert(isWall());
|
||||
return target.wall();
|
||||
|
|
|
@ -668,7 +668,7 @@ int GetDistToLine(int x1, int y1, int x2, int y2, int x3, int y3)
|
|||
return approxDist(t1-x1, t2-y1);
|
||||
}
|
||||
|
||||
void ClipMove(vec3_t& pos, sectortype** pSector, int xv, int yv, int wd, int cd, int fd, unsigned int nMask, Collision& hit, int tracecount)
|
||||
void ClipMove(vec3_t& pos, sectortype** pSector, int xv, int yv, int wd, int cd, int fd, unsigned int nMask, CollisionBase& hit, int tracecount)
|
||||
{
|
||||
auto opos = pos;
|
||||
sectortype* bakSect = *pSector;
|
||||
|
|
|
@ -46,7 +46,7 @@ int VectorScan(DBloodActor *pSprite, int nOffset, int nZOffset, int dx, int dy,
|
|||
void GetZRange(DBloodActor *pSprite, int *ceilZ, Collision *ceilHit, int *floorZ, Collision *floorHit, int nDist, unsigned int nMask, unsigned int nClipParallax = 0);
|
||||
void GetZRangeAtXYZ(int x, int y, int z, sectortype* pSector, int *ceilZ, Collision *ceilHit, int *floorZ, Collision *floorHit, int nDist, unsigned int nMask, unsigned int nClipParallax = 0);
|
||||
int GetDistToLine(int x1, int y1, int x2, int y2, int x3, int y3);
|
||||
void ClipMove(vec3_t& pos, sectortype** pSector, int xv, int yv, int wd, int cd, int fd, unsigned int nMask, Collision& hit, int tracecount = 3);
|
||||
void ClipMove(vec3_t& pos, sectortype** pSector, int xv, int yv, int wd, int cd, int fd, unsigned int nMask, CollisionBase& hit, int tracecount = 3);
|
||||
BitArray GetClosestSpriteSectors(sectortype* pSector, int x, int y, int nDist, TArray<walltype*>* pWalls, bool newSectCheckMethod = false);
|
||||
int picWidth(int nPic, int repeat);
|
||||
int picHeight(int nPic, int repeat);
|
||||
|
|
|
@ -456,14 +456,6 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, DUDEEXTRA& w, DUDE
|
|||
return arc;
|
||||
}
|
||||
|
||||
FSerializer& Serialize(FSerializer& arc, const char* keyname, DBloodActor*& w, DBloodActor** def)
|
||||
{
|
||||
int index = w? int(w - bloodActors) : -1;
|
||||
Serialize(arc, keyname, index, nullptr);
|
||||
if (arc.isReading()) w = index == -1? nullptr : &bloodActors[index];
|
||||
return arc;
|
||||
}
|
||||
|
||||
void DBloodActor::Serialize(FSerializer& arc)
|
||||
{
|
||||
Super::Serialize(arc);
|
||||
|
|
|
@ -112,6 +112,6 @@ extern int nPrecacheCount;
|
|||
void tilePrecacheTile(int nTile, int nType, int palette);
|
||||
|
||||
int tileGetSurfType(int hit);
|
||||
int tileGetSurfType(Collision& hit);
|
||||
int tileGetSurfType(CollisionBase& hit);
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -452,7 +452,7 @@ bool nnExtEraseModernStuff(DBloodActor* actor)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void nnExtTriggerObject(const EventObject& eob, int command)
|
||||
void nnExtTriggerObject(EventObject& eob, int command)
|
||||
{
|
||||
if (eob.isSector())
|
||||
{
|
||||
|
@ -4532,19 +4532,20 @@ bool condCheckSprite(DBloodActor* aCond, int cmpOp, bool PUSH)
|
|||
case 58: // touching another sprite?
|
||||
{
|
||||
DBloodActor* actorvar = nullptr;
|
||||
// Caution: The hit pointers here may be stale, so be careful with them.
|
||||
switch (arg3)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
if (objActor->hit.florhit.type == kHitSprite) actorvar = objActor->hit.florhit.actor();
|
||||
if (objActor->hit.florhit.type == kHitSprite) actorvar = objActor->hit.florhit.safeActor();
|
||||
if (arg3 || var >= 0) break;
|
||||
[[fallthrough]];
|
||||
case 2:
|
||||
if (objActor->hit.hit.type == kHitSprite) actorvar = objActor->hit.hit.actor();
|
||||
if (objActor->hit.hit.type == kHitSprite) actorvar = objActor->hit.hit.safeActor();
|
||||
if (arg3 || var >= 0) break;
|
||||
[[fallthrough]];
|
||||
case 3:
|
||||
if (objActor->hit.ceilhit.type == kHitSprite) actorvar = objActor->hit.ceilhit.actor();
|
||||
if (objActor->hit.ceilhit.type == kHitSprite) actorvar = objActor->hit.ceilhit.safeActor();
|
||||
break;
|
||||
}
|
||||
if (actorvar == nullptr)
|
||||
|
@ -4559,15 +4560,15 @@ bool condCheckSprite(DBloodActor* aCond, int cmpOp, bool PUSH)
|
|||
{
|
||||
case 0:
|
||||
case 1:
|
||||
if (hit.ceilhit.type == kHitSprite && hit.ceilhit.actor() == objActor) actorvar = iactor;
|
||||
if (hit.ceilhit.type == kHitSprite && hit.ceilhit.safeActor() == objActor) actorvar = iactor;
|
||||
if (arg3 || actorvar) break;
|
||||
[[fallthrough]];
|
||||
case 2:
|
||||
if (hit.hit.type == kHitSprite && hit.hit.actor() == objActor) actorvar = iactor;
|
||||
if (hit.hit.type == kHitSprite && hit.hit.safeActor() == objActor) actorvar = iactor;
|
||||
if (arg3 || actorvar) break;
|
||||
[[fallthrough]];
|
||||
case 3:
|
||||
if (hit.florhit.type == kHitSprite && hit.florhit.actor() == objActor) actorvar = iactor;
|
||||
if (hit.florhit.type == kHitSprite && hit.florhit.safeActor() == objActor) actorvar = iactor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -4708,7 +4709,7 @@ void modernTypeSendCommand(DBloodActor* actor, int destChannel, COMMAND_ID comma
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void modernTypeTrigger(int destObjType, sectortype* destSect, walltype* destWall, DBloodActor* destactor, const EVENT& event)
|
||||
void modernTypeTrigger(int destObjType, sectortype* destSect, walltype* destWall, DBloodActor* destactor, EVENT& event)
|
||||
{
|
||||
if (!event.isActor()) return;
|
||||
auto pActor = event.getActor();
|
||||
|
@ -5421,7 +5422,7 @@ void useDudeSpawn(DBloodActor* pSource, DBloodActor* pSprite)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool modernTypeOperateSprite(DBloodActor* actor, const EVENT& event)
|
||||
bool modernTypeOperateSprite(DBloodActor* actor, EVENT& event)
|
||||
{
|
||||
auto pSprite = &actor->s();
|
||||
auto pXSprite = &actor->x();
|
||||
|
@ -6126,7 +6127,7 @@ void useSequentialTx(DBloodActor* sourceactor, COMMAND_ID cmd, bool setState)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int useCondition(DBloodActor* sourceactor, const EVENT& event)
|
||||
int useCondition(DBloodActor* sourceactor, EVENT& event)
|
||||
{
|
||||
spritetype* pSource = &sourceactor->s();
|
||||
auto pXSource = &sourceactor->x();
|
||||
|
@ -6211,8 +6212,10 @@ int useCondition(DBloodActor* sourceactor, const EVENT& event)
|
|||
}
|
||||
|
||||
// send it for initial object
|
||||
if ((pSource->flags & kModernTypeFlag2) && (sourceactor->condition[0] != sourceactor->condition[1] || !(pSource->hitag & kModernTypeFlag1))) {
|
||||
nnExtTriggerObject(condGet(sourceactor), pXSource->command);
|
||||
if ((pSource->flags & kModernTypeFlag2) && (sourceactor->condition[0] != sourceactor->condition[1] || !(pSource->hitag & kModernTypeFlag1)))
|
||||
{
|
||||
auto co = condGet(sourceactor);
|
||||
nnExtTriggerObject(co, pXSource->command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7329,7 +7332,7 @@ bool isActive(DBloodActor* actor)
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int getDataFieldOfObject(const EventObject &eob, int dataIndex)
|
||||
int getDataFieldOfObject(EventObject &eob, int dataIndex)
|
||||
{
|
||||
int data = -65535;
|
||||
|
||||
|
|
|
@ -331,9 +331,9 @@ void seqTxSendCmdAll(DBloodActor* pXSource, DBloodActor* nIndex, COMMAND_ID cmd,
|
|||
void trPlayerCtrlLink(DBloodActor* pXSource, PLAYER* pPlayer, bool checkCondition);
|
||||
void trPlayerCtrlStopScene(PLAYER* pPlayer);
|
||||
// ------------------------------------------------------------------------- //
|
||||
void modernTypeTrigger(int type, sectortype*sect, walltype* wal, DBloodActor* actor, const EVENT& event);
|
||||
void modernTypeTrigger(int type, sectortype*sect, walltype* wal, DBloodActor* actor, EVENT& event);
|
||||
bool modernTypeOperateSector(sectortype* pSector, const EVENT& event);
|
||||
bool modernTypeOperateSprite(DBloodActor*, const EVENT& event);
|
||||
bool modernTypeOperateSprite(DBloodActor*, EVENT& event);
|
||||
bool modernTypeOperateWall(walltype* pWall, const EVENT& event);
|
||||
void modernTypeSendCommand(DBloodActor* nSprite, int channel, COMMAND_ID command);
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
@ -358,14 +358,14 @@ bool isShrinked(DBloodActor* pSprite);
|
|||
bool IsBurningDude(DBloodActor* pSprite);
|
||||
bool IsKillableDude(DBloodActor* pSprite);
|
||||
bool isActive(DBloodActor* nSprite);
|
||||
int getDataFieldOfObject(const EventObject& eob, int dataIndex);
|
||||
int getDataFieldOfObject(EventObject& eob, int dataIndex);
|
||||
int getDataFieldOfObject(int objType, sectortype* sect, walltype* wal, DBloodActor* actor, int dataIndex);
|
||||
bool setDataValueOfObject(int objType, sectortype* sect, walltype* wal, DBloodActor* objActor, int dataIndex, int value);
|
||||
bool incDecGoalValueIsReached(DBloodActor* actor);
|
||||
int getSpriteMassBySize(DBloodActor* pSprite);
|
||||
bool ceilIsTooLow(DBloodActor* pSprite);
|
||||
void levelEndLevelCustom(int nLevel);
|
||||
int useCondition(DBloodActor*, const EVENT& event);
|
||||
int useCondition(DBloodActor*, EVENT& event);
|
||||
bool condCmp(int val, int arg1, int arg2, int comOp);
|
||||
bool condCmpne(int arg1, int arg2, int comOp);
|
||||
void condError(DBloodActor* pXCond, const char* pzFormat, ...);
|
||||
|
|
|
@ -75,7 +75,7 @@ int tileGetSurfType(int hit)
|
|||
return surfType[hit];
|
||||
}
|
||||
|
||||
int tileGetSurfType(Collision& hit)
|
||||
int tileGetSurfType(CollisionBase& hit)
|
||||
{
|
||||
switch (hit.type)
|
||||
{
|
||||
|
@ -86,7 +86,7 @@ int tileGetSurfType(Collision& hit)
|
|||
case kHitWall:
|
||||
return surfType[hit.hitWall->picnum];
|
||||
case kHitSprite:
|
||||
return surfType[hit.actor()->s().picnum];
|
||||
return surfType[hit.hitActor->s().picnum];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ void ReverseBusy(sectortype* pSector, BUSYID a2)
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int GetSourceBusy(const EVENT& a1)
|
||||
unsigned int GetSourceBusy(EVENT& a1)
|
||||
{
|
||||
if (a1.isSector())
|
||||
{
|
||||
|
@ -1677,7 +1677,7 @@ void LinkSprite(DBloodActor* actor, EVENT event)
|
|||
}
|
||||
}
|
||||
|
||||
void LinkWall(walltype* pWall, const EVENT& event)
|
||||
void LinkWall(walltype* pWall, EVENT& event)
|
||||
{
|
||||
int nBusy = GetSourceBusy(event);
|
||||
pWall->xw().busy = nBusy;
|
||||
|
@ -1770,7 +1770,7 @@ void trMessageSector(sectortype* pSector, EVENT event)
|
|||
}
|
||||
}
|
||||
|
||||
void trMessageWall(walltype* pWall, const EVENT& event)
|
||||
void trMessageWall(walltype* pWall, EVENT& event)
|
||||
{
|
||||
assert(pWall->hasX());
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ extern TArray<BUSY> gBusy;
|
|||
void trTriggerSector(sectortype *pSector, int command);
|
||||
void trMessageSector(sectortype* pSector, EVENT event);
|
||||
void trTriggerWall(walltype*, int command);
|
||||
void trMessageWall(walltype* pWall, const EVENT& event);
|
||||
void trMessageWall(walltype* pWall, EVENT& event);
|
||||
void trTriggerSprite(DBloodActor* actor, int command);
|
||||
void trMessageSprite(DBloodActor* actor, EVENT event);
|
||||
void trProcessBusy(void);
|
||||
|
|
|
@ -47,6 +47,23 @@ void SetDispatcher();
|
|||
void InitCheats();
|
||||
int registerosdcommands(void);
|
||||
|
||||
IMPLEMENT_CLASS(DDukeActor, false, true)
|
||||
IMPLEMENT_POINTERS_START(DDukeActor)
|
||||
IMPLEMENT_POINTER(ownerActor)
|
||||
IMPLEMENT_POINTER(hitOwnerActor)
|
||||
IMPLEMENT_POINTER(temp_actor)
|
||||
IMPLEMENT_POINTER(seek_actor)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
size_t DDukeActor::PropagateMark()
|
||||
{
|
||||
for (auto& var : uservars)
|
||||
{
|
||||
var.Mark();
|
||||
}
|
||||
return uservars.Size() + Super::PropagateMark();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// game specific command line args go here.
|
||||
|
@ -285,10 +302,7 @@ int GameInterface::GetCurrentSkill()
|
|||
|
||||
void GameInterface::app_init()
|
||||
{
|
||||
for (int i = 0; i < MAXSPRITES; i++)
|
||||
{
|
||||
actorArray[i] = &hittype[i];
|
||||
}
|
||||
SetupActors(RUNTIME_CLASS(DDukeActor));
|
||||
|
||||
if (isRR()) C_SetNotifyFontScale(0.5);
|
||||
ud.god = 0;
|
||||
|
|
|
@ -24,19 +24,23 @@ class GameVarValue
|
|||
|
||||
public:
|
||||
GameVarValue() = default;
|
||||
explicit GameVarValue(DDukeActor* actor_) { ActorP = actor_; assert(isActor()); /* GC:WriteBarrier(actor);*/ }
|
||||
explicit GameVarValue(DDukeActor* actor_) { ActorP = actor_; assert(isActor()); }
|
||||
explicit GameVarValue(int val) { index = (val << 8) | Value; }
|
||||
|
||||
bool isActor() const { return (index & 7) == Actor; }
|
||||
bool isValue() const { return (index & 7) == Value; }
|
||||
|
||||
DDukeActor* actor() const { assert(isActor()); return /*GC::ReadBarrier*/(ActorP); }
|
||||
int value() const { assert(isValue()); return index >> 8; }
|
||||
int safeValue() const { return isValue() ? value() : actor() == nullptr ? 0 : -1; } // return -1 for valid actors and 0 for null. This allows most comparisons to work.
|
||||
DDukeActor* safeActor() const { return isActor() ? actor() : nullptr; }
|
||||
DDukeActor* actor() { assert(isActor()); return GC::ReadBarrier(ActorP); }
|
||||
int value() { assert(isValue()); return index >> 8; }
|
||||
int safeValue() { return isValue() ? value() : actor() == nullptr ? 0 : -1; } // return -1 for valid actors and 0 for null. This allows most comparisons to work.
|
||||
DDukeActor* safeActor() { return isActor() ? actor() : nullptr; }
|
||||
|
||||
bool operator==(const GameVarValue& other) const { return index == other.index; }
|
||||
bool operator!=(const GameVarValue& other) const { return index != other.index; }
|
||||
void Mark()
|
||||
{
|
||||
if (isActor()) GC::Mark(ActorP);
|
||||
}
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
|
@ -91,7 +91,6 @@ TArray<CraneDef> cranes;
|
|||
|
||||
bool sound445done; // used in checksectors_r. This was local state inside a function, but this must be maintained globally and serialized
|
||||
|
||||
DDukeActor hittype[MAXSPRITES + 1]; // +1 to have a blank entry for serialization, all access in game code through the iterators.
|
||||
int spriteqamount = 64; // internal sprite queue
|
||||
int spriteqloc;
|
||||
DDukeActor* spriteq[1024];
|
||||
|
|
|
@ -949,7 +949,8 @@ static TArray<DDukeActor*> spawnactors(SpawnSpriteDef& sprites)
|
|||
auto sprt = &sprites.sprites[i];
|
||||
auto actor = static_cast<DDukeActor*>(InsertActor(sprt->sector(), sprt->statnum));
|
||||
spawns[j++] = actor;
|
||||
*actor->s = sprites.sprites[i];
|
||||
actor->spr = sprites.sprites[i];
|
||||
actor->s = &actor->spr;
|
||||
if (sprites.sprext.Size()) actor->sx() = sprites.sprext[i];
|
||||
else actor->sx() = {};
|
||||
actor->sm() = {};
|
||||
|
|
|
@ -43,15 +43,6 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
|
|||
|
||||
BEGIN_DUKE_NS
|
||||
|
||||
/*template<>*/ FSerializer& Serialize(FSerializer& arc, const char* key, Duke3d::DDukeActor*& ht, Duke3d::DDukeActor** def)
|
||||
{
|
||||
int index = ht ? ht->GetSpriteIndex() : -1;
|
||||
assert(index >= -1 && index < MAXSPRITES);
|
||||
Serialize(arc, key, index, nullptr);
|
||||
ht = index < 0 ? nullptr : &Duke3d::hittype[index];
|
||||
return arc;
|
||||
}
|
||||
|
||||
FSerializer& Serialize(FSerializer& arc, const char* keyname, GameVarValue& w, GameVarValue* def);
|
||||
void SerializeActorGlobals(FSerializer& arc);
|
||||
void lava_serialize(FSerializer& arc);
|
||||
|
|
|
@ -56,6 +56,7 @@ DDukeActor* EGS(sectortype* whatsectp, int s_x, int s_y, int s_z, int s_pn, int8
|
|||
auto act = static_cast<DDukeActor*>(::InsertActor(whatsectp, s_ss));
|
||||
|
||||
if (act == nullptr) return nullptr;
|
||||
act->s = &act->spr;
|
||||
SetupGameVarsForActor(act);
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ struct STATUSBARTYPE
|
|||
|
||||
class DDukeActor : public DCoreActor
|
||||
{
|
||||
using Super = DCoreActor;
|
||||
DECLARE_CLASS(DDukeActor, DCoreActor)
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
uint8_t cgg;
|
||||
uint8_t spriteextra; // moved here for easier maintenance. This was originally a hacked in field in the sprite structure called 'filler'.
|
||||
|
@ -47,15 +48,8 @@ public:
|
|||
|
||||
TArray<GameVarValue> uservars;
|
||||
|
||||
static DDukeActor* array(); // this is necessary to allow define inline functions referencing the global array inside the definition itself.
|
||||
|
||||
DDukeActor()
|
||||
{
|
||||
index = int(this - array());
|
||||
s = &DCoreActor::s();
|
||||
}
|
||||
DDukeActor(const DDukeActor& other) = delete; // we also do not want to allow copies.
|
||||
DDukeActor& operator=(const DDukeActor& other) = delete;
|
||||
DDukeActor() = default;
|
||||
size_t PropagateMark() override;
|
||||
void ClearContent() override
|
||||
{
|
||||
Super::ClearContent();
|
||||
|
@ -109,8 +103,6 @@ public:
|
|||
void Serialize(FSerializer& arc) override;
|
||||
|
||||
};
|
||||
extern DDukeActor hittype[MAXSPRITES + 1];
|
||||
inline DDukeActor* DDukeActor::array() { return hittype; }
|
||||
|
||||
// subclassed to add a game specific actor() method
|
||||
using HitInfo = THitInfo<DDukeActor>;
|
||||
|
|
|
@ -52,7 +52,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_PS_NS
|
||||
|
||||
DExhumedActor exhumedActors[MAXSPRITES];
|
||||
IMPLEMENT_CLASS(DExhumedActor, false, true)
|
||||
IMPLEMENT_POINTERS_START(DExhumedActor)
|
||||
IMPLEMENT_POINTER(pTarget)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
static MapRecord* NextMap;
|
||||
|
||||
|
@ -464,10 +467,7 @@ static void SetTileNames()
|
|||
|
||||
void GameInterface::app_init()
|
||||
{
|
||||
for (int i = 0; i < MAXSPRITES; i++)
|
||||
{
|
||||
actorArray[i] = &exhumedActors[i];
|
||||
}
|
||||
SetupActors(RUNTIME_CLASS(DExhumedActor));
|
||||
|
||||
#if 0
|
||||
help_disabled = true;
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
BEGIN_PS_NS
|
||||
|
||||
class DExhumedActor;
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -16,9 +15,8 @@ enum
|
|||
|
||||
class DExhumedActor : public DCoreActor
|
||||
{
|
||||
using Super = DCoreActor;
|
||||
|
||||
DExhumedActor* base();
|
||||
DECLARE_CLASS(DExhumedActor, DCoreActor)
|
||||
HAS_OBJECT_POINTERS
|
||||
|
||||
public:
|
||||
DExhumedActor* pTarget;
|
||||
|
@ -41,11 +39,7 @@ public:
|
|||
int y;
|
||||
|
||||
|
||||
DExhumedActor()
|
||||
{
|
||||
index = (int(this - base()));
|
||||
}
|
||||
DExhumedActor& operator=(const DExhumedActor& other) = default;
|
||||
DExhumedActor() = default;
|
||||
|
||||
void ClearContent() override
|
||||
{
|
||||
|
@ -58,10 +52,6 @@ public:
|
|||
|
||||
};
|
||||
|
||||
extern DExhumedActor exhumedActors[MAXSPRITES];
|
||||
|
||||
inline DExhumedActor* DExhumedActor::base() { return exhumedActors; }
|
||||
|
||||
// subclassed to add a game specific actor() method
|
||||
using HitInfo = THitInfo<DExhumedActor>;
|
||||
using Collision = TCollision<DExhumedActor>;
|
||||
|
@ -71,12 +61,4 @@ using ExhumedSectIterator = TSectIterator<DExhumedActor>;
|
|||
using ExhumedSpriteIterator = TSpriteIterator<DExhumedActor>;
|
||||
|
||||
|
||||
inline FSerializer& Serialize(FSerializer& arc, const char* keyname, DExhumedActor*& w, DExhumedActor** def)
|
||||
{
|
||||
int index = w? int(w - exhumedActors) : -1;
|
||||
Serialize(arc, keyname, index, nullptr);
|
||||
if (arc.isReading()) w = index == -1? nullptr : &exhumedActors[index];
|
||||
return arc;
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -42,7 +42,17 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|||
|
||||
BEGIN_SW_NS
|
||||
|
||||
DSWActor swActors[MAXSPRITES];
|
||||
IMPLEMENT_CLASS(DSWActor, false, true)
|
||||
IMPLEMENT_POINTERS_START(DSWActor)
|
||||
IMPLEMENT_POINTER(ownerActor)
|
||||
IMPLEMENT_POINTER(user.lowActor)
|
||||
IMPLEMENT_POINTER(user.lowActor)
|
||||
IMPLEMENT_POINTER(user.highActor)
|
||||
IMPLEMENT_POINTER(user.targetActor)
|
||||
IMPLEMENT_POINTER(user.flameActor)
|
||||
IMPLEMENT_POINTER(user.attachActor)
|
||||
IMPLEMENT_POINTER(user.WpnGoalActor)
|
||||
IMPLEMENT_POINTERS_END
|
||||
|
||||
extern int jump_grav;
|
||||
|
||||
|
|
|
@ -178,10 +178,7 @@ void GameInterface::LoadGameTextures()
|
|||
|
||||
void GameInterface::app_init()
|
||||
{
|
||||
for (int i = 0; i < MAXSPRITES; i++)
|
||||
{
|
||||
actorArray[i] = &swActors[i];
|
||||
}
|
||||
SetupActors(RUNTIME_CLASS(DSWActor));
|
||||
|
||||
GameTicRate = TICS_PER_SEC / synctics;
|
||||
InitCheats();
|
||||
|
|
|
@ -7,9 +7,8 @@ BEGIN_SW_NS
|
|||
|
||||
class DSWActor : public DCoreActor
|
||||
{
|
||||
using Super = DCoreActor;
|
||||
|
||||
DSWActor* base();
|
||||
DECLARE_CLASS(DSWActor, DCoreActor)
|
||||
HAS_OBJECT_POINTERS
|
||||
|
||||
public:
|
||||
|
||||
|
@ -18,10 +17,7 @@ public:
|
|||
walltype* tempwall; // transient, to replace a hack using a 16 bit sprite field.
|
||||
DSWActor* ownerActor;
|
||||
|
||||
DSWActor()
|
||||
{
|
||||
index = (int(this - base()));
|
||||
}
|
||||
DSWActor() = default;
|
||||
DSWActor& operator=(const DSWActor& other) = default;
|
||||
|
||||
void ClearContent()
|
||||
|
@ -50,9 +46,6 @@ public:
|
|||
|
||||
};
|
||||
|
||||
extern DSWActor swActors[MAXSPRITES];
|
||||
|
||||
inline DSWActor* DSWActor::base() { return swActors; }
|
||||
|
||||
// subclassed to add a game specific actor() method
|
||||
|
||||
|
@ -62,13 +55,4 @@ using SWSectIterator = TSectIterator<DSWActor>;
|
|||
using SWSpriteIterator = TSpriteIterator<DSWActor>;
|
||||
|
||||
|
||||
inline FSerializer& Serialize(FSerializer& arc, const char* keyname, DSWActor*& w, DSWActor** def)
|
||||
{
|
||||
int index = w? int(w - swActors) : -1;
|
||||
Serialize(arc, keyname, index, nullptr);
|
||||
if (arc.isReading()) w = index == -1? nullptr : &swActors[index];
|
||||
return arc;
|
||||
}
|
||||
|
||||
|
||||
END_SW_NS
|
||||
|
|
Loading…
Reference in a new issue