Added MemArchive feature from mohaas/mohaab

This commit is contained in:
smallmodel 2023-09-06 23:11:43 +02:00
parent b4d8982341
commit 9a104566ba
No known key found for this signature in database
GPG key ID: 9F2D623CEDF08512
4 changed files with 695 additions and 20 deletions

View file

@ -22,44 +22,175 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
#include "cg_archive.h"
#include "cg_commands.h"
#include "memarchiver.h"
#include "../qcommon/tiki.h"
void CG_ArchiveStuff(MemArchiver& archiver, int svsTime)
{
// FIXME: unimplemented
archiver.SetBaseTime(svsTime);
commandManager.ArchiveToMemory(archiver);
CG_ArchiveVSSGlobals(archiver);
}
size_t CG_SaveStateToBuffer(void** out, int svsTime)
{
// FIXME: unimplemented
return 0;
MemArchiver archiver;
size_t size;
archiver.SetupForWriting(0x200000);
CG_ArchiveStuff(archiver, svsTime);
size = archiver.BufferSize();
if (size && out) {
*out = archiver.ConfiscateBuffer();
}
return size;
}
void CG_LoadStateToBuffer(void* state, size_t size, int svsTime)
qboolean CG_LoadStateToBuffer(void* state, size_t size, int svsTime)
{
// FIXME: unimplemented
MemArchiver archiver;
archiver.SetupForReading((byte*)state, size);
CG_ArchiveStuff(archiver, svsTime);
return archiver.FinishedReading();
}
void CG_ArchiveStringContainer(MemArchiver& archiver, Container<str>* container)
{
// FIXME: unimplemented
int num;
int i;
if (archiver.IsReading()) {
str tmp;
archiver.ArchiveInteger(&num);
container->ClearObjectList();
for (i = 0; i < num; i++) {
archiver.ArchiveString(&tmp);
container->AddObject(tmp);
}
} else {
num = container->NumObjects();
archiver.ArchiveInteger(&num);
for (i = 0; i < num; i++) {
str& tmp = container->ObjectAt(i);
archiver.ArchiveString(&tmp);
}
}
}
void CG_ArchiveTikiPointer(MemArchiver& archiver, dtiki_t** pTiki)
{
// FIXME: unimplemented
str tmp;
if (archiver.IsReading()) {
archiver.ArchiveString(&tmp);
if (tmp.length()) {
*pTiki = cgi.R_Model_GetHandle(cgi.R_RegisterModel(tmp.c_str()));
} else {
*pTiki = NULL;
}
} else {
if (*pTiki) {
tmp = (*pTiki)->name;
}
archiver.ArchiveString(&tmp);
}
}
void CG_ArchiveModelHandle(MemArchiver& archiver, qhandle_t* handle)
{
// FIXME: unimplemented
str tmp;
if (archiver.IsReading()) {
archiver.ArchiveString(&tmp);
if (tmp.length()) {
*handle = cgi.R_RegisterModel(tmp.c_str());
} else {
*handle = NULL;
}
} else {
if (*handle) {
tmp = cgi.R_GetModelName(*handle);
} else {
tmp = "";
}
archiver.ArchiveString(&tmp);
}
}
void CG_ArchiveShaderHandle(MemArchiver& archiver, qhandle_t* handle)
{
// FIXME: unimplemented
str tmp;
if (archiver.IsReading()) {
archiver.ArchiveString(&tmp);
if (tmp.length()) {
*handle = cgi.R_RegisterShader(tmp.c_str());
} else {
*handle = NULL;
}
} else {
if (*handle) {
tmp = cgi.R_GetShaderName(*handle);
} else {
tmp = "";
}
archiver.ArchiveString(&tmp);
}
}
void CG_ArchiveRefEntity(MemArchiver& archiver, refEntity_t* ref)
{
// FIXME: unimplemented
archiver.ArchiveRaw(&ref->reType, sizeof(ref->reType));
archiver.ArchiveInteger(&ref->renderfx);
CG_ArchiveModelHandle(archiver, &ref->hModel);
CG_ArchiveModelHandle(archiver, &ref->hOldModel);
archiver.ArchiveVec3(ref->lightingOrigin);
archiver.ArchiveInteger(&ref->parentEntity);
archiver.ArchiveVec3(ref->axis[0]);
archiver.ArchiveVec3(ref->axis[1]);
archiver.ArchiveVec3(ref->axis[2]);
archiver.ArchiveBoolean(&ref->nonNormalizedAxes);
archiver.ArchiveVec3(ref->origin);
archiver.ArchiveRaw(ref->frameInfo, 192);
archiver.ArchiveFloat(&ref->actionWeight);
archiver.ArchiveShort(&ref->wasframe);
archiver.ArchiveFloat(&ref->scale);
archiver.ArchiveVec3(ref->oldorigin);
archiver.ArchiveInteger(&ref->skinNum);
CG_ArchiveShaderHandle(archiver, &ref->customShader);
archiver.ArchiveRaw(ref->shaderRGBA, 4);
archiver.ArchiveFloat(ref->shaderTexCoord);
archiver.ArchiveFloat(&ref->shaderTexCoord[1]);
archiver.ArchiveFloat(&ref->shaderTime);
archiver.ArchiveInteger(&ref->entityNumber);
archiver.ArchiveRaw(ref->surfaces, 32);
archiver.ArchiveFloat(ref->shader_data);
archiver.ArchiveFloat(&ref->shader_data[1]);
ref->bone_tag = NULL;
ref->bone_quat = NULL;
ref->of = NULL;
ref->nf = NULL;
CG_ArchiveTikiPointer(archiver, &ref->tiki);
archiver.ArchiveInteger(&ref->bonestart);
archiver.ArchiveInteger(&ref->morphstart);
archiver.ArchiveBoolean(&ref->hasMorph);
archiver.ArchiveFloat(&ref->radius);
archiver.ArchiveFloat(&ref->rotation);
}

View file

@ -36,7 +36,7 @@ extern "C" {
#endif
size_t CG_SaveStateToBuffer(void** out, int svsTime);
void CG_LoadStateToBuffer(void* state, size_t size, int svsTime);
qboolean CG_LoadStateToBuffer(void* state, size_t size, int svsTime);
#ifdef __cplusplus
void CG_ArchiveStuff(MemArchiver& archiver, int svsTime);

View file

@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_specialfx.h"
#include "scriptexception.h"
#include "tiki.h"
#include "cg_archive.h"
#include "memarchiver.h"
refEntity_t *current_entity = NULL;
int current_entity_number = -1;
@ -5404,3 +5406,469 @@ void ClientGameCommandManager::EventViewKick(Event *ev)
cg.viewkick[1] = -fYawMax;
}
}
int ClientGameCommandManager::IdForTempModel(const ctempmodel_t* model)
{
int index;
if (model == &m_active_tempmodels) {
return -1;
}
if (!model) {
return -2;
}
index = model - m_tempmodels;
if (index >= MAX_TEMPMODELS) {
return -2;
}
if (model != &m_tempmodels[index]) {
return -2;
}
return model - m_tempmodels;
}
ctempmodel_t* ClientGameCommandManager::TempModelForId(int id)
{
if (id == -1) {
return &m_active_tempmodels;
}
if (id == -2) {
return NULL;
}
return &m_tempmodels[id];
}
int ClientGameCommandManager::IdForSpawnThing(const spawnthing_t* sp)
{
int i;
if (!sp) {
return 0;
}
for (i = 1; i <= m_emitters.NumObjects(); i++) {
if (sp == m_emitters.ObjectAt(i)) {
return i;
}
}
return 0;
}
spawnthing_t* ClientGameCommandManager::SpawnThingForId(int id)
{
if (!id) {
return 0;
}
return m_emitters.ObjectAt(id);
}
int ClientGameCommandManager::IdForVssSource(const cvssource_t* source)
{
int index;
if (source == &m_active_vsssources) {
return -1;
}
if (!source) {
return -2;
}
index = source - m_vsssources;
if (index < 0 || index >= m_iAllocatedvsssources) {
return -2;
}
if (source != &m_vsssources[index]) {
return -2;
}
return source - m_vsssources;
}
cvssource_t* ClientGameCommandManager::VssSourceForId(int id)
{
if (id == -1) {
return &m_active_vsssources;
}
if (id == -2) {
return 0;
}
return &m_vsssources[id];
}
void ClientGameCommandManager::ArchiveTempModelPointerToMemory(MemArchiver& archiver, ctempmodel_t** model)
{
int id;
if (archiver.IsReading()) {
archiver.ArchiveInteger(&id);
*model = TempModelForId(id);
} else {
id = IdForTempModel(*model);
archiver.ArchiveInteger(&id);
}
}
void ClientGameCommandManager::ArchiveSpawnThingPointerToMemory(MemArchiver& archiver, spawnthing_t** sp)
{
int id;
if (archiver.IsReading()) {
archiver.ArchiveInteger(&id);
*sp = SpawnThingForId(id);
} else {
id = IdForSpawnThing(*sp);
archiver.ArchiveInteger(&id);
}
}
void ClientGameCommandManager::ArchiveVssSourcePointerToMemory(MemArchiver& archiver, cvssource_t** source)
{
int id;
if (archiver.IsReading()) {
archiver.ArchiveInteger(&id);
*source = VssSourceForId(id);
} else {
id = IdForVssSource(*source);
archiver.ArchiveInteger(&id);
}
}
void ClientGameCommandManager::ArchiveToMemory(MemArchiver& archiver)
{
spawnthing_t* sp;
int num;
int i;
m_localemitter.ArchiveToMemory(archiver);
if (archiver.IsReading()) {
archiver.ArchiveInteger(&num);
for (i = 0; i < num; i++) {
sp = new spawnthing_t();
sp->ArchiveToMemory(archiver);
m_emitters.AddObjectAt(i + 1, sp);
}
} else {
num = m_emitters.NumObjects();
archiver.ArchiveInteger(&num);
for (i = 0; i < num; i++) {
sp = m_emitters.ObjectAt(i);
sp->ArchiveToMemory(archiver);
}
}
ArchiveTempModelPointerToMemory(archiver, &m_active_tempmodels.prev);
ArchiveTempModelPointerToMemory(archiver, &m_active_tempmodels.next);
ArchiveTempModelPointerToMemory(archiver, &m_free_tempmodels);
for (i = 0; i < MAX_TEMPMODELS; i++) {
m_tempmodels[i].ArchiveToMemory(archiver);
}
if (archiver.IsReading()) {
archiver.ArchiveInteger(&num);
if (m_iAllocatedvsssources != num) {
m_iAllocatedvsssources = num;
m_vsssources = (cvssource_t*)cgi.Malloc(m_iAllocatedvsssources * sizeof(cvssource_t));
// instead of using memset, call the constructor
for (i = 0; i < m_iAllocatedvsssources; i++) {
new (&m_vsssources[i]) cvssource_t();
}
}
} else {
archiver.ArchiveInteger(&m_iAllocatedvsssources);
}
ArchiveVssSourcePointerToMemory(archiver, &m_active_vsssources.prev);
ArchiveVssSourcePointerToMemory(archiver, &m_active_vsssources.next);
ArchiveVssSourcePointerToMemory(archiver, &m_free_vsssources);
for (i = 0; i < m_iAllocatedvsssources; i++) {
m_vsssources[i].ArchiveToMemory(archiver);
}
archiver.ArchiveTime(&m_iLastVSSRepulsionTime);
m_command_time_manager.ArchiveToMemory(archiver);
archiver.ArchiveInteger(&m_seed);
archiver.ArchiveFloat(&m_fEventWait);
m_pCurrentSfx = NULL;
}
void commandthing_t::ArchiveToMemory(MemArchiver& archiver)
{
int num;
int i;
enttracker_t::ArchiveToMemory(archiver);
if (archiver.IsReading()) {
archiver.ArchiveInteger(&num);
for (i = 0; i < num; i++) {
commandtime_t ct;
ct.ArchiveToMemory(archiver);
m_commandtimes.AddObject(ct);
}
} else {
archiver.ArchiveInteger(&num);
m_commandtimes.ClearObjectList();
for (i = 0; i < num; i++) {
commandtime_t& ct = m_commandtimes.ObjectAt(i);
ct.ArchiveToMemory(archiver);
}
}
// FIXME: unimplemented
}
void cvssource_t::ArchiveToMemory(MemArchiver& archiver)
{
commandManager.ArchiveVssSourcePointerToMemory(archiver, &next);
commandManager.ArchiveVssSourcePointerToMemory(archiver, &prev);
commandManager.ArchiveVssSourcePointerToMemory(archiver, &stnext);
archiver.ArchiveInteger(&stindex);
archiver.ArchiveVector(&lastOrigin);
archiver.ArchiveFloat(&lastRadius);
archiver.ArchiveFloat(&lastDensity);
archiver.ArchiveVec3(lastColor);
archiver.ArchiveVec3(lastLighting);
archiver.ArchiveVector(&newOrigin);
archiver.ArchiveFloat(&newRadius);
archiver.ArchiveFloat(&newDensity);
archiver.ArchiveVec3(newColor);
archiver.ArchiveVec3(newLighting);
archiver.ArchiveFloat(&ooRadius);
archiver.ArchiveVector(&velocity);
archiver.ArchiveFloat(&startAlpha);
archiver.ArchiveInteger(&roll);
archiver.ArchiveVector(&repulsion);
archiver.ArchiveInteger(&lifeTime);
archiver.ArchiveInteger(&collisionmask);
archiver.ArchiveInteger(&parent);
archiver.ArchiveInteger(&flags);
archiver.ArchiveInteger(&flags2);
archiver.ArchiveInteger(&smokeType);
archiver.ArchiveFloat(&typeInfo);
archiver.ArchiveFloat(&fadeMult);
archiver.ArchiveFloat(&scaleMult);
archiver.ArchiveTime(&lastPhysicsTime);
archiver.ArchiveTime(&lastLightingTime);
archiver.ArchiveBoolean(&lastValid);
}
void ctempmodel_t::ArchiveToMemory(MemArchiver& archiver)
{
commandManager.ArchiveTempModelPointerToMemory(archiver, &next);
commandManager.ArchiveTempModelPointerToMemory(archiver, &prev);
cgd.ArchiveToMemory(archiver);
archiver.ArchiveString(&modelname);
CG_ArchiveRefEntity(archiver, &lastEnt);
CG_ArchiveRefEntity(archiver, &ent);
archiver.ArchiveInteger(&number);
archiver.ArchiveTime(&lastAnimTime);
archiver.ArchiveTime(&lastPhysicsTime);
archiver.ArchiveTime(&killTime);
archiver.ArchiveTime(&next_bouncesound_time);
archiver.ArchiveInteger(&seed);
archiver.ArchiveInteger(&twinkleTime);
archiver.ArchiveInteger(&aliveTime);
archiver.ArchiveBoolean(&addedOnce);
archiver.ArchiveBoolean(&lastEntValid);
commandManager.ArchiveSpawnThingPointerToMemory(archiver, &m_spawnthing);
}
void enttracker_t::ArchiveToMemory(MemArchiver& archiver)
{
archiver.ArchiveRaw(usedNumbers, sizeof(usedNumbers));
}
void emittertime_t::ArchiveToMemory(MemArchiver& archiver)
{
archiver.ArchiveInteger(&entity_number);
archiver.ArchiveTime(&last_emit_time);
archiver.ArchiveVector(&oldorigin);
archiver.ArchiveBoolean(&active);
archiver.ArchiveBoolean(&lerp_emitter);
}
void emitterthing_t::ArchiveToMemory(MemArchiver& archiver)
{
int num;
int i;
enttracker_t::ArchiveToMemory(archiver);
if (archiver.IsReading()) {
emittertime_t et;
archiver.ArchiveInteger(&num);
for (i = 0; i < num; i++) {
et.ArchiveToMemory(archiver);
m_emittertimes.AddObject(et);
}
} else {
num = m_emittertimes.NumObjects();
archiver.ArchiveInteger(&num);
for (i = 0; i < num; i++) {
emittertime_t& et = m_emittertimes[i];
et.ArchiveToMemory(archiver);
}
}
archiver.ArchiveBoolean(&startoff);
}
void cg_common_data::ArchiveToMemory(MemArchiver& archiver)
{
archiver.ArchiveInteger(&life);
archiver.ArchiveTime(&createTime);
archiver.ArchiveVector(&origin);
archiver.ArchiveVector(&oldorigin);
archiver.ArchiveVector(&accel);
archiver.ArchiveVector(&angles);
archiver.ArchiveVector(&velocity);
archiver.ArchiveVector(&avelocity);
archiver.ArchiveVector(&parentOrigin);
archiver.ArchiveVector(&parentMins);
archiver.ArchiveVector(&parentMaxs);
archiver.ArchiveVector(&minVel);
archiver.ArchiveVector(&maxVel);
archiver.ArchiveFloat(color);
archiver.ArchiveFloat(&color[1]);
archiver.ArchiveFloat(&color[2]);
archiver.ArchiveFloat(&color[3]);
archiver.ArchiveFloat(&alpha);
archiver.ArchiveFloat(&scaleRate);
archiver.ArchiveFloat(&scalemin);
archiver.ArchiveFloat(&scalemax);
archiver.ArchiveFloat(&bouncefactor);
archiver.ArchiveInteger(&bouncecount);
archiver.ArchiveInteger(&maxbouncecount);
archiver.ArchiveString(&bouncesound);
archiver.ArchiveInteger(&bouncesound_delay);
archiver.ArchiveInteger(&flags);
archiver.ArchiveInteger(&flags2);
CG_ArchiveTikiPointer(archiver, &tiki);
archiver.ArchiveInteger(&swarmfreq);
archiver.ArchiveFloat(&swarmmaxspeed);
archiver.ArchiveFloat(&swarmdelta);
archiver.ArchiveFloat(&lightIntensity);
archiver.ArchiveInteger(&lightType);
archiver.ArchiveInteger(&fadeintime);
archiver.ArchiveInteger(&fadedelay);
archiver.ArchiveInteger(&parent);
archiver.ArchiveInteger(&collisionmask);
archiver.ArchiveInteger(&min_twinkletimeoff);
archiver.ArchiveInteger(&max_twinkletimeoff);
archiver.ArchiveInteger(&min_twinkletimeon);
archiver.ArchiveInteger(&max_twinkletimeon);
archiver.ArchiveInteger(&lightstyle);
archiver.ArchiveInteger(&physicsRate);
archiver.ArchiveFloat(&scale);
archiver.ArchiveFloat(&scale2);
archiver.ArchiveString(&swipe_shader);
archiver.ArchiveString(&swipe_tag_start);
archiver.ArchiveString(&swipe_tag_end);
archiver.ArchiveString(&shadername);
archiver.ArchiveFloat(&swipe_life);
archiver.ArchiveFloat(&friction);
archiver.ArchiveFloat(&spin_rotation);
archiver.ArchiveFloat(&decal_orientation);
archiver.ArchiveFloat(&decal_radius);
}
void spawnthing_t::ArchiveToMemory(MemArchiver& archiver)
{
emitterthing_t::ArchiveToMemory(archiver);
CG_ArchiveStringContainer(archiver, &m_modellist);
CG_ArchiveStringContainer(archiver, &m_taglist);
cgd.ArchiveToMemory(archiver);
archiver.ArchiveInteger(&entnum);
archiver.ArchiveVector(&origin_offset_base);
archiver.ArchiveVector(&origin_offset_amplitude);
archiver.ArchiveVector(&axis_offset_base);
archiver.ArchiveVector(&axis_offset_amplitude);
archiver.ArchiveVector(&randvel_base);
archiver.ArchiveVector(&randvel_amplitude);
archiver.ArchiveVector(&avelocity_base);
archiver.ArchiveVector(&avelocity_amplitude);
archiver.ArchiveVector(&angles_amplitude);
archiver.ArchiveVec3(axis[0]);
archiver.ArchiveVec3(axis[1]);
archiver.ArchiveVec3(axis[2]);
archiver.ArchiveVec3(tag_axis[0]);
archiver.ArchiveVec3(tag_axis[1]);
archiver.ArchiveVec3(tag_axis[2]);
archiver.ArchiveFloat(&life_random);
archiver.ArchiveFloat(&forwardVelocity);
archiver.ArchiveFloat(&sphereRadius);
archiver.ArchiveFloat(&coneHeight);
archiver.ArchiveFloat(&spawnRate);
archiver.ArchiveTime(&lastTime);
archiver.ArchiveInteger(&count);
archiver.ArchiveInteger(&tagnum);
archiver.ArchiveString(&emittername);
archiver.ArchiveString(&animName);
archiver.ArchiveFloat(dcolor);
archiver.ArchiveFloat(&dcolor[1]);
archiver.ArchiveFloat(&dcolor[2]);
archiver.ArchiveBoolean(&dlight);
archiver.ArchiveInteger(&numtempmodels);
archiver.ArchiveVec3(linked_origin);
archiver.ArchiveVec3(linked_axis[0]);
archiver.ArchiveVec3(linked_axis[1]);
archiver.ArchiveVec3(linked_axis[2]);
archiver.ArchiveFloat(&fMinRangeSquared);
archiver.ArchiveFloat(&fMaxRangeSquared);
archiver.ArchiveString(&startTag);
archiver.ArchiveString(&endTag);
archiver.ArchiveFloat(&length);
archiver.ArchiveFloat(&min_offset);
archiver.ArchiveFloat(&max_offset);
archiver.ArchiveFloat(&overlap);
archiver.ArchiveFloat(&numSubdivisions);
archiver.ArchiveFloat(&delay);
archiver.ArchiveFloat(&toggledelay);
archiver.ArchiveInteger(&beamflags);
archiver.ArchiveInteger(&numspherebeams);
archiver.ArchiveFloat(&endalpha);
archiver.ArchiveFloat(&spreadx);
archiver.ArchiveFloat(&spready);
archiver.ArchiveBoolean(&use_last_trace_end);
}
void commandtime_t::ArchiveToMemory(MemArchiver& archiver)
{
archiver.ArchiveInteger(&entity_number);
archiver.ArchiveInteger(&command_number);
archiver.ArchiveTime(&last_command_time);
}

View file

@ -116,6 +116,7 @@ TIKI file, similar to ScriptMaster in the server game dll.
class spawnthing_t;
class specialeffect_t;
class MemArchiver;
typedef enum {
NOT_RANDOM,
@ -181,6 +182,9 @@ public:
float decal_orientation;
float decal_radius;
float spin_rotation;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline cg_common_data::cg_common_data()
@ -249,6 +253,9 @@ public:
spawnthing_t *m_spawnthing;
void (*touchfcn)(ctempmodel_t *ct, trace_t *trace);
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline ctempmodel_t::ctempmodel_t()
@ -315,8 +322,46 @@ public:
int lastPhysicsTime;
int lastLightingTime;
qboolean lastValid;
public:
cvssource_t();
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline cvssource_t::cvssource_t()
: next(NULL)
, prev(NULL)
, stnext(NULL)
, stindex(0)
, lastRadius(0)
, lastDensity(0)
, lastColor{0}
, lastLighting{0}
, newRadius(0)
, newDensity(0)
, newColor{0}
, newLighting{0}
, ooRadius(0)
, startAlpha(0)
, roll(0)
, lifeTime(0)
, collisionmask(0)
, parent(0)
, flags(0)
, flags2(0)
, smokeType(0)
, typeInfo(0)
, fadeMult(0)
, scaleMult(0)
, lastPhysicsTime(0)
, lastLightingTime(0)
, lastValid(qfalse)
{
}
class cvssourcestate_t
{
public:
@ -387,6 +432,9 @@ public:
protected:
qboolean usedNumbers[256];
virtual void RemoveEntity(int entnum);
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline enttracker_t::enttracker_t()
@ -437,6 +485,9 @@ public:
Vector oldorigin;
qboolean active;
qboolean lerp_emitter;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
// emitterthing_t is used to keep track of the last time and emitter was updated
@ -452,6 +503,9 @@ public:
emittertime_t *GetEmitTime(int entnum);
virtual void RemoveEntity(int entnum);
qboolean startoff;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline void emitterthing_t::RemoveEntity(int entnum)
@ -510,18 +564,23 @@ public:
int entity_number;
int command_number;
int last_command_time;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
// This class is used for keeping track of the last time an entity executed a
// particular command. A command number must be assigned externally by the user
class commandthing_t : public enttracker_t
{
Container<commandtime_t *> m_commandtimes; // A list of entity numbers and the last time they
Container<commandtime_t> m_commandtimes; // A list of entity numbers and the last time they
// executed a command
public:
commandtime_t *GetLastCommandTime(int entnum, int commandnum);
virtual void RemoveEntity(int entnum);
void ArchiveToMemory(MemArchiver& archiver);
};
inline void commandthing_t::RemoveEntity(int entnum)
@ -532,7 +591,7 @@ inline void commandthing_t::RemoveEntity(int entnum)
count = m_commandtimes.NumObjects();
for (num = count; num >= 1; num--) {
ct = m_commandtimes.ObjectAt(num);
ct = &m_commandtimes.ObjectAt(num);
if (ct->entity_number == entnum) {
m_commandtimes.RemoveObjectAt(num);
}
@ -544,27 +603,26 @@ inline void commandthing_t::RemoveEntity(int entnum)
inline commandtime_t *commandthing_t::GetLastCommandTime(int entnum, int commandnum)
{
int num, count;
commandtime_t *ct;
// Search for this entity number
count = m_commandtimes.NumObjects();
for (num = 1; num <= count; num++) {
ct = m_commandtimes.ObjectAt(num);
commandtime_t* ct = &m_commandtimes.ObjectAt(num);
if ((ct->entity_number == entnum) && (ct->command_number == commandnum)) {
return ct;
}
}
// Add a new entry if we didn't find it
ct = new commandtime_t;
ct->entity_number = entnum;
ct->command_number = commandnum;
ct->last_command_time = 0;
commandtime_t ct;
ct.entity_number = entnum;
ct.command_number = commandnum;
ct.last_command_time = 0;
m_commandtimes.AddObject(ct);
return ct;
return &m_commandtimes.ObjectAt(m_commandtimes.NumObjects());
}
class spawnthing_t : public emitterthing_t
@ -625,6 +683,9 @@ public:
void (*touchfcn)(ctempmodel_t *ct, trace_t *trace);
str GetModel(void);
void SetModel(str model);
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline void spawnthing_t::SetModel(str model)
@ -921,6 +982,21 @@ public:
void ResetTreadMarkSources(Event *ev);
void InitializeRainCvars();
void InitializeBeams();
//
// archive stuff
//
int IdForTempModel(const ctempmodel_t* model);
ctempmodel_t* TempModelForId(int id);
int IdForSpawnThing(const spawnthing_t* sp);
spawnthing_t* SpawnThingForId(int id);
int IdForVssSource(const cvssource_t* source);
cvssource_t* VssSourceForId(int id);
void ArchiveTempModelPointerToMemory(MemArchiver& archiver, ctempmodel_t** model);
void ArchiveSpawnThingPointerToMemory(MemArchiver& archiver, spawnthing_t** sp);
void ArchiveVssSourcePointerToMemory(MemArchiver& archiver, cvssource_t** source);
void ArchiveToMemory(MemArchiver& archiver);
};
class EmitterLoader : public Listener