rewrote state pointer serializer to handle the in-object states of custom dudes, deleted the old custom dude states and added one missing state to the list.

This commit is contained in:
Christoph Oelckers 2023-10-17 18:13:38 +02:00
parent 73050e3f74
commit 30826ef22f
3 changed files with 111 additions and 33 deletions

View file

@ -61,11 +61,6 @@ AISTATE tinycalebBurnGoto = { kAiStateMove, 3, nullptr, 3600, NULL, &AF(aiMoveFo
AISTATE tinycalebBurnSearch = { kAiStateSearch, 3, nullptr, 3600, NULL, &AF(aiMoveForward), &AF(burnThinkSearch), &tinycalebBurnSearch };
AISTATE tinycalebBurnAttack = { kAiStateChase, 3, &AF(BurnSeqCallback), 120, NULL, NULL, NULL, &tinycalebBurnChase };
AISTATE genDudeBurnIdle = { kAiStateIdle, 3, nullptr, 0, NULL, NULL, &AF(aiThinkTarget), NULL };
AISTATE genDudeBurnChase = { kAiStateChase, 3, nullptr, 0, NULL, &AF(aiMoveForward), &AF(burnThinkChase), NULL };
AISTATE genDudeBurnGoto = { kAiStateMove, 3, nullptr, 3600, NULL, &AF(aiMoveForward), &AF(burnThinkGoto), &genDudeBurnSearch };
AISTATE genDudeBurnSearch = { kAiStateSearch, 3, nullptr, 3600, NULL, &AF(aiMoveForward), &AF(burnThinkSearch), &genDudeBurnSearch };
AISTATE genDudeBurnAttack = { kAiStateChase, 3, &AF(BurnSeqCallback), 120, NULL, NULL, NULL, &genDudeBurnChase };
void BurnSeqCallback(DBloodActor*)
{

View file

@ -110,11 +110,7 @@ extern AISTATE tinycalebBurnChase;
extern AISTATE tinycalebBurnGoto;
extern AISTATE tinycalebBurnSearch;
extern AISTATE tinycalebBurnAttack;
extern AISTATE genDudeBurnIdle;
extern AISTATE genDudeBurnChase;
extern AISTATE genDudeBurnGoto;
extern AISTATE genDudeBurnSearch;
extern AISTATE genDudeBurnAttack;
extern AISTATE tinycalebIdle;
extern AISTATE tinycalebChase;
@ -181,6 +177,7 @@ extern AISTATE cultistTsFire;
extern AISTATE cultistSProneFire;
extern AISTATE cultistTProneFire;
extern AISTATE cultistTsProneFire;
extern AISTATE cultistTsProneFireFixed;
extern AISTATE cultistRecoil;
extern AISTATE cultistProneRecoil;
extern AISTATE cultistTeslaRecoil;

View file

@ -123,11 +123,6 @@ static AISTATE* const allAIStates[] =
&tinycalebBurnGoto,
&tinycalebBurnSearch,
&tinycalebBurnAttack,
&genDudeBurnIdle,
&genDudeBurnChase,
&genDudeBurnGoto,
&genDudeBurnSearch,
&genDudeBurnAttack,
&tinycalebIdle,
&tinycalebChase,
&tinycalebDodge,
@ -191,6 +186,7 @@ static AISTATE* const allAIStates[] =
&cultistSProneFire,
&cultistTProneFire,
&cultistTsProneFire,
&cultistTsProneFireFixed,
&cultistRecoil,
&cultistProneRecoil,
&cultistTeslaRecoil,
@ -353,12 +349,112 @@ static AISTATE* const allAIStates[] =
&zombieFTeslaRecoil,
};
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
#ifdef NOONE_EXTENSIONS
// Serializing states is a lot more tricky for custom dudes.
// Note that this makes no assumptions about the relationship between actor and dude because at restoration this isn't known.
struct AIStateRep
{
DCustomDude* owner;
int index;
};
static AIStateRep makeStateRep(AISTATE* state)
{
int i = 0;
if (state == nullptr) return { nullptr, -1 };
for (auto cstate : allAIStates)
{
if (state == cstate)
{
return { nullptr, i };
}
i++;
}
if (gModernMap)
{
if (state >= genPatrolStates && state < genPatrolStates + kPatrolStateSize)
{
return { nullptr, int(state - genPatrolStates) + 1000 };
}
// now it gets ugly: the custom dudes each have a copied set of states. Find out which one.
BloodSpriteIterator it;
while (auto actor = it.Next())
{
if (IsCustomDude(actor))
{
auto dude = cdudeGet(actor);
if (dude)
{
auto firststate = (AISTATE*)dude->states;
auto count = sizeof(dude->states) / sizeof(AISTATE);
if (state >= firststate && state < firststate + count)
{
return { dude, int(state - firststate) };
}
}
}
}
}
Printf(PRINT_HIGH, "Attempt to save invalid state!\n"); // we got no further info here, sorry!
return { nullptr, -1 };
}
static AISTATE* getStateFromRep(AIStateRep* rep)
{
if (rep->owner == nullptr)
{
int i = rep->index;
if (i >= 0 && i < countof(allAIStates))
{
return allAIStates[i];
}
else if (gModernMap && i >= 1000 && i < 1000 + kPatrolStateSize)
{
return genPatrolStates + (i - 1000);
}
else
{
return nullptr;
}
}
else if (gModernMap)
{
// at this point the object may not have been deserialized but it definitely has been allocated so we can just take the address.
AISTATE* state = (AISTATE*)rep->owner->states;
return state + rep->index;
}
else return nullptr;
}
FSerializer& Serialize(FSerializer& arc, const char* keyname, AIStateRep& w, AIStateRep* def)
{
if (arc.BeginObject(keyname))
{
arc("object", w.owner)
("index", w.index)
.EndObject();
}
return arc;
}
FSerializer& Serialize(FSerializer& arc, const char* keyname, AISTATE*& w, AISTATE** def)
{
unsigned i = 0;
if (arc.isWriting())
{
auto rep = makeStateRep(w);
arc(keyname, rep);
}
else
{
AIStateRep rep;
arc(keyname, rep);
w = getStateFromRep(&rep);
}
return arc;
}
#else
FSerializer& Serialize(FSerializer& arc, const char* keyname, AISTATE*& w, AISTATE** def)
{
unsigned i = 0;
@ -374,13 +470,6 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, AISTATE*& w, AISTA
}
i++;
}
#ifdef NOONE_EXTENSIONS
if (w >= genPatrolStates && w < genPatrolStates + kPatrolStateSize)
{
i = int(w - genPatrolStates) + 1000;
arc(keyname, i);
}
#endif
}
else
{
@ -389,12 +478,6 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, AISTATE*& w, AISTA
{
w = allAIStates[i];
}
#ifdef NOONE_EXTENSIONS
else if (i >= 1000 && i < 1000 + kPatrolStateSize)
{
w = genPatrolStates + (i - 1000);
}
#endif
else
{
w = nullptr;
@ -403,6 +486,9 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, AISTATE*& w, AISTA
return arc;
}
#endif
//---------------------------------------------------------------------------
//
//