2021-10-29 18:49:57 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
// included by game.h
|
|
|
|
|
|
|
|
BEGIN_SW_NS
|
|
|
|
|
|
|
|
|
|
|
|
class DSWActor
|
|
|
|
{
|
|
|
|
int index;
|
|
|
|
DSWActor* base();
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2021-11-19 23:18:23 +00:00
|
|
|
bool hasUser;
|
|
|
|
USER user;
|
2021-11-24 19:11:50 +00:00
|
|
|
walltype* tempwall; // transient, to replace a hack using a 16 bit sprite field.
|
2021-11-19 23:18:23 +00:00
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
DSWActor() :index(int(this - base())) { /*assert(index >= 0 && index < kMaxSprites);*/ }
|
|
|
|
DSWActor& operator=(const DSWActor& other) = default;
|
|
|
|
|
|
|
|
void Clear()
|
|
|
|
{
|
2021-11-17 16:01:10 +00:00
|
|
|
clearUser();
|
2021-10-29 18:49:57 +00:00
|
|
|
}
|
2021-11-19 23:18:23 +00:00
|
|
|
bool hasU() { return hasUser; }
|
2021-11-06 09:40:57 +00:00
|
|
|
|
2021-11-17 16:01:10 +00:00
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
spritetype& s() { return sprite[index]; }
|
2021-11-19 23:18:23 +00:00
|
|
|
USER* u() { return &user; }
|
2021-10-31 22:01:00 +00:00
|
|
|
USER* allocUser()
|
|
|
|
{
|
2021-11-19 23:18:23 +00:00
|
|
|
hasUser = true;
|
2021-11-06 09:40:57 +00:00
|
|
|
return u();
|
2021-10-31 22:01:00 +00:00
|
|
|
}
|
2021-10-29 18:49:57 +00:00
|
|
|
|
2021-11-01 22:26:13 +00:00
|
|
|
void clearUser()
|
|
|
|
{
|
2021-11-19 23:18:23 +00:00
|
|
|
hasUser = false;
|
|
|
|
user.Clear();
|
2021-11-01 22:26:13 +00:00
|
|
|
}
|
|
|
|
|
2021-11-01 16:54:18 +00:00
|
|
|
int GetIndex()
|
|
|
|
{
|
|
|
|
return s().time;
|
|
|
|
}
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
int GetSpriteIndex() const
|
|
|
|
{
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
extern DSWActor swActors[MAXSPRITES];
|
|
|
|
|
|
|
|
inline DSWActor* DSWActor::base() { return swActors; }
|
|
|
|
|
|
|
|
// Iterator wrappers that return an actor pointer, not an index.
|
|
|
|
class SWStatIterator : public StatIterator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SWStatIterator(int stat) : StatIterator(stat)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
DSWActor* Next()
|
|
|
|
{
|
|
|
|
int n = NextIndex();
|
|
|
|
return n >= 0 ? &swActors[n] : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
DSWActor* Peek()
|
|
|
|
{
|
|
|
|
int n = PeekIndex();
|
|
|
|
return n >= 0 ? &swActors[n] : nullptr;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SWSectIterator : public SectIterator
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
SWSectIterator(int stat) : SectIterator(stat)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-11-11 19:20:00 +00:00
|
|
|
SWSectIterator(sectortype* stat) : SectIterator(stat)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
DSWActor* Next()
|
|
|
|
{
|
|
|
|
int n = NextIndex();
|
|
|
|
return n >= 0 ? &swActors[n] : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
DSWActor* Peek()
|
|
|
|
{
|
|
|
|
int n = PeekIndex();
|
|
|
|
return n >= 0 ? &swActors[n] : nullptr;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// An iterator to iterate over all sprites.
|
|
|
|
class SWSpriteIterator
|
|
|
|
{
|
|
|
|
SWStatIterator it;
|
|
|
|
int stat = 0;
|
|
|
|
|
|
|
|
public:
|
|
|
|
SWSpriteIterator() : it(0) {}
|
|
|
|
|
|
|
|
DSWActor* 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 SWLinearSpriteIterator
|
|
|
|
{
|
|
|
|
int index = 0;
|
|
|
|
public:
|
|
|
|
|
|
|
|
void Reset()
|
|
|
|
{
|
|
|
|
index = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
DSWActor* Next()
|
|
|
|
{
|
|
|
|
while (index < MAXSPRITES)
|
|
|
|
{
|
|
|
|
auto p = &swActors[index++];
|
|
|
|
if (p->s().statnum != MAXSTATUS) return p;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-10-29 23:15:32 +00:00
|
|
|
enum EHitBitsSW
|
|
|
|
{
|
|
|
|
kHitTypeMaskSW = 0x1C000,
|
|
|
|
kHitSky = 0x10000, // SW only
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2021-10-31 09:54:34 +00:00
|
|
|
inline int Collision::setNone()
|
2021-10-29 18:49:57 +00:00
|
|
|
{
|
2021-10-31 09:54:34 +00:00
|
|
|
type = kHitNone;
|
|
|
|
index = -1;
|
|
|
|
legacyVal = 0;
|
|
|
|
actor = nullptr;
|
|
|
|
return kHitNone;
|
|
|
|
}
|
2021-10-29 18:49:57 +00:00
|
|
|
|
2021-10-31 09:54:34 +00:00
|
|
|
inline int Collision::setSector(int num)
|
|
|
|
{
|
|
|
|
type = kHitSector;
|
|
|
|
index = num;
|
|
|
|
legacyVal = type | index;
|
|
|
|
actor = nullptr;
|
|
|
|
return kHitSector;
|
|
|
|
}
|
|
|
|
inline int Collision::setWall(int num)
|
|
|
|
{
|
|
|
|
type = kHitWall;
|
|
|
|
index = num;
|
|
|
|
legacyVal = type | index;
|
|
|
|
actor = nullptr;
|
|
|
|
return kHitWall;
|
|
|
|
}
|
|
|
|
inline int Collision::setSprite(DSWActor* num)
|
|
|
|
{
|
|
|
|
type = kHitSprite;
|
|
|
|
index = -1;
|
|
|
|
legacyVal = type | int(num - swActors);
|
|
|
|
actor = num;
|
|
|
|
return kHitSprite;
|
|
|
|
}
|
2021-10-29 18:49:57 +00:00
|
|
|
|
2021-11-06 11:19:08 +00:00
|
|
|
int Collision::setSky() { setNone(); type = kHitSky; return kHitSky; }
|
|
|
|
|
2021-10-31 09:54:34 +00:00
|
|
|
inline int Collision::setFromEngine(int value)
|
|
|
|
{
|
|
|
|
legacyVal = value;
|
|
|
|
type = value & kHitTypeMaskSW;
|
|
|
|
if (type == 0) { index = -1; actor = nullptr; }
|
|
|
|
else if (type != kHitSprite) { index = value & kHitIndexMask; actor = nullptr; }
|
|
|
|
else { index = -1; actor = &swActors[value & kHitIndexMask]; }
|
|
|
|
return type;
|
|
|
|
}
|
2021-10-29 18:49:57 +00:00
|
|
|
|
2021-11-03 23:23:05 +00:00
|
|
|
struct HITINFO {
|
|
|
|
DSWActor* hitactor;
|
2021-11-24 15:49:53 +00:00
|
|
|
int hitsect;
|
|
|
|
int hitwall;
|
2021-11-03 23:23:05 +00:00
|
|
|
short hitsprite;
|
|
|
|
vec3_t pos;
|
|
|
|
|
|
|
|
void clearObj()
|
|
|
|
{
|
|
|
|
pos = {};
|
2021-11-24 15:49:53 +00:00
|
|
|
hitsect = hitwall = -1;
|
2021-11-03 23:23:05 +00:00
|
|
|
hitsprite = -1;
|
|
|
|
hitactor = nullptr;
|
|
|
|
}
|
|
|
|
void set(hitdata_t* hit)
|
|
|
|
{
|
2021-11-24 15:49:53 +00:00
|
|
|
hitsect = hit->sect;
|
|
|
|
hitwall = hit->wall;
|
2021-11-03 23:23:05 +00:00
|
|
|
hitsprite = hit->sprite;
|
|
|
|
hitactor = hit->sprite >= 0 ? &swActors[hit->sprite] : nullptr;
|
|
|
|
pos = hit->pos;
|
|
|
|
}
|
2021-11-24 15:49:53 +00:00
|
|
|
|
2021-11-24 15:55:24 +00:00
|
|
|
walltype* wall() const { return hitwall == -1? nullptr : &::wall[hitwall]; }
|
|
|
|
sectortype* sector() const { return hitsect == -1 ? nullptr : &::sector[hitsect]; }
|
2021-11-03 23:23:05 +00:00
|
|
|
};
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-10-31 10:52:18 +00:00
|
|
|
inline void ChangeActorSect(DSWActor* actor, int sect)
|
|
|
|
{
|
|
|
|
changespritesect(actor->GetSpriteIndex(), sect);
|
|
|
|
}
|
2021-10-29 18:49:57 +00:00
|
|
|
|
2021-10-31 15:55:24 +00:00
|
|
|
inline int SetActorZ(DSWActor* actor, const vec3_t* newpos)
|
|
|
|
{
|
|
|
|
return setspritez(actor->GetSpriteIndex(), newpos);
|
|
|
|
}
|
|
|
|
|
2021-11-04 23:00:47 +00:00
|
|
|
inline int SetActor(DSWActor* actor, const vec3_t* newpos)
|
|
|
|
{
|
|
|
|
return setsprite(actor->GetSpriteIndex(), newpos);
|
|
|
|
}
|
|
|
|
|
2021-10-29 18:49:57 +00:00
|
|
|
END_SW_NS
|