2021-11-25 20:42:49 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <stdint.h>
|
2021-12-30 11:21:51 +00:00
|
|
|
#include "maptypes.h"
|
2022-01-23 08:54:49 +00:00
|
|
|
#include "build.h"
|
|
|
|
#include "actorinfo.h"
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
MAXSTATUS = 1024
|
|
|
|
};
|
2021-11-25 20:42:49 +00:00
|
|
|
|
2022-05-27 11:55:38 +00:00
|
|
|
struct FWallSpriteDesc
|
|
|
|
{
|
|
|
|
walltype* wall;
|
|
|
|
float offsetOnWall;
|
|
|
|
};
|
|
|
|
|
|
|
|
// This is for quick determination of walls a wall sprite is attached to.
|
|
|
|
struct FWallSpriteInfo
|
|
|
|
{
|
|
|
|
tspritetype base; // this is needed for checking if something has changed.
|
|
|
|
TArray<FWallSpriteDesc> connections[2]; // two lists - for front and back
|
|
|
|
};
|
|
|
|
|
2021-12-05 19:55:19 +00:00
|
|
|
class DCoreActor : public DObject
|
2021-11-25 20:42:49 +00:00
|
|
|
{
|
2021-12-05 19:55:19 +00:00
|
|
|
DECLARE_CLASS(DCoreActor, DObject)
|
|
|
|
HAS_OBJECT_POINTERS
|
2021-11-25 20:42:49 +00:00
|
|
|
// common part of the game actors
|
|
|
|
public:
|
|
|
|
|
2021-12-04 21:04:16 +00:00
|
|
|
// These two are needed because we cannot rely on the ones in the sprites for unlinking.
|
|
|
|
int link_stat;
|
|
|
|
sectortype* link_sector;
|
|
|
|
DCoreActor* prevStat, * nextStat;
|
|
|
|
DCoreActor* prevSect, * nextSect;
|
2022-05-27 11:55:38 +00:00
|
|
|
FWallSpriteInfo* wallspriteinfo; // this is render data but needs to be attached to the actor so it can be found.
|
2021-12-04 21:04:16 +00:00
|
|
|
|
2021-12-05 08:34:30 +00:00
|
|
|
spritetype spr;
|
|
|
|
spriteext_t sprext;
|
|
|
|
spritesmooth_t spsmooth;
|
|
|
|
|
2022-02-03 21:06:09 +00:00
|
|
|
DVector3 opos;
|
2022-01-08 20:18:18 +00:00
|
|
|
int time;
|
2021-12-30 17:21:02 +00:00
|
|
|
int16_t oang;
|
2022-02-13 10:38:21 +00:00
|
|
|
int16_t spritesetindex;
|
|
|
|
|
2021-12-30 17:21:02 +00:00
|
|
|
|
2021-12-05 19:55:19 +00:00
|
|
|
DCoreActor() = default;
|
2021-12-05 08:20:41 +00:00
|
|
|
virtual ~DCoreActor() = default;
|
2021-12-05 19:55:19 +00:00
|
|
|
DCoreActor(const DCoreActor& other) = delete; // we also do not want to allow copies.
|
|
|
|
DCoreActor& operator=(const DCoreActor& other) = delete;
|
|
|
|
|
2021-12-05 08:20:41 +00:00
|
|
|
virtual void Serialize(FSerializer& arc);
|
|
|
|
|
2021-12-06 16:00:15 +00:00
|
|
|
virtual void BeginPlay() {}
|
|
|
|
void OnDestroy() override;
|
2021-12-05 19:55:19 +00:00
|
|
|
size_t PropagateMark() override;
|
2022-08-04 21:48:46 +00:00
|
|
|
int GetOffsetAndHeight(int& height);
|
2021-12-05 19:55:19 +00:00
|
|
|
|
2021-12-03 20:36:32 +00:00
|
|
|
bool exists() const
|
|
|
|
{
|
2021-12-23 22:48:39 +00:00
|
|
|
return (unsigned)spr.statnum < MAXSTATUS;
|
2021-12-03 20:36:32 +00:00
|
|
|
}
|
|
|
|
|
2021-11-25 21:33:55 +00:00
|
|
|
int GetIndex() const
|
2021-11-25 20:42:49 +00:00
|
|
|
{
|
2021-12-22 20:06:31 +00:00
|
|
|
// This is only identical with the sprite index for items spawned at map start.
|
2022-01-08 20:18:18 +00:00
|
|
|
return time;
|
2022-08-08 22:11:21 +00:00
|
|
|
}
|
|
|
|
|
2022-01-31 18:20:53 +00:00
|
|
|
const vec3_t int_pos() const
|
2022-01-30 14:38:30 +00:00
|
|
|
{
|
2022-02-02 23:32:59 +00:00
|
|
|
return { int(spr.pos.X * worldtoint), int(spr.pos.Y * worldtoint), int(spr.pos.Z * zworldtoint) };
|
2022-01-30 14:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void set_int_z(int z)
|
|
|
|
{
|
2022-02-02 23:32:59 +00:00
|
|
|
spr.pos.Z = z * zinttoworld;
|
2022-01-30 14:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void add_int_z(int z)
|
|
|
|
{
|
2022-02-02 23:32:59 +00:00
|
|
|
spr.pos.Z += z * zinttoworld;
|
2022-01-30 14:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void add_int_pos(const vec3_t& add)
|
|
|
|
{
|
2022-02-02 23:32:59 +00:00
|
|
|
spr.pos += { add.X* inttoworld, add.Y* inttoworld, add.Z* zinttoworld };
|
2022-01-30 14:38:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void set_int_pos(const vec3_t& add)
|
|
|
|
{
|
2022-02-02 23:32:59 +00:00
|
|
|
spr.pos = { add.X* inttoworld, add.Y* inttoworld, add.Z* zinttoworld };
|
2022-01-30 14:38:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-02 23:32:59 +00:00
|
|
|
void copyXY(DCoreActor* other)
|
2022-01-30 16:56:38 +00:00
|
|
|
{
|
2022-02-02 23:32:59 +00:00
|
|
|
spr.pos.X = other->spr.pos.X;
|
|
|
|
spr.pos.Y = other->spr.pos.Y;
|
2022-01-30 16:56:38 +00:00
|
|
|
}
|
|
|
|
|
2022-01-30 15:20:11 +00:00
|
|
|
void set_int_xy(int x, int y)
|
|
|
|
{
|
2022-02-02 23:32:59 +00:00
|
|
|
spr.pos.X = x * inttoworld;
|
|
|
|
spr.pos.Y = y * inttoworld;
|
2022-01-30 15:20:11 +00:00
|
|
|
}
|
|
|
|
|
2022-08-16 21:15:16 +00:00
|
|
|
const int16_t int_ang() const
|
|
|
|
{
|
|
|
|
return spr.__int_angle;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_int_ang(int a)
|
|
|
|
{
|
|
|
|
spr.__int_angle = int16_t(a);
|
|
|
|
}
|
|
|
|
|
2022-08-16 21:25:11 +00:00
|
|
|
void add_int_ang(int a)
|
|
|
|
{
|
|
|
|
spr.__int_angle += int16_t(a);
|
|
|
|
}
|
2022-08-16 21:15:16 +00:00
|
|
|
|
2022-08-08 22:11:21 +00:00
|
|
|
// Same as above but with invertex y and z axes to match the renderer's coordinate system.
|
|
|
|
DVector3 render_pos() const
|
|
|
|
{
|
2022-02-02 23:32:59 +00:00
|
|
|
return { spr.pos.X, -spr.pos.Y, -spr.pos.Z };
|
2022-08-08 22:11:21 +00:00
|
|
|
}
|
2022-01-30 13:42:28 +00:00
|
|
|
|
2022-02-03 21:06:09 +00:00
|
|
|
double interpolatedx(double const smoothratio, int const scale = 16)
|
|
|
|
{
|
|
|
|
return interpolatedvaluef(opos.X, spr.pos.X, smoothratio, scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
double interpolatedy(double const smoothratio, int const scale = 16)
|
|
|
|
{
|
|
|
|
return interpolatedvaluef(opos.Y, spr.pos.Y, smoothratio, scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
double interpolatedz(double const smoothratio, int const scale = 16)
|
|
|
|
{
|
|
|
|
return interpolatedvalue(opos.Z, spr.pos.Z, smoothratio, scale);
|
|
|
|
}
|
|
|
|
|
|
|
|
DVector2 interpolatedvec2(double const smoothratio, int const scale = 16)
|
|
|
|
{
|
|
|
|
return
|
|
|
|
{
|
|
|
|
interpolatedx(smoothratio, scale),
|
|
|
|
interpolatedy(smoothratio, scale)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
DVector3 interpolatedvec3(double const smoothratio, int const scale = 16)
|
|
|
|
{
|
|
|
|
return
|
|
|
|
{
|
|
|
|
interpolatedx(smoothratio, scale),
|
|
|
|
interpolatedy(smoothratio, scale),
|
|
|
|
interpolatedz(smoothratio, scale)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-02-03 20:58:28 +00:00
|
|
|
int32_t __interpolatedx(double const smoothratio, int const scale = 16)
|
2021-12-30 16:32:31 +00:00
|
|
|
{
|
2022-02-03 21:06:09 +00:00
|
|
|
return interpolatedx(smoothratio, scale) * worldtoint;
|
2021-12-30 16:32:31 +00:00
|
|
|
}
|
|
|
|
|
2022-02-03 20:58:28 +00:00
|
|
|
int32_t __interpolatedy(double const smoothratio, int const scale = 16)
|
2021-12-30 16:32:31 +00:00
|
|
|
{
|
2022-02-03 21:06:09 +00:00
|
|
|
return interpolatedy(smoothratio, scale) * worldtoint;
|
2021-12-30 16:32:31 +00:00
|
|
|
}
|
|
|
|
|
2022-02-03 20:58:28 +00:00
|
|
|
int32_t __interpolatedz(double const smoothratio, int const scale = 16)
|
2021-12-30 16:32:31 +00:00
|
|
|
{
|
2022-02-03 21:06:09 +00:00
|
|
|
return interpolatedz(smoothratio, scale) * zworldtoint;
|
2021-12-30 16:32:31 +00:00
|
|
|
}
|
|
|
|
|
2022-02-03 20:58:28 +00:00
|
|
|
vec2_t __interpolatedvec2(double const smoothratio, int const scale = 16)
|
2021-12-30 16:32:31 +00:00
|
|
|
{
|
|
|
|
return
|
|
|
|
{
|
2022-02-03 21:06:09 +00:00
|
|
|
(int)(interpolatedx(smoothratio, scale) * worldtoint),
|
|
|
|
(int)(interpolatedy(smoothratio, scale) * worldtoint)
|
2021-12-30 16:32:31 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
int16_t interpolatedang(double const smoothratio)
|
|
|
|
{
|
2022-08-16 21:17:01 +00:00
|
|
|
return interpolatedangle(oang, int_ang(), smoothratio, 16);
|
2021-12-30 16:32:31 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 16:10:08 +00:00
|
|
|
void backupx()
|
|
|
|
{
|
2022-02-03 21:06:09 +00:00
|
|
|
opos.X = spr.pos.X;
|
2021-12-30 16:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void backupy()
|
|
|
|
{
|
2022-02-03 21:06:09 +00:00
|
|
|
opos.Y = spr.pos.Y;
|
2021-12-30 16:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void backupz()
|
|
|
|
{
|
2022-02-03 21:06:09 +00:00
|
|
|
opos.Z = spr.pos.Z;
|
2021-12-30 16:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void backupvec2()
|
|
|
|
{
|
2022-02-03 21:06:09 +00:00
|
|
|
backupx();
|
|
|
|
backupy();
|
2021-12-30 16:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void backuppos()
|
|
|
|
{
|
2022-02-03 21:06:09 +00:00
|
|
|
opos = spr.pos;
|
2021-12-30 16:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void backupang()
|
|
|
|
{
|
2022-08-16 21:17:01 +00:00
|
|
|
oang = int_ang();
|
2021-12-30 16:10:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void backuploc()
|
|
|
|
{
|
|
|
|
backuppos();
|
|
|
|
backupang();
|
|
|
|
}
|
|
|
|
|
2021-11-25 21:33:55 +00:00
|
|
|
sectortype* sector() const
|
2021-11-25 20:42:49 +00:00
|
|
|
{
|
2021-12-30 15:51:56 +00:00
|
|
|
return spr.sectp;
|
2021-11-25 20:42:49 +00:00
|
|
|
}
|
|
|
|
|
2021-11-25 21:33:55 +00:00
|
|
|
bool insector() const
|
|
|
|
{
|
2021-12-30 15:24:51 +00:00
|
|
|
return spr.sectp != nullptr;
|
2021-11-25 21:33:55 +00:00
|
|
|
}
|
2021-11-25 20:42:49 +00:00
|
|
|
|
2021-12-30 15:36:04 +00:00
|
|
|
void setsector(sectortype* sect)
|
|
|
|
{
|
|
|
|
// place for asserts.
|
|
|
|
spr.sectp = sect;
|
|
|
|
}
|
|
|
|
|
2021-12-30 15:39:43 +00:00
|
|
|
int sectno() const
|
|
|
|
{
|
|
|
|
return spr.sectp ? ::sector.IndexOf(spr.sectp) : -1;
|
|
|
|
}
|
|
|
|
|
2022-02-20 23:12:51 +00:00
|
|
|
auto spriteset() const
|
|
|
|
{
|
|
|
|
return static_cast<PClassActor*>(GetClass())->ActorInfo()->SpriteSet;
|
|
|
|
}
|
2021-12-30 15:39:43 +00:00
|
|
|
|
2021-11-25 20:42:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// holds pointers to the game-side actors.
|
|
|
|
extern TArray<sectortype> sector;
|
|
|
|
extern TArray<walltype> wall;
|
|
|
|
|
|
|
|
|
|
|
|
// Masking these into the object index to keep it in 16 bit was probably the single most dumbest and pointless thing Build ever did.
|
|
|
|
// Gonna be fun to globally replace these to finally lift the limit this imposes on map size.
|
|
|
|
// Names taken from DukeGDX
|
|
|
|
enum EHitBits
|
|
|
|
{
|
2021-12-29 18:41:41 +00:00
|
|
|
kHitNone = 0,
|
|
|
|
kHitTypeMask = 0xC000,
|
|
|
|
kHitTypeMaskSW = 0x1C000, // SW has one more relevant bit
|
|
|
|
kHitIndexMask = 0x3FFF,
|
|
|
|
kHitSector = 0x4000,
|
|
|
|
kHitWall = 0x8000,
|
|
|
|
kHitSprite = 0xC000,
|
|
|
|
kHitVoid = 0x10000, // SW only
|
2021-11-25 20:42:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
// This serves as input/output for all functions dealing with collisions, hits, etc.
|
|
|
|
// Not all utilities use all variables.
|
|
|
|
struct HitInfoBase
|
|
|
|
{
|
|
|
|
vec3_t hitpos;
|
|
|
|
sectortype* hitSector;
|
|
|
|
walltype* hitWall;
|
2021-12-29 18:41:41 +00:00
|
|
|
DCoreActor* hitActor;
|
2021-11-25 20:42:49 +00:00
|
|
|
|
2021-11-26 12:41:15 +00:00
|
|
|
void clearObj()
|
|
|
|
{
|
|
|
|
hitSector = nullptr;
|
|
|
|
hitWall = nullptr;
|
|
|
|
hitActor = nullptr;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
struct THitInfo : public HitInfoBase
|
|
|
|
{
|
|
|
|
T* actor() const { return static_cast<T*>(hitActor); }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct CollisionBase
|
|
|
|
{
|
|
|
|
int type;
|
2021-11-26 13:26:03 +00:00
|
|
|
int exbits; // extended game-side info (only used by Exhumed)
|
2021-11-26 12:41:15 +00:00
|
|
|
union
|
|
|
|
{
|
|
|
|
// can only have one at a time
|
|
|
|
sectortype* hitSector;
|
|
|
|
walltype* hitWall;
|
|
|
|
DCoreActor* hitActor;
|
|
|
|
};
|
2021-11-25 20:42:49 +00:00
|
|
|
|
|
|
|
void invalidate()
|
|
|
|
{
|
|
|
|
type = -1; // something invalid that's not a valid hit type.
|
2021-11-26 12:41:15 +00:00
|
|
|
hitSector = nullptr;
|
2021-11-25 20:42:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int setNone()
|
|
|
|
{
|
|
|
|
*this = {};
|
|
|
|
return kHitNone;
|
|
|
|
}
|
|
|
|
|
|
|
|
int setSector(int num)
|
|
|
|
{
|
|
|
|
*this = {};
|
|
|
|
type = kHitSector;
|
|
|
|
hitSector = §or[num];
|
|
|
|
return kHitSector;
|
|
|
|
}
|
|
|
|
|
2021-11-26 00:01:16 +00:00
|
|
|
int setSector(sectortype* num)
|
|
|
|
{
|
|
|
|
*this = {};
|
|
|
|
type = kHitSector;
|
|
|
|
hitSector = num;
|
|
|
|
return kHitSector;
|
|
|
|
}
|
|
|
|
|
2021-11-25 20:42:49 +00:00
|
|
|
int setWall(int num)
|
|
|
|
{
|
|
|
|
*this = {};
|
|
|
|
type = kHitWall;
|
|
|
|
hitWall = &wall[num];
|
|
|
|
return kHitWall;
|
|
|
|
}
|
|
|
|
|
2021-11-26 00:01:16 +00:00
|
|
|
int setWall(walltype* num)
|
|
|
|
{
|
|
|
|
*this = {};
|
|
|
|
type = kHitWall;
|
|
|
|
hitWall = num;
|
|
|
|
return kHitWall;
|
|
|
|
}
|
|
|
|
|
2021-11-25 21:33:55 +00:00
|
|
|
int setSprite(DCoreActor* num)
|
2021-11-25 20:42:49 +00:00
|
|
|
{
|
|
|
|
*this = {};
|
|
|
|
type = kHitSprite;
|
|
|
|
hitActor = num;
|
|
|
|
return kHitSprite;
|
|
|
|
}
|
|
|
|
|
2021-11-26 12:41:15 +00:00
|
|
|
int setVoid()
|
|
|
|
{
|
|
|
|
hitSector = nullptr;
|
2021-11-25 20:42:49 +00:00
|
|
|
type = kHitVoid;
|
2021-11-26 12:41:15 +00:00
|
|
|
return kHitVoid;
|
2021-11-25 20:42:49 +00:00
|
|
|
}
|
|
|
|
};
|
2021-11-25 21:33:55 +00:00
|
|
|
|
2021-11-26 12:00:33 +00:00
|
|
|
template<class T>
|
2021-11-26 12:41:15 +00:00
|
|
|
struct TCollision : public CollisionBase
|
2021-11-26 12:00:33 +00:00
|
|
|
{
|
2021-12-05 19:55:19 +00:00
|
|
|
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;
|
|
|
|
}
|
2021-11-26 12:00:33 +00:00
|
|
|
};
|
2021-11-25 21:33:55 +00:00
|
|
|
|
2021-11-26 12:41:15 +00:00
|
|
|
|
2021-12-04 21:04:16 +00:00
|
|
|
struct ActorStatList
|
|
|
|
{
|
|
|
|
DCoreActor* firstEntry, * lastEntry;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern ActorStatList statList[MAXSTATUS];
|
2021-11-26 12:41:15 +00:00
|
|
|
|
2021-11-25 21:33:55 +00:00
|
|
|
template<class TActor>
|
2021-12-04 21:04:16 +00:00
|
|
|
class TStatIterator
|
2021-11-25 21:33:55 +00:00
|
|
|
{
|
2021-12-04 21:04:16 +00:00
|
|
|
DCoreActor* next;
|
2021-11-25 21:33:55 +00:00
|
|
|
public:
|
2021-12-04 21:04:16 +00:00
|
|
|
TStatIterator(int stat)
|
|
|
|
{
|
|
|
|
next = statList[stat].firstEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Reset(int stat)
|
2021-11-25 21:33:55 +00:00
|
|
|
{
|
2021-12-04 21:04:16 +00:00
|
|
|
next = statList[stat].firstEntry;
|
2021-11-25 21:33:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TActor* Next()
|
|
|
|
{
|
2021-12-04 21:04:16 +00:00
|
|
|
auto n = next;
|
|
|
|
if (next) next = next->nextStat;
|
|
|
|
return static_cast<TActor*>(n);
|
2021-11-25 21:33:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TActor* Peek()
|
|
|
|
{
|
2021-12-04 21:04:16 +00:00
|
|
|
return static_cast<TActor*>(next);
|
2021-11-25 21:33:55 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class TActor>
|
2021-12-04 21:04:16 +00:00
|
|
|
class TSectIterator
|
2021-11-25 21:33:55 +00:00
|
|
|
{
|
2021-12-04 21:04:16 +00:00
|
|
|
DCoreActor* next;
|
2021-11-25 21:33:55 +00:00
|
|
|
public:
|
2021-12-04 21:04:16 +00:00
|
|
|
//[[deprecated]]
|
|
|
|
TSectIterator(int stat)
|
|
|
|
{
|
|
|
|
next = sector[stat].firstEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
TSectIterator(sectortype* stat)
|
2021-11-25 21:33:55 +00:00
|
|
|
{
|
2021-12-04 21:04:16 +00:00
|
|
|
next = stat->firstEntry;
|
2021-11-25 21:33:55 +00:00
|
|
|
}
|
|
|
|
|
2021-12-04 21:04:16 +00:00
|
|
|
//[[deprecated]]
|
|
|
|
void Reset(int stat)
|
2021-11-25 21:33:55 +00:00
|
|
|
{
|
2021-12-04 21:04:16 +00:00
|
|
|
next = sector[stat].firstEntry;
|
2021-11-25 21:33:55 +00:00
|
|
|
}
|
|
|
|
|
2021-12-04 21:04:16 +00:00
|
|
|
void Reset(sectortype* stat)
|
|
|
|
{
|
|
|
|
next = stat->firstEntry;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-25 21:33:55 +00:00
|
|
|
TActor* Next()
|
|
|
|
{
|
2021-12-04 21:04:16 +00:00
|
|
|
auto n = next;
|
|
|
|
if (next) next = next->nextSect;
|
|
|
|
return static_cast<TActor*>(n);
|
2021-11-25 21:33:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TActor* Peek()
|
|
|
|
{
|
2021-12-04 21:04:16 +00:00
|
|
|
return static_cast<TActor*>(next);
|
2021-11-25 21:33:55 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// An iterator to iterate over all sprites.
|
|
|
|
template<class TActor>
|
|
|
|
class TSpriteIterator
|
|
|
|
{
|
|
|
|
TStatIterator<TActor> it;
|
|
|
|
int stat = 0;
|
|
|
|
|
|
|
|
public:
|
|
|
|
TSpriteIterator() : it(0) {}
|
|
|
|
|
|
|
|
TActor* Next()
|
|
|
|
{
|
|
|
|
while (stat < MAXSTATUS)
|
|
|
|
{
|
|
|
|
auto ac = it.Next();
|
|
|
|
if (ac) return ac;
|
|
|
|
stat++;
|
|
|
|
if (stat < MAXSTATUS) it.Reset(stat);
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
2021-12-03 20:36:32 +00:00
|
|
|
|
|
|
|
void Reset()
|
|
|
|
{
|
|
|
|
stat = 0;
|
|
|
|
it.Reset(0);
|
|
|
|
}
|
2021-11-25 21:33:55 +00:00
|
|
|
};
|
|
|
|
|
2021-11-26 20:52:01 +00:00
|
|
|
using CoreSectIterator = TSectIterator<DCoreActor>;
|
|
|
|
|
2021-12-06 16:00:15 +00:00
|
|
|
DCoreActor* InsertActor(PClass* type, sectortype* sector, int stat, bool forcetail = false);
|
2021-12-04 21:04:16 +00:00
|
|
|
void ChangeActorSect(DCoreActor* actor, sectortype* sector, bool forcetail = false);
|
|
|
|
int ChangeActorStat(DCoreActor* actor, int nStatus, bool forcetail = false);
|
|
|
|
void InitSpriteLists();
|
2021-11-26 20:52:01 +00:00
|
|
|
|
|
|
|
|
2021-12-03 19:20:33 +00:00
|
|
|
void SetActorZ(DCoreActor* actor, const vec3_t* newpos);
|
|
|
|
void SetActor(DCoreActor* actor, const vec3_t* newpos);
|
2021-11-26 20:52:01 +00:00
|
|
|
|
2021-12-03 19:20:33 +00:00
|
|
|
inline void SetActor(DCoreActor* actor, const vec3_t& newpos)
|
2021-11-26 20:52:01 +00:00
|
|
|
{
|
2021-12-03 19:20:33 +00:00
|
|
|
SetActor(actor, &newpos);
|
2021-11-26 20:52:01 +00:00
|
|
|
}
|
|
|
|
|
2022-02-01 23:00:54 +00:00
|
|
|
inline void SetActorZ(DCoreActor* actor, const vec3_t& newpos)
|
|
|
|
{
|
|
|
|
SetActorZ(actor, &newpos);
|
|
|
|
}
|
2021-11-25 21:33:55 +00:00
|
|
|
|
2022-02-05 09:16:50 +00:00
|
|
|
inline void SetActor(DCoreActor* actor, const DVector3& newpos)
|
|
|
|
{
|
|
|
|
vec3_t ipos = { int(newpos.X * worldtoint), int(newpos.Y * worldtoint), int(newpos.Z * zworldtoint) };
|
|
|
|
SetActor(actor, &ipos);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void SetActorZ(DCoreActor* actor, const DVector3& newpos)
|
|
|
|
{
|
|
|
|
vec3_t ipos = { int(newpos.X * worldtoint), int(newpos.Y * worldtoint), int(newpos.Z * zworldtoint) };
|
|
|
|
SetActorZ(actor, &ipos);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-26 12:41:15 +00:00
|
|
|
|
|
|
|
inline int clipmove(vec3_t& pos, sectortype** const sect, int xvect, int yvect,
|
|
|
|
int const walldist, int const ceildist, int const flordist, unsigned const cliptype, CollisionBase& result, int clipmoveboxtracenum = 3)
|
|
|
|
{
|
|
|
|
int sectno = *sect ? sector.IndexOf(*sect) : -1;
|
2021-12-04 00:05:18 +00:00
|
|
|
result = clipmove_(&pos, §no, xvect, yvect, walldist, ceildist, flordist, cliptype, clipmoveboxtracenum);
|
2021-11-26 12:41:15 +00:00
|
|
|
*sect = sectno == -1 ? nullptr : §or[sectno];
|
2021-12-04 00:05:18 +00:00
|
|
|
return result.type;
|
2021-11-26 12:41:15 +00:00
|
|
|
}
|
2021-11-26 17:59:28 +00:00
|
|
|
|
2022-02-05 09:16:50 +00:00
|
|
|
inline int clipmove(DVector3& pos, sectortype** const sect, int xvect, int yvect,
|
|
|
|
int const walldist, int const ceildist, int const flordist, unsigned const cliptype, CollisionBase& result, int clipmoveboxtracenum = 3)
|
|
|
|
{
|
|
|
|
auto vect = vec3_t(pos.X * worldtoint, pos.Y * worldtoint, pos.Z * zworldtoint);
|
|
|
|
int res = clipmove(vect, sect, xvect, yvect, walldist, ceildist, flordist, cliptype, result, clipmoveboxtracenum);
|
|
|
|
pos = { vect.X * inttoworld, vect.Y * inttoworld, vect.Z * zinttoworld };
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-26 19:41:03 +00:00
|
|
|
inline int pushmove(vec3_t* const vect, sectortype** const sect, int32_t const walldist, int32_t const ceildist, int32_t const flordist,
|
|
|
|
uint32_t const cliptype, bool clear = true)
|
|
|
|
{
|
|
|
|
int sectno = *sect ? sector.IndexOf(*sect) : -1;
|
|
|
|
int res = pushmove_(vect, §no, walldist, ceildist, flordist, cliptype, clear);
|
|
|
|
*sect = sectno == -1 ? nullptr : §or[sectno];
|
|
|
|
return res;
|
|
|
|
}
|
2021-12-04 18:08:50 +00:00
|
|
|
|
2022-02-05 09:16:50 +00:00
|
|
|
inline int pushmove(DVector3& pos, sectortype** const sect, int32_t const walldist, int32_t const ceildist, int32_t const flordist,
|
2022-01-30 16:56:38 +00:00
|
|
|
uint32_t const cliptype, bool clear = true)
|
|
|
|
{
|
2022-02-05 09:16:50 +00:00
|
|
|
auto vect = vec3_t(pos.X * worldtoint, pos.Y * worldtoint, pos.Z * zworldtoint);
|
2022-01-30 16:56:38 +00:00
|
|
|
int sectno = *sect ? sector.IndexOf(*sect) : -1;
|
|
|
|
int res = pushmove_(&vect, §no, walldist, ceildist, flordist, cliptype, clear);
|
2022-02-05 09:16:50 +00:00
|
|
|
pos = { vect.X * inttoworld, vect.Y * inttoworld, vect.Z * zinttoworld };
|
2022-01-30 16:56:38 +00:00
|
|
|
*sect = sectno == -1 ? nullptr : §or[sectno];
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2022-02-05 09:16:50 +00:00
|
|
|
inline int pushmove(DCoreActor* actor, sectortype** const sect, int32_t const walldist, int32_t const ceildist, int32_t const flordist,
|
|
|
|
uint32_t const cliptype, bool clear = true)
|
|
|
|
{
|
|
|
|
return pushmove(actor->spr.pos, sect, walldist, ceildist, flordist, cliptype, clear);
|
|
|
|
}
|
|
|
|
|
2022-08-07 08:25:15 +00:00
|
|
|
tspritetype* renderAddTsprite(tspriteArray& tsprites, DCoreActor* actor);
|
2022-01-23 08:54:49 +00:00
|
|
|
|
|
|
|
inline PClassActor* PClass::FindActor(FName name)
|
|
|
|
{
|
|
|
|
auto cls = FindClass(name);
|
|
|
|
return cls && cls->IsDescendantOf(RUNTIME_CLASS(DCoreActor)) ? static_cast<PClassActor*>(cls) : nullptr;
|
|
|
|
}
|
2022-01-23 09:54:56 +00:00
|
|
|
|
|
|
|
inline DCoreActor* GetDefaultByType(const PClass* type)
|
|
|
|
{
|
|
|
|
return (DCoreActor*)(type->Defaults);
|
|
|
|
}
|
|
|
|
|