From 71e74ca36340e5532a52d1fc7f50a5a07aa833b0 Mon Sep 17 00:00:00 2001
From: toaster <rollerorbital@gmail.com>
Date: Mon, 25 Nov 2019 14:33:15 +0000
Subject: [PATCH] Fix a bunch of shit with MP special stages!

* Prevent an infinite quantity of Emeralds being spawned when P_GiveEmerald is called while a MP Special Stage is in session (resolves #347).
* Fix FuriousFox's ridiculous timer on special stage spawn (mentioned in the comments of the previous issue) by correctly marking spectator players in special stages as finished, and preventing the underflow.
---
 src/g_game.c | 2 +-
 src/p_mobj.c | 2 +-
 src/p_tick.c | 5 ++---
 src/p_user.c | 4 +++-
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/g_game.c b/src/g_game.c
index faaed13c73..11ad1862dc 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -2978,7 +2978,7 @@ void G_AddPlayer(INT32 playernum)
 	if (G_GametypeUsesLives() || ((netgame || multiplayer) && gametype == GT_COOP))
 		p->lives = cv_startinglives.value;
 
-	if (countplayers && !notexiting)
+	if ((countplayers && !notexiting) || G_IsSpecialStage(gamemap))
 		P_DoPlayerExit(p);
 }
 
diff --git a/src/p_mobj.c b/src/p_mobj.c
index f2dd1a734f..b5af077b57 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -11294,7 +11294,7 @@ void P_SpawnPlayer(INT32 playernum)
 	mobj->radius = FixedMul(skins[p->skin].radius, mobj->scale);
 	mobj->height = P_GetPlayerHeight(p);
 
-	if (!leveltime && ((maptol & TOL_NIGHTS) == TOL_NIGHTS) != (G_IsSpecialStage(gamemap))) // non-special NiGHTS stage or special non-NiGHTS stage
+	if (!leveltime && !p->spectator && ((maptol & TOL_NIGHTS) == TOL_NIGHTS) != (G_IsSpecialStage(gamemap))) // non-special NiGHTS stage or special non-NiGHTS stage
 	{
 		if (maptol & TOL_NIGHTS)
 		{
diff --git a/src/p_tick.c b/src/p_tick.c
index e02b11f490..60a776cbc5 100644
--- a/src/p_tick.c
+++ b/src/p_tick.c
@@ -476,7 +476,7 @@ static inline void P_DoSpecialStageStuff(void)
 		// Count up the rings of all the players and see if
 		// they've collected the required amount.
 		for (i = 0; i < MAXPLAYERS; i++)
-			if (playeringame[i])
+			if (playeringame[i] && players[i].nightstime)
 			{
 				tic_t oldnightstime = players[i].nightstime;
 				countspheres += players[i].spheres;
@@ -506,12 +506,11 @@ static inline void P_DoSpecialStageStuff(void)
 			{
 				// Halt all the players
 				for (i = 0; i < MAXPLAYERS; i++)
-					if (playeringame[i])
+					if (playeringame[i] && !players[i].exiting)
 					{
 						players[i].mo->momx = players[i].mo->momy = 0;
 						players[i].exiting = (14*TICRATE)/5 + 1;
 					}
-
 				sstimer = 0;
 				P_GiveEmerald(true);
 				P_RestoreMusic(&players[consoleplayer]);
diff --git a/src/p_user.c b/src/p_user.c
index ed2a1a446b..115ecc6671 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -343,13 +343,15 @@ void P_GiveEmerald(boolean spawnObj)
 				continue;
 
 			emmo = P_SpawnMobjFromMobj(players[i].mo, 0, 0, players[i].mo->height, MT_GOTEMERALD);
+			if (!emmo)
+				continue;
 			P_SetTarget(&emmo->target, players[i].mo);
 			P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em);
 			P_SetTarget(&players[i].mo->tracer, emmo);
 
 			if (pnum == 255)
 			{
-				i = pnum;
+				pnum = i;
 				continue;
 			}
 
-- 
GitLab