From 5358fd594b006674b1cd375330da07202d852b3e Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 6 Apr 2012 04:46:45 +0000 Subject: [PATCH] - Fixed: A_Respawn and P_NightmareRespawn() should not check for collision with world geometry. The initial spawn did not, so this can prevent respawns of things that were initially spawned if they happen to intersect a wall. - Fixed: Don't respawn actors inside the floor. - Fixed: The final calls to P_FindFloorCeiling() in P_NightmareRespawn() and A_RestoreSpecialPosition also need to pass true as the second parameter. (Because this parameter is onlyspawnpos, not onlymidtex.) SVN r3518 (trunk) --- src/g_shared/a_pickups.cpp | 9 +++++++-- src/p_local.h | 6 +++--- src/p_map.cpp | 8 ++++---- src/p_mobj.cpp | 15 +++++++++++++-- src/thingdef/thingdef_codeptr.cpp | 13 ++++++++++++- 5 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index ceb97fc3d..f4a326dfc 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -384,8 +384,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition) self->z += FloatBobOffsets[(self->FloatBobPhase + level.maptime) & 63]; } } - // Redo floor/ceiling check, now with 3D floors - P_FindFloorCeiling(self); + // Redo floor/ceiling check, in case of 3D floors + P_FindFloorCeiling(self, true); + if (self->z < self->floorz) + { // Do not reappear under the floor, even if that's where we were for the + // initial spawn. + self->z = self->floorz; + } } int AInventory::StaticLastMessageTic; diff --git a/src/p_local.h b/src/p_local.h index 12f98a4b8..be8c1b426 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -405,8 +405,8 @@ extern TArray spechit; bool P_TestMobjLocation (AActor *mobj); bool P_TestMobjZ (AActor *mobj, bool quick=true, AActor **pOnmobj = NULL); -bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm); -bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y); +bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bool actorsonly=false); +bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, bool actorsonly=false); AActor *P_CheckOnmobj (AActor *thing); void P_FakeZMovement (AActor *mo); bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, int dropoff, const secplane_t * onfloor, FCheckPosition &tm, bool missileCheck = false); @@ -432,7 +432,7 @@ void P_ResetSightCounters (bool full); bool P_TalkFacing (AActor *player); void P_UseLines (player_t* player); bool P_UsePuzzleItem (AActor *actor, int itemType); -void P_FindFloorCeiling (AActor *actor, bool onlymidtex = false); +void P_FindFloorCeiling (AActor *actor, bool onlyspawnpos = false); bool P_ChangeSector (sector_t* sector, int crunch, int amt, int floorOrCeil, bool isreset); diff --git a/src/p_map.cpp b/src/p_map.cpp index 25ce2c813..9a1526c43 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1256,7 +1256,7 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm) // //========================================================================== -bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm) +bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bool actorsonly) { sector_t *newsec; AActor *thingblocker; @@ -1399,7 +1399,7 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm) thing->BlockingMobj = NULL; thing->height = realheight; - if (thing->flags & MF_NOCLIP) + if (actorsonly || (thing->flags & MF_NOCLIP)) return (thing->BlockingMobj = thingblocker) == NULL; FBlockLinesIterator it(box); @@ -1435,10 +1435,10 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm) return (thing->BlockingMobj = thingblocker) == NULL; } -bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y) +bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, bool actorsonly) { FCheckPosition tm; - return P_CheckPosition(thing, x, y, tm); + return P_CheckPosition(thing, x, y, tm, actorsonly); } //---------------------------------------------------------------------------- diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 005e10257..a656da959 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2467,12 +2467,23 @@ void P_NightmareRespawn (AActor *mobj) mo = AActor::StaticSpawn(RUNTIME_TYPE(mobj), x, y, z, NO_REPLACE, true); if (z == ONFLOORZ) + { mo->z += mobj->SpawnPoint[2]; + if (mo->z < mo->floorz) + { // Do not respawn monsters in the floor, even if that's where they + // started. The initial P_ZMovement() call would have put them on + // the floor right away, but we need them on the floor now so we + // can use P_CheckPosition() properly. + mo->z = mo->floorz; + } + } else if (z == ONCEILINGZ) + { mo->z -= mobj->SpawnPoint[2]; + } // something is occupying its position? - if (!P_TestMobjLocation (mo)) + if (!P_CheckPosition(mo, mo->x, mo->y, true)) { //[GrafZahl] MF_COUNTKILL still needs to be checked here. mo->ClearCounters(); @@ -2481,7 +2492,7 @@ void P_NightmareRespawn (AActor *mobj) } // If there are 3D floors, we need to find floor/ceiling again. - P_FindFloorCeiling(mo); + P_FindFloorCeiling(mo, true); z = mo->z; diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index bf2e19e61..1db284b4c 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -2649,10 +2649,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Respawn) { // [KS] DIE DIE DIE DIE erm *ahem* =) oktorespawn = P_TeleportMove(self, self->x, self->y, self->z, true); + if (oktorespawn) + { // Need to do this over again, since P_TeleportMove() will redo + // it with the proper point-on-side calculation. + self->UnlinkFromWorld(); + self->LinkToWorld(true); + sector_t *sec = self->Sector; + self->dropoffz = + self->floorz = sec->floorplane.ZatPoint(self->x, self->y); + self->ceilingz = sec->ceilingplane.ZatPoint(self->x, self->y); + P_FindFloorCeiling(self, true); + } } else { - oktorespawn = P_TestMobjLocation(self); + oktorespawn = P_CheckPosition(self, self->x, self->z, true); } if (oktorespawn)