From 941f9502e944f95ba6bb10895f7b4924807ac8e4 Mon Sep 17 00:00:00 2001 From: Boondorl <59555366+Boondorl@users.noreply.github.com> Date: Sun, 24 Nov 2024 09:44:47 -0500 Subject: [PATCH] Improved "respawn where died" functionality (#2831) Now uses a "last safe position" system instead. This: -Prevents players from slipping into places they shouldn't via their dead body and then respawning there -No longer sends players back to spawn if they fall into kill pits -Adds a safety feature where the kill command always resets back to spawn should a player ever get stuck somewhere --- src/g_game.cpp | 1 + src/gamedata/r_defs.h | 2 ++ src/playsim/d_player.h | 2 ++ src/playsim/p_mobj.cpp | 15 ++++++--------- src/playsim/p_sectors.cpp | 22 ++++++++++++++++++++++ src/playsim/p_user.cpp | 11 ++++++++++- 6 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index 42ce6e99a..f43642813 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1438,6 +1438,7 @@ void FLevelLocals::PlayerReborn (int player) p->cheats |= chasecam; p->Bot = Bot; //Added by MC: p->settings_controller = settings_controller; + p->LastSafePos = p->mo->Pos(); p->oldbuttons = ~0, p->attackdown = true; p->usedown = true; // don't do anything immediately p->original_oldbuttons = ~0; diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index bf0f6be4b..a6f4c2c4f 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -805,6 +805,8 @@ public: void RemoveForceField(); int Index() const { return sectornum; } + bool IsDangerous(const DVector3& pos, double height) const; + void AdjustFloorClip () const; void SetColor(PalEntry pe, int desat); void SetFade(PalEntry pe); diff --git a/src/playsim/d_player.h b/src/playsim/d_player.h index a717bb42c..2a2fd3334 100644 --- a/src/playsim/d_player.h +++ b/src/playsim/d_player.h @@ -435,6 +435,8 @@ public: DAngle ConversationNPCAngle = nullAngle; bool ConversationFaceTalker = false; + DVector3 LastSafePos = {}; // Mark the last known safe location the player was standing. + double GetDeltaViewHeight() const { return (mo->FloatVar(NAME_ViewHeight) + crouchviewdelta - viewheight) / 8; diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index d896db678..acc18902a 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -5594,16 +5594,13 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag PlayerSpawnPickClass(playernum); - if (( dmflags2 & DF2_SAME_SPAWN_SPOT ) && - ( p->playerstate == PST_REBORN ) && - ( deathmatch == false ) && - ( gameaction != ga_worlddone ) && - ( p->mo != NULL ) && - ( !(p->mo->Sector->Flags & SECF_NORESPAWN) ) && - ( NULL != p->attacker ) && // don't respawn on damaging floors - ( p->mo->Sector->damageamount < TELEFRAG_DAMAGE )) // this really should be a bit smarter... + if ((dmflags2 & DF2_SAME_SPAWN_SPOT) && !deathmatch + && p->mo != nullptr && p->playerstate == PST_REBORN + && gameaction != ga_worlddone + && !(p->mo->Sector->Flags & SECF_NORESPAWN) + && p->LastDamageType != NAME_Suicide) { - spawn = p->mo->Pos(); + spawn = p->LastSafePos; SpawnAngle = p->mo->Angles.Yaw; } else diff --git a/src/playsim/p_sectors.cpp b/src/playsim/p_sectors.cpp index a9014c2ce..581a5350a 100644 --- a/src/playsim/p_sectors.cpp +++ b/src/playsim/p_sectors.cpp @@ -129,6 +129,28 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, NextSpecialSector, P_NextSpecialSector) ACTION_RETURN_POINTER(P_NextSpecialSector(self, type, nogood)); } +bool sector_t::IsDangerous(const DVector3& pos, double height) const +{ + if (damageamount > 0) + return true; + + auto cl = dyn_cast(ceilingdata.Get()); + if (cl != nullptr && cl->getCrush() > 0) + return true; + + for (auto rover : e->XFloor.ffloors) + { + if ((rover->flags & FF_EXISTS) && rover->model->damageamount > 0 + && pos.Z <= rover->top.plane->ZatPoint(pos) + && pos.Z + height >= rover->bottom.plane->ZatPoint(pos)) + { + return true; + } + } + + return false; +} + // // P_FindLowestFloorSurrounding() // FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 4dfab3d6c..652d533ca 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -361,6 +361,7 @@ void player_t::CopyFrom(player_t &p, bool copyPSP) MUSINFOactor = p.MUSINFOactor; MUSINFOtics = p.MUSINFOtics; SoundClass = p.SoundClass; + LastSafePos = p.LastSafePos; angleOffsetTargets = p.angleOffsetTargets; if (copyPSP) { @@ -1291,6 +1292,13 @@ void P_PlayerThink (player_t *player) player->SubtitleCounter--; } + if (player->playerstate == PST_LIVE + && player->mo->Z() <= player->mo->floorz + && !player->mo->Sector->IsDangerous(player->mo->Pos(), player->mo->Height)) + { + player->LastSafePos = player->mo->Pos(); + } + // Bots do not think in freeze mode. if (player->mo->Level->isFrozen() && player->Bot != nullptr) { @@ -1779,7 +1787,8 @@ void player_t::Serialize(FSerializer &arc) ("onground", onground) ("musinfoactor", MUSINFOactor) ("musinfotics", MUSINFOtics) - ("soundclass", SoundClass); + ("soundclass", SoundClass) + ("lastsafepos", LastSafePos); if (arc.isWriting ()) {