diff --git a/source/blood/src/loadsave.cpp b/source/blood/src/loadsave.cpp index 5284a4182..2364c2feb 100644 --- a/source/blood/src/loadsave.cpp +++ b/source/blood/src/loadsave.cpp @@ -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 { diff --git a/source/sw/src/ai.cpp b/source/sw/src/ai.cpp index 5f5cac9fe..c2e9fc226 100644 --- a/source/sw/src/ai.cpp +++ b/source/sw/src/ai.cpp @@ -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) diff --git a/source/sw/src/sprite.cpp b/source/sw/src/sprite.cpp index 9b8d27f40..281abc783 100644 --- a/source/sw/src/sprite.cpp +++ b/source/sw/src/sprite.cpp @@ -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)