diff --git a/src/d_main.cpp b/src/d_main.cpp index 30bbb5227f..c5b77942e7 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -579,6 +579,7 @@ CVAR(Flag, sv_localitems, dmflags3, DF3_LOCAL_ITEMS); CVAR(Flag, sv_nolocaldrops, dmflags3, DF3_NO_LOCAL_DROPS); CVAR(Flag, sv_nocoopitems, dmflags3, DF3_NO_COOP_ONLY_ITEMS); CVAR(Flag, sv_nocoopthings, dmflags3, DF3_NO_COOP_ONLY_THINGS); +CVAR(Flag, sv_rememberlastweapon, dmflags3, DF3_REMEMBER_LAST_WEAP); //========================================================================== // diff --git a/src/doomdef.h b/src/doomdef.h index 668059909f..70759a406d 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -185,6 +185,7 @@ enum : unsigned DF3_NO_LOCAL_DROPS = 1 << 3, // Drops from Actors aren't picked up locally DF3_NO_COOP_ONLY_ITEMS = 1 << 4, // Items that only appear in co-op are disabled DF3_NO_COOP_ONLY_THINGS = 1 << 5, // Any Actor that only appears in co-op is disabled + DF3_REMEMBER_LAST_WEAP = 1 << 6, // When respawning in co-op, keep the last used weapon out instead of switching to the best new one. }; // [RH] Compatibility flags. diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 33756709d2..7e6a1f7d75 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -5508,6 +5508,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag p->mo = mobj; mobj->player = p; state = p->playerstate; + const auto heldWeap = state == PST_REBORN && (dmflags3 & DF3_REMEMBER_LAST_WEAP) ? p->ReadyWeapon : nullptr; if (state == PST_REBORN || state == PST_ENTER) { PlayerReborn (playernum); @@ -5608,7 +5609,7 @@ AActor *FLevelLocals::SpawnPlayer (FPlayerStart *mthing, int playernum, int flag { // Special inventory handling for respawning in coop IFVM(PlayerPawn, FilterCoopRespawnInventory) { - VMValue params[] = { p->mo, oldactor }; + VMValue params[] = { p->mo, oldactor, ((heldWeap == nullptr || (heldWeap->ObjectFlags & OF_EuthanizeMe)) ? nullptr : heldWeap) }; VMCall(func, params, 2, nullptr, 0); } } diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 517ef29d03..fffac02ef2 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1705,6 +1705,7 @@ OptionMenu CoopOptions protected Option "$GMPLYMNU_SHAREKEYS", "sv_coopsharekeys", "YesNo" Option "$GMPLYMNU_LOCALITEMS", "sv_localitems", "YesNo" Option "$GMPLYMNU_NOLOCALDROP", "sv_nolocaldrops", "YesNo" + Option "$GMPLYMNU_REMEMBERWEAP", "sv_rememberlastweapon", "YesNo" Class "GameplayMenu" } diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index d87fc17066..e2a4873303 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -867,7 +867,7 @@ class PlayerPawn : Actor // //=========================================================================== - void FilterCoopRespawnInventory (PlayerPawn oldplayer) + void FilterCoopRespawnInventory (PlayerPawn oldplayer, Weapon curHeldWeapon = null) { // If we're losing everything, this is really simple. if (sv_cooploseinventory) @@ -876,6 +876,10 @@ class PlayerPawn : Actor return; } + // Make sure to get the real held weapon before messing with the inventory. + if (curHeldWeapon && curHeldWeapon.bPowered_Up) + curHeldWeapon = curHeldWeapon.SisterWeapon; + // Walk through the old player's inventory and destroy or modify // according to dmflags. Inventory next; @@ -957,7 +961,15 @@ class PlayerPawn : Actor ObtainInventory (oldplayer); player.ReadyWeapon = NULL; - PickNewWeapon (NULL); + if (curHeldWeapon && curHeldWeapon.owner == self && curHeldWeapon.CheckAmmo(Weapon.EitherFire, false)) + { + player.PendingWeapon = curHeldWeapon; + BringUpWeapon(); + } + else + { + PickNewWeapon (NULL); + } }