- clean out stale sprite pointers in User when a sprite gets removed.

This was the main reason for those constant crashes, the game was accessing an invalid sprite, treating its data as valid.
Also added a few checks for valid targets in two places where it still crashed.
This commit is contained in:
Christoph Oelckers 2020-02-14 21:44:59 +01:00
parent 4323632ed2
commit 410f5a4545
3 changed files with 22 additions and 5 deletions

View file

@ -451,8 +451,8 @@ void UnindexAIState(AISTATE*& state)
auto index = intptr_t(state);
if (index >= 0 && index < countof(allAIStates))
{
Printf("Unindexing %i to state %p\n", int(index), state);
state = allAIStates[index];
Printf("Unindexing %i to state %p\n", int(index), state);
}
else
{

View file

@ -305,12 +305,10 @@ CanSeePlayer(short SpriteNum)
// if actor can still see the player
int look_height = SPRITEp_TOS(sp);
ASSERT(u->tgt_sp);
//if (FAF_Sector(sp->sectnum))
// return(TRUE);
if (FAFcansee(sp->x, sp->y, look_height, sp->sectnum, u->tgt_sp->x, u->tgt_sp->y, SPRITEp_UPPER(u->tgt_sp), u->tgt_sp->sectnum))
if (u->tgt_sp && FAFcansee(sp->x, sp->y, look_height, sp->sectnum, u->tgt_sp->x, u->tgt_sp->y, SPRITEp_UPPER(u->tgt_sp), u->tgt_sp->sectnum))
return TRUE;
else
return FALSE;
@ -644,6 +642,12 @@ DoActorActionDecide(short SpriteNum)
u->Dist = 0;
action = InitActorDecide;
// target is gone.
if (u->tgt_sp == nullptr)
{
return action;
}
if (TEST(u->Flags, SPR_JUMPING | SPR_FALLING))
{
//CON_Message("Jumping or falling");
@ -658,7 +662,6 @@ DoActorActionDecide(short SpriteNum)
return action;
}
ICanSee = CanSeePlayer(SpriteNum); // Only need to call once
// But need the result multiple times
@ -845,6 +848,9 @@ DoActorDecide(short SpriteNum)
if (actor_action == InitActorAttack && u->WeaponNum == 0)
return 0; // Just let the actor do as it was doing before in this case
// Target is gone.
if (u->tgt_sp == nullptr)
return 0;
// zombie is attacking a player
if (actor_action == InitActorAttack && u->ID == ZOMBIE_RUN_R0 && User[u->tgt_sp-sprite]->PlayerP)

View file

@ -812,6 +812,17 @@ KillSprite(int16_t SpriteNum)
memset(sp, 0xCC, sizeof(SPRITE));
sp->statnum = statnum;
sp->sectnum = sectnum;
// Kill references in all users - slow but unavoidable if we don't want the game to crash on stale pointers.
for (auto u : User)
{
if (u)
{
if (u->hi_sp == sp) u->hi_sp = nullptr;
if (u->lo_sp == sp) u->lo_sp = nullptr;
if (u->tgt_sp == sp) u->tgt_sp = nullptr;
}
}
}
void ChangeState(short SpriteNum, STATEp statep)