diff --git a/src/g_game.cpp b/src/g_game.cpp index 48bda24f5f..b0c8775fc5 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1655,9 +1655,10 @@ static void G_QueueBody (AActor *body) // // G_DoReborn // +EXTERN_CVAR(Bool, sv_singleplayerrespawn) void G_DoReborn (int playernum, bool freshbot) { - if (!multiplayer && !(level.flags2 & LEVEL2_ALLOWRESPAWN)) + if (!multiplayer && !(level.flags2 & LEVEL2_ALLOWRESPAWN) && !sv_singleplayerrespawn) { if (BackupSaveName.Len() > 0 && FileExists (BackupSaveName.GetChars())) { // Load game from the last point it was saved diff --git a/src/g_level.cpp b/src/g_level.cpp index 4c4b56324a..2a1e0e70ca 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -526,6 +526,8 @@ static bool unloading; // //========================================================================== +EXTERN_CVAR(Bool, sv_singleplayerrespawn) + void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill) { level_info_t *nextinfo = NULL; @@ -634,7 +636,7 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill // If this is co-op, respawn any dead players now so they can // keep their inventory on the next map. - if ((multiplayer || level.flags2 & LEVEL2_ALLOWRESPAWN) && !deathmatch && player->playerstate == PST_DEAD) + if ((multiplayer || level.flags2 & LEVEL2_ALLOWRESPAWN || sv_singleplayerrespawn) && !deathmatch && player->playerstate == PST_DEAD) { // Copied from the end of P_DeathThink [[ player->cls = NULL; // Force a new class if the player is using a random class diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 8f926ea77f..3e20118784 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1,4 +1,4 @@ -// Emacs style mode select -*- C++ -*- +// Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // // $Id:$ @@ -4495,6 +4495,7 @@ void AActor::AdjustFloorClip () // Most of the player structure stays unchanged between levels. // EXTERN_CVAR (Bool, chasedemo) +EXTERN_CVAR(Bool, sv_singleplayerrespawn) extern bool demonew; @@ -4682,7 +4683,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags) { // Give all cards in death match mode. p->mo->GiveDeathmatchInventory (); } - else if ((multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN)) && state == PST_REBORN && oldactor != NULL) + else if ((multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN) || sv_singleplayerrespawn) && state == PST_REBORN && oldactor != NULL) { // Special inventory handling for respawning in coop p->mo->FilterCoopRespawnInventory (oldactor); } diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index ce5b6a74ae..59e83d9e72 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -640,6 +640,12 @@ static void ReadOnePlayer(FSerializer &arc, bool skipload) playerTemp.Serialize(arc); if (!skipload) { + // This temp player has undefined pitch limits, so set them to something + // that should leave the pitch stored in the savegame intact when + // rendering. The real pitch limits will be set by P_SerializePlayers() + // via a net command, but that won't be processed in time for a screen + // wipe, so we need something here. + playerTemp.MaxPitch = playerTemp.MinPitch = playerTemp.mo->Angles.Pitch; CopyPlayer(&players[i], &playerTemp, name); } else diff --git a/src/p_user.cpp b/src/p_user.cpp index dec769025e..232214bfd2 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -65,6 +65,9 @@ static FRandom pr_skullpop ("SkullPop"); // [RH] # of ticks to complete a turn180 #define TURN180_TICKS ((TICRATE / 4) + 1) +// [SP] Allows respawn in single player +CVAR(Bool, sv_singleplayerrespawn, false, CVAR_SERVERINFO | CVAR_LATCH) + // Variables for prediction CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Bool, cl_predict_specials, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -2212,7 +2215,9 @@ void P_DeathThink (player_t *player) if (level.time >= player->respawn_time || ((player->cmd.ucmd.buttons & BT_USE) && player->Bot == NULL)) { player->cls = NULL; // Force a new class if the player is using a random class - player->playerstate = (multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN)) ? PST_REBORN : PST_ENTER; + player->playerstate = + (multiplayer || (level.flags2 & LEVEL2_ALLOWRESPAWN) || sv_singleplayerrespawn) + ? PST_REBORN : PST_ENTER; if (player->mo->special1 > 2) { player->mo->special1 = 0; diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 859bc8f1bd..dc8a8fb83e 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -3160,7 +3160,7 @@ static void R_RenderDecal (side_t *wall, DBaseDecal *decal, drawseg_t *clipper, rereadcolormap = false; } - rw_light = rw_lightleft + (x1 - WallC.sx1) * rw_lightstep; + rw_light = rw_lightleft + (x1 - savecoord.sx1) * rw_lightstep; if (fixedlightlev >= 0) R_SetColorMapLight((r_fullbrightignoresectorcolor) ? &FullNormalLight : usecolormap, 0, FIXEDLIGHT2SHADE(fixedlightlev)); else if (fixedcolormap != NULL)