- setup for Duke actor data transition to something more scripting friendly.

The main problem here is that there's two data arrays representing an actor - sprite and hittype and the engine only uses indices for reference.
By setting up hittype to contain a sprite reference, the function and iterator interface can be rewritten to use a single pointer instead to represent an actor.
The main objective is to reduce the number of accesses to the global arrays which constitute the biggest refactoring blocker.
This commit is contained in:
Christoph Oelckers 2020-10-17 09:06:09 +02:00
parent 05c095e448
commit 78afb67c7f
6 changed files with 30 additions and 49 deletions

View file

@ -903,7 +903,7 @@ static spriteext_t spriteext_s[MAXSPRITES+MAXUNIQHUDID];
static spritesmooth_t spritesmooth_s[MAXSPRITES+MAXUNIQHUDID];
static sectortype sector_s[MAXSECTORS];
static walltype wall_s[MAXWALLS];
static spritetype sprite_s[MAXSPRITES];
spritetype sprite_s[MAXSPRITES];
static tspritetype tsprite_s[MAXSPRITESONSCREEN];
int32_t enginePreInit(void)

View file

@ -73,7 +73,7 @@ uint8_t sectorextra[MAXSECTORS]; // move these back into the base structs!
int rtsplaying;
int tempwallptr;
weaponhit hittype[MAXSPRITES];
weaponhit hittype[MAXSPRITES+1]; // +1 to have a blank entry for serialization.
bool sound445done; // this was local state inside a function, but this must be maintained globally and serialized
uint16_t frags[MAXPLAYERS][MAXPLAYERS];
player_struct ps[MAXPLAYERS];

View file

@ -59,7 +59,7 @@ extern uint8_t sectorextra[MAXSECTORS]; // these hold fields that were formerly
extern int rtsplaying;
extern int tempwallptr;
extern weaponhit hittype[MAXSPRITES];
extern bool sound445done;
extern uint16_t frags[MAXPLAYERS][MAXPLAYERS];
extern player_struct ps[MAXPLAYERS];

View file

@ -684,7 +684,7 @@ void prelevel_common(int g)
resetprestat(0, g);
numclouds = 0;
memset(hittype, 0, sizeof(hittype));
for (auto& h : hittype) h.clear();
memset(sectorextra, 0, sizeof(sectorextra));
memset(shadedsector, 0, sizeof(shadedsector));
memset(geosectorwarp, -1, sizeof(geosectorwarp));

View file

@ -31,6 +31,8 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
#include "duke3d.h"
#include "gamestate.h"
extern FixedBitArray<MAXSPRITES> activeSprites;
BEGIN_DUKE_NS
@ -293,8 +295,10 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, player_struct& w,
return arc;
}
FSerializer& Serialize(FSerializer& arc, const char* keyname, weaponhit& w, weaponhit* def)
{
if (!def) def = &hittype[MAXSPRITES];
if (arc.BeginObject(keyname))
{
arc("cgg", w.cgg, def->cgg)
@ -327,7 +331,7 @@ void GameInterface::SerializeGameState(FSerializer& arc)
{
if (arc.isReading())
{
memset(hittype, 0, sizeof(hittype));
for (auto& h : hittype) h.clear();
memset(sectorextra, 0, sizeof(sectorextra));
memset(shadedsector, 0, sizeof(shadedsector));
memset(geosectorwarp, -1, sizeof(geosectorwarp));
@ -340,42 +344,8 @@ void GameInterface::SerializeGameState(FSerializer& arc)
arc("multimode", ud.multimode);
if (ud.multimode > 1) arc.Array("frags", &frags[0][0], MAXPLAYERS * MAXPLAYERS);
// Here we must only save the used entries, otherwise the savegame would get too large.
weaponhit def = {};
if (arc.isWriting())
{
if (arc.BeginArray("weaponhit"))
{
// Save this in a way that's easy to read out again. RapidJSON sucks at iterating over objects. :(
for (int i = 0; i < MAXSPRITES; i++)
{
if (sprite[i].statnum != MAXSTATUS)
{
arc(nullptr, i);
arc(nullptr, hittype[i], def);
}
}
}
arc.EndArray();
}
else
{
if (arc.BeginArray("weaponhit"))
{
auto s = arc.ArraySize()/2;
for (unsigned i = 0; i < s; i++)
{
int ii;
arc(nullptr, ii);
arc(nullptr, hittype[ii], def);
}
arc.EndArray();
}
}
arc("skill", ud.player_skill)
arc.SparseArray("actors", hittype, MAXSPRITES, activeSprites)
("skill", ud.player_skill)
("from_bonus", ud.from_bonus)
("secretlevel", ud.secretlevel)
("respawn_monsters", ud.respawn_monsters)

View file

@ -4,6 +4,8 @@
#include "d_net.h"
#include "gameinput.h"
extern spritetype sprite_s[];
BEGIN_DUKE_NS
// all the struct types from JFDuke's duke3d.h
@ -28,16 +30,25 @@ struct weaponhit
short timetosleep;
int floorz, ceilingz, lastvx, lastvy, bposx, bposy, bposz, aflags;
int temp_data[6];
};
spritetype& s; // direct reference to the corresponding sprite.
// This is how a Duke actor should later be exposed to scripting. The object definition parts are disabled for now so that this can be used already to transition the code.
class DDukeActor //: public DBuildActor
{
public:
//DECLARE_CLASS(DDukeActor, DBuildActor)
spritetype s;
weaponhit h;
static weaponhit* array(); // this is necessary to allow define inline functions referencing the global array inside the definition itself.
weaponhit() : s(sprite_s[this - array()]) {} // little trick to initialize the reference automatically. ;)
weaponhit(const weaponhit& other) = delete; // we also do not want to allow copies.
weaponhit& operator=(const weaponhit& other) = delete;
void clear()
{
cgg = spriteextra = 0;
picnum = ang = extra = owner = movflag = tempang = actorstayput = dispicnum = timetosleep = 0;
floorz = ceilingz = lastvx = lastvy = bposx = bposy = bposz = aflags = 0;
memset(temp_data, 0, sizeof(temp_data));
}
};
extern weaponhit hittype[MAXSPRITES + 1];
inline weaponhit* weaponhit::array() { return hittype; }
using DDukeActor = weaponhit; // we do not really want that stupid name in our interface (but also not rename the struct yet.)
struct animwalltype
{