#pragma once #include "coreactor.h" BEGIN_PS_NS class DExhumedActor; enum { kHitAuxMask = 0x30000, kHitAux1 = 0x10000, kHitAux2 = 0x20000, }; // Wrapper around the insane collision info mess from Build. struct Collision { int type; int index; int exbits; int legacyVal; // should be removed later, but needed for converting back for unadjusted code. DExhumedActor* actor; Collision() = default; explicit Collision(int legacyval) { setFromEngine(legacyval); } // need forward declarations of these. int actorIndex(DExhumedActor*); DExhumedActor* Actor(int); int setNone() { type = kHitNone; index = -1; exbits = 0; legacyVal = 0; actor = nullptr; return kHitNone; } int setSector(int num) { type = kHitSector; index = num; exbits = 0; legacyVal = type | index; actor = nullptr; return kHitSector; } int setWall(int num) { type = kHitWall; index = num; exbits = 0; legacyVal = type | index; actor = nullptr; return kHitWall; } int setSprite(DExhumedActor* num) { type = kHitSprite; index = -1; exbits = 0; legacyVal = type | actorIndex(num); actor = num; return kHitSprite; } int setFromEngine(int value) { legacyVal = value; type = value & kHitTypeMask; exbits = value & kHitAuxMask; if (type == 0) { index = -1; actor = nullptr; } else if (type != kHitSprite) { index = value & kHitIndexMask; actor = nullptr; } else { index = -1; actor = Actor(value & kHitIndexMask); } return type; } walltype* wall() { return &::wall[index]; } sectortype* sector() { return &::sector[index]; } }; class DExhumedActor : public DCoreActor { DExhumedActor* base(); public: DExhumedActor* pTarget; int16_t nPhase; int16_t nHealth; int16_t nFrame; int16_t nAction; int16_t nCount; int16_t nRun; union { int16_t nIndex; int16_t nAngle; }; // angle is for wasp. union { int16_t nIndex2; int16_t nAngle2; }; // index2 is for scorpion, angle2 is for wasp. union { int16_t nChannel; int16_t nVel; }; // channel is for scorpion, vel is for wasp. union { int16_t nDamage; int16_t nAction2; }; // nAction2 is for the queen. // for the grenade. int nTurn; int x; int y; DExhumedActor() { index = (int(this - base())); } DExhumedActor& operator=(const DExhumedActor& other) = default; void Clear() { } }; extern DExhumedActor exhumedActors[MAXSPRITES]; inline DExhumedActor* Collision::Actor(int i) { return &exhumedActors[i]; } inline int Collision::actorIndex(DExhumedActor* a) { return a->GetSpriteIndex(); } inline DExhumedActor* DExhumedActor::base() { return exhumedActors; } // subclassed to add a game specific actor() method using HitInfo = THitInfo; // Iterator wrappers that return an actor pointer, not an index. class ExhumedStatIterator : public StatIterator { public: ExhumedStatIterator(int stat) : StatIterator(stat) { } DExhumedActor* Next() { int n = NextIndex(); return n >= 0 ? &exhumedActors[n] : nullptr; } DExhumedActor* Peek() { int n = PeekIndex(); return n >= 0 ? &exhumedActors[n] : nullptr; } }; class ExhumedSectIterator : public SectIterator { public: ExhumedSectIterator(int stat) : SectIterator(stat) { } ExhumedSectIterator(sectortype* stat) : SectIterator(stat) { } DExhumedActor* Next() { int n = NextIndex(); return n >= 0 ? &exhumedActors[n] : nullptr; } DExhumedActor* Peek() { int n = PeekIndex(); return n >= 0 ? &exhumedActors[n] : nullptr; } }; // An iterator to iterate over all sprites. class ExhumedSpriteIterator { ExhumedStatIterator it; int stat = 0; public: ExhumedSpriteIterator() : it(0) {} DExhumedActor* Next() { while (stat < MAXSTATUS) { auto ac = it.Next(); if (ac) return ac; stat++; if (stat < MAXSTATUS) it.Reset(stat); } return nullptr; } }; // For iterating linearly over map spawned sprites. class ExhumedLinearSpriteIterator { int index = 0; public: void Reset() { index = 0; } DExhumedActor* Next() { while (index < MAXSPRITES) { auto p = &exhumedActors[index++]; if (p->s().statnum != MAXSTATUS) return p; } return nullptr; } }; 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; } inline void ChangeActorStat(DExhumedActor* actor, int stat) { changespritestat(actor->GetSpriteIndex(), stat); } inline void ChangeActorSect(DExhumedActor* actor, sectortype* stat) { changespritesect(actor->GetSpriteIndex(), sector.IndexOf(stat)); } inline void setActorPos(DExhumedActor* actor, vec3_t* pos) { setsprite(actor->GetSpriteIndex(), pos); } END_BLD_NS