- 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:
Christoph Oelckers 2021-12-05 20:55:19 +01:00
parent 8606045689
commit 588f88c9cc
29 changed files with 209 additions and 184 deletions

View file

@ -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.
}
}

View file

@ -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);

View file

@ -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:

View file

@ -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;

View file

@ -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;

View file

@ -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));

View file

@ -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);
}
//---------------------------------------------------------------------------

View file

@ -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();

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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, ...);

View file

@ -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];
}
}

View file

@ -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());

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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];

View file

@ -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() = {};

View file

@ -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);

View file

@ -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);

View file

@ -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>;

View file

@ -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;

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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