From 5a58b2d90e75db8e192478429d1a7eaddd7c4b3a Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 17 Apr 2020 21:19:21 +0200
Subject: [PATCH] Refactor T_EachTimeThinker

---
 src/p_floor.c | 178 ++++++++++++++++----------------------------------
 1 file changed, 57 insertions(+), 121 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index a5c3586211..2a0d09b651 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1547,30 +1547,40 @@ static boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec)
 	return false;
 }
 
-//
-// P_HavePlayersEnteredArea
-//
-// Helper function for T_EachTimeThinker
-//
-static INT32 P_HavePlayersEnteredArea(boolean *curPlayers, boolean *oldPlayers, boolean inAndOut)
+static boolean P_IsPlayerValid(size_t playernum)
 {
-	INT32 i;
+	if (!playeringame[playernum])
+		return false;
 
-	// Easy check... nothing has changed
-	if (!memcmp(curPlayers, oldPlayers, sizeof(boolean)*MAXPLAYERS))
-		return -1;
+	if (!players[playernum].mo)
+		return false;
 
-	// Otherwise, we have to check if any new players have entered
-	for (i = 0; i < MAXPLAYERS; i++)
-	{
-		if (inAndOut && !curPlayers[i] && oldPlayers[i])
-			return i;
+	if (players[playernum].mo->health <= 0)
+		return false;
+
+	if (players[playernum].spectator)
+		return false;
+
+	return true;
+}
+
+static boolean P_IsMobjTouchingSector(mobj_t *mo, sector_t *sec)
+{
+	msecnode_t *node;
+
+	if (mo->subsector->sector == sec)
+		return true;
 
-		if (curPlayers[i] && !oldPlayers[i])
-			return i;
+	if (!(sec->flags & SF_TRIGGERSPECIAL_TOUCH))
+		return false;
+
+	for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
+	{
+		if (node->m_sector == sec)
+			return true;
 	}
 
-	return -1;
+	return false;
 }
 
 //
@@ -1586,20 +1596,14 @@ void T_EachTimeThinker(eachtime_t *eachtime)
 	size_t i, j;
 	sector_t *sec = NULL;
 	sector_t *targetsec = NULL;
-	//sector_t *usesec = NULL;
 	INT32 secnum = -1;
-	INT32 affectPlayer = 0;
 	boolean oldPlayersInArea[MAXPLAYERS];
-	boolean playersInArea[MAXPLAYERS];
 	boolean oldPlayersOnArea[MAXPLAYERS];
-	boolean playersOnArea[MAXPLAYERS];
 	boolean *oldPlayersArea;
 	boolean *playersArea;
 	boolean FOFsector = false;
-	boolean inAndOut = false;
 	boolean floortouch = false;
 	fixed_t bottomheight, topheight;
-	msecnode_t *node;
 	ffloor_t *rover;
 
 	for (i = 0; i < MAXPLAYERS; i++)
@@ -1608,8 +1612,6 @@ void T_EachTimeThinker(eachtime_t *eachtime)
 		oldPlayersOnArea[i] = eachtime->playersOnArea[i];
 		eachtime->playersInArea[i] = false;
 		eachtime->playersOnArea[i] = false;
-		playersInArea[i] = false;
-		playersOnArea[i] = false;
 	}
 
 	while ((secnum = P_FindSectorFromLineTag(eachtime->sourceline, secnum)) >= 0)
@@ -1654,35 +1656,10 @@ void T_EachTimeThinker(eachtime_t *eachtime)
 
 				for (j = 0; j < MAXPLAYERS; j++)
 				{
-					if (!playeringame[j])
+					if (!P_IsPlayerValid(j))
 						continue;
 
-					if (!players[j].mo)
-						continue;
-
-					if (players[j].mo->health <= 0)
-						continue;
-
-					if ((netgame || multiplayer) && players[j].spectator)
-						continue;
-
-					if (players[j].mo->subsector->sector == targetsec)
-						;
-					else if (sec->flags & SF_TRIGGERSPECIAL_TOUCH)
-					{
-						boolean insector = false;
-						for (node = players[j].mo->touching_sectorlist; node; node = node->m_sectorlist_next)
-						{
-							if (node->m_sector == targetsec)
-							{
-								insector = true;
-								break;
-							}
-						}
-						if (!insector)
-							continue;
-					}
-					else
+					if (!P_IsMobjTouchingSector(players[j].mo, targetsec))
 						continue;
 
 					topheight = P_GetSpecialTopZ(players[j].mo, sec, targetsec);
@@ -1694,16 +1671,10 @@ void T_EachTimeThinker(eachtime_t *eachtime)
 					if (players[j].mo->z + players[j].mo->height < bottomheight)
 						continue;
 
-					if (floortouch == true && P_IsObjectOnGroundIn(players[j].mo, targetsec))
-					{
+					if (floortouch && P_IsObjectOnGroundIn(players[j].mo, targetsec))
 						eachtime->playersOnArea[j] = true;
-						playersOnArea[j] = true;
-					}
 					else
-					{
 						eachtime->playersInArea[j] = true;
-						playersInArea[j] = true;
-					}
 				}
 			}
 		}
@@ -1712,94 +1683,61 @@ void T_EachTimeThinker(eachtime_t *eachtime)
 		{
 			for (i = 0; i < MAXPLAYERS; i++)
 			{
-				if (!playeringame[i])
-					continue;
-
-				if (!players[i].mo)
-					continue;
-
-				if (players[i].mo->health <= 0)
-					continue;
-
-				if ((netgame || multiplayer) && players[i].spectator)
+				if (!P_IsPlayerValid(i))
 					continue;
 
-				if (players[i].mo->subsector->sector == sec)
-					;
-				else if (sec->flags & SF_TRIGGERSPECIAL_TOUCH)
-				{
-					boolean insector = false;
-					for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next)
-					{
-						if (node->m_sector == sec)
-						{
-							insector = true;
-							break;
-						}
-					}
-					if (!insector)
-						continue;
-				}
-				else
+				if (!P_IsMobjTouchingSector(players[i].mo, sec))
 					continue;
 
 				if (!(players[i].mo->subsector->sector == sec
 					|| P_PlayerTouchingSectorSpecial(&players[i], 2, (GETSECSPECIAL(sec->special, 2))) == sec))
 					continue;
 
-				if (floortouch == true && P_IsObjectOnRealGround(players[i].mo, sec))
-				{
+				if (floortouch && P_IsObjectOnRealGround(players[i].mo, sec))
 					eachtime->playersOnArea[i] = true;
-					playersOnArea[i] = true;
-				}
 				else
-				{
 					eachtime->playersInArea[i] = true;
-					playersInArea[i] = true;
-				}
 			}
 		}
 	}
 
-	if (eachtime->triggerOnExit)
-		inAndOut = true;
-
 	// Check if a new player entered.
 	// If not, check if a player hit the floor.
 	// If either condition is true, execute.
-	if (floortouch == true)
+	if (floortouch)
 	{
-		playersArea = playersOnArea;
+		playersArea = eachtime->playersOnArea;
 		oldPlayersArea = oldPlayersOnArea;
 	}
 	else
 	{
-		playersArea = playersInArea;
+		playersArea = eachtime->playersInArea;
 		oldPlayersArea = oldPlayersInArea;
 	}
 
-	while ((affectPlayer = P_HavePlayersEnteredArea(playersArea, oldPlayersArea, inAndOut)) != -1)
+	// Easy check... nothing has changed
+	if (!memcmp(playersArea, oldPlayersArea, sizeof(boolean)*MAXPLAYERS))
+		return;
+
+	// If sector has an "all players" trigger type, all players need to be in area
+	if (GETSECSPECIAL(sec->special, 2) == 2 || GETSECSPECIAL(sec->special, 2) == 3)
 	{
-		if (GETSECSPECIAL(sec->special, 2) == 2 || GETSECSPECIAL(sec->special, 2) == 3)
+		for (i = 0; i < MAXPLAYERS; i++)
 		{
-			for (i = 0; i < MAXPLAYERS; i++)
-			{
-				if (!playeringame[i])
-					continue;
-
-				if (!players[i].mo)
-					continue;
-
-				if (players[i].mo->health <= 0)
-					continue;
+			if (P_IsPlayerValid(i) && playersArea[i])
+				continue;
+		}
+	}
 
-				if ((netgame || multiplayer) && players[i].spectator)
-					continue;
+	// Trigger for every player who has entered (and exited, if triggerOnExit)
+	for (i = 0; i < MAXPLAYERS; i++)
+	{
+		if (playersArea[i] == oldPlayersArea[i])
+			continue;
 
-				if (!playersArea[i])
-					return;
-			}
-		}
+		// If player has just left, check if still valid
+		if (!playersArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i)))
+			continue;
 
 		CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", eachtime->sourceline->tag);
 
@@ -1807,12 +1745,10 @@ void T_EachTimeThinker(eachtime_t *eachtime)
 		// No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever!
 		// This should now run ONLY the stuff for eachtime->sourceline itself, instead of all trigger linedefs sharing the same tag.
 		// Makes much more sense doing it this way, honestly.
-		P_RunTriggerLinedef(eachtime->sourceline, players[affectPlayer].mo, sec);
+		P_RunTriggerLinedef(eachtime->sourceline, players[i].mo, sec);
 
 		if (!eachtime->sourceline->special) // this happens only for "Trigger on X calls" linedefs
 			P_RemoveThinker(&eachtime->thinker);
-
-		oldPlayersArea[affectPlayer]=playersArea[affectPlayer];
 	}
 }
 
-- 
GitLab