From 44434a64d1e92b82d02bab4bd354c49dceb782e0 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Thu, 9 Dec 2021 07:10:16 +0100
Subject: [PATCH] Refactor P_RunTriggerLinedef

---
 src/p_spec.c | 414 +++++++++++++++++++++++++--------------------------
 1 file changed, 202 insertions(+), 212 deletions(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index 265cba2b53..ed2f9eb977 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -1501,108 +1501,215 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor)
 	return true;
 }
 
-/** Used by P_LinedefExecute to check a trigger linedef's conditions
-  * The linedef executor specials in the trigger linedef's sector are run if all conditions are met.
-  * Return false cancels P_LinedefExecute, this happens if a condition is not met.
-  *
-  * \param triggerline Trigger linedef to check conditions for; should NEVER be NULL.
-  * \param actor Object initiating the action; should not be NULL.
-  * \param caller Sector in which the action was started. May be NULL.
-  * \sa P_ProcessLineSpecial, P_LinedefExecute
-  */
-boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller)
+static boolean P_CheckPlayerMare(line_t *triggerline, INT32 targetmare)
 {
-	sector_t *ctlsector;
-	fixed_t dist = P_AproxDistance(triggerline->dx, triggerline->dy)>>FRACBITS;
-	size_t i, linecnt, sectori;
-	INT16 specialtype = triggerline->special;
+	UINT8 mare;
 
-	/////////////////////////////////////////////////
-	// Distance-checking/sector trigger conditions //
-	/////////////////////////////////////////////////
+	if (!(maptol & TOL_NIGHTS))
+		return false;
 
-	// Linetypes 303 and 304 require a specific
-	// number, or minimum or maximum, of rings.
-	if (specialtype == 303 || specialtype == 304)
-	{
-		fixed_t rings = 0;
+	mare = P_FindLowestMare();
 
-		// With the passuse flag, count all player's
-		// rings.
-		if (triggerline->flags & ML_EFFECT4)
-		{
-			for (i = 0; i < MAXPLAYERS; i++)
-			{
-				if (!playeringame[i] || players[i].spectator)
-					continue;
+	if (triggerline->flags & ML_NOCLIMB)
+		return mare <= targetmare;
 
-				if (!players[i].mo || ((maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings) <= 0)
-					continue;
+	if (triggerline->flags & ML_BLOCKMONSTERS)
+		return mare >= targetmare;
 
-				rings += (maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings;
-			}
-		}
-		else
-		{
-			if (!(actor && actor->player))
-				return false; // no player to count rings from here, sorry
+	return mare == targetmare;
+}
 
-			rings = (maptol & TOL_NIGHTS) ? actor->player->spheres : actor->player->rings;
-		}
+static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor, INT32 targetrings)
+{
+	INT32 rings = 0;
+	size_t i;
 
-		if (triggerline->flags & ML_NOCLIMB)
-		{
-			if (rings > dist)
-				return false;
-		}
-		else if (triggerline->flags & ML_BLOCKMONSTERS)
-		{
-			if (rings < dist)
-				return false;
-		}
-		else
+	// With the passuse flag, count all player's
+	// rings.
+	if (triggerline->flags & ML_EFFECT4)
+	{
+		for (i = 0; i < MAXPLAYERS; i++)
 		{
-			if (rings != dist)
-				return false;
+			if (!playeringame[i] || players[i].spectator)
+				continue;
+
+			if (!players[i].mo || ((maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings) <= 0)
+				continue;
+
+			rings += (maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings;
 		}
 	}
-	else if (specialtype >= 314 && specialtype <= 315)
+	else
 	{
-		msecnode_t *node;
-		mobj_t *mo;
-		INT32 numpush = 0;
-		INT32 numneeded = dist;
+		if (!(actor && actor->player))
+			return false; // no player to count rings from here, sorry
+
+		rings = (maptol & TOL_NIGHTS) ? actor->player->spheres : actor->player->rings;
+	}
 
-		if (!caller)
-			return false; // we need a calling sector to find pushables in, silly!
+	if (triggerline->flags & ML_NOCLIMB)
+		return rings <= targetrings;
 
-		// Count the pushables in this sector
-		node = caller->touching_thinglist; // things touching this sector
-		while (node)
-		{
-			mo = node->m_thing;
-			if ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse))
-				numpush++;
-			node = node->m_thinglist_next;
-		}
+	if (triggerline->flags & ML_BLOCKMONSTERS)
+		return rings >= targetrings;
 
-		if (triggerline->flags & ML_NOCLIMB) // Need at least or more
-		{
-			if (numpush < numneeded)
-				return false;
-		}
-		else if (triggerline->flags & ML_EFFECT4) // Need less than
+	return rings == targetrings;
+}
+
+static boolean P_CheckPushables(line_t *triggerline, sector_t *caller, INT32 targetpushables)
+{
+	msecnode_t *node;
+	mobj_t *mo;
+	INT32 numpushables = 0;
+
+	if (!caller)
+		return false; // we need a calling sector to find pushables in, silly!
+
+	// Count the pushables in this sector
+	for (node = caller->touching_thinglist; node; node = node->m_thinglist_next)
+	{
+		mo = node->m_thing;
+		if ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse))
+			numpushables++;
+	}
+
+	if (triggerline->flags & ML_NOCLIMB)
+		return numpushables >= targetpushables;
+
+	if (triggerline->flags & ML_EFFECT4)
+		return numpushables <= targetpushables;
+
+	return numpushables == targetpushables;
+}
+
+static void P_ActivateLinedefExecutor(line_t *line, mobj_t *actor, sector_t *caller)
+{
+	if (line->special < 400 || line->special >= 500)
+		return;
+
+	if (line->executordelay)
+		P_AddExecutorDelay(line, actor, caller);
+	else
+		P_ProcessLineSpecial(line, actor, caller);
+}
+
+static boolean P_ActivateLinedefExecutorsInSector(line_t *triggerline, mobj_t *actor, sector_t *caller)
+{
+	sector_t *ctlsector = triggerline->frontsector;
+	size_t sectori = (size_t)(ctlsector - sectors);
+	size_t linecnt = ctlsector->linecount;
+	size_t i;
+
+	if (triggerline->flags & ML_EFFECT5) // disregard order for efficiency
+	{
+		for (i = 0; i < linecnt; i++)
+			P_ActivateLinedefExecutor(ctlsector->lines[i], actor, caller);
+	}
+	else // walk around the sector in a defined order
+	{
+		boolean backwards = false;
+		size_t j, masterlineindex = (size_t)-1;
+
+		for (i = 0; i < linecnt; i++)
+			if (ctlsector->lines[i] == triggerline)
+			{
+				masterlineindex = i;
+				break;
+			}
+
+#ifdef PARANOIA
+		if (masterlineindex == (size_t)-1)
 		{
-			if (numpush >= numneeded)
-				return false;
+			const size_t li = (size_t)(ctlsector->lines[i] - lines);
+			I_Error("Line %s isn't linked into its front sector", sizeu1(li));
 		}
-		else // Need exact
+#endif
+
+		// i == masterlineindex
+		for (;;)
 		{
-			if (numpush != numneeded)
-				return false;
+			if (backwards) // v2 to v1
+			{
+				for (j = 0; j < linecnt; j++)
+				{
+					if (i == j)
+						continue;
+					if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v2)
+					{
+						i = j;
+						break;
+					}
+					if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v1)
+					{
+						i = j;
+						backwards = false;
+						break;
+					}
+				}
+				if (j == linecnt)
+				{
+					const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes);
+					CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n",
+						sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v1->x, ctlsector->lines[i]->v1->y);
+					return false; // abort
+				}
+			}
+			else // v1 to v2
+			{
+				for (j = 0; j < linecnt; j++)
+				{
+					if (i == j)
+						continue;
+					if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v1)
+					{
+						i = j;
+						break;
+					}
+					if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v2)
+					{
+						i = j;
+						backwards = true;
+						break;
+					}
+				}
+				if (j == linecnt)
+				{
+					const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes);
+					CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n",
+						sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v2->x, ctlsector->lines[i]->v2->y);
+					return false; // abort
+				}
+			}
+
+			if (i == masterlineindex)
+				break;
+
+			P_ActivateLinedefExecutor(ctlsector->lines[i], actor, caller);
 		}
 	}
-	else if (caller)
+
+	return true;
+}
+
+/** Used by P_LinedefExecute to check a trigger linedef's conditions
+  * The linedef executor specials in the trigger linedef's sector are run if all conditions are met.
+  * Return false cancels P_LinedefExecute, this happens if a condition is not met.
+  *
+  * \param triggerline Trigger linedef to check conditions for; should NEVER be NULL.
+  * \param actor Object initiating the action; should not be NULL.
+  * \param caller Sector in which the action was started. May be NULL.
+  * \sa P_ProcessLineSpecial, P_LinedefExecute
+  */
+boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller)
+{
+	fixed_t dist = P_AproxDistance(triggerline->dx, triggerline->dy)>>FRACBITS;
+	INT16 specialtype = triggerline->special;
+
+	////////////////////////
+	// Trigger conditions //
+	////////////////////////
+
+	if (caller)
 	{
 		if (GETSECSPECIAL(caller->special, 2) == 6)
 		{
@@ -1611,28 +1718,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 		}
 		else if (GETSECSPECIAL(caller->special, 2) == 7)
 		{
-			UINT8 mare;
-
-			if (!(maptol & TOL_NIGHTS))
+			if (!P_CheckPlayerMare(triggerline, dist))
 				return false;
-
-			mare = P_FindLowestMare();
-
-			if (triggerline->flags & ML_NOCLIMB)
-			{
-				if (!(mare <= dist))
-					return false;
-			}
-			else if (triggerline->flags & ML_BLOCKMONSTERS)
-			{
-				if (!(mare >= dist))
-					return false;
-			}
-			else
-			{
-				if (!(mare == dist))
-					return false;
-			}
 		}
 		// If we were not triggered by a sector type especially for the purpose,
 		// a Linedef Executor linedef trigger is not handling sector triggers properly, return.
@@ -1646,12 +1733,13 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 		}
 	}
 
-	//////////////////////////////////////
-	// Miscellaneous trigger conditions //
-	//////////////////////////////////////
-
 	switch (specialtype)
 	{
+		case 303: // continuous
+		case 304: // once
+			if (!P_CheckPlayerRings(triggerline, actor, dist))
+				return false;
+			break;
 		case 305: // continuous
 		case 306: // each time
 		case 307: // once
@@ -1670,6 +1758,11 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 			if (!(actor && actor->player && actor->player->ctfteam == 2))
 				return false;
 			break;
+		case 314: // continuous
+		case 315: // once
+			if (!P_CheckPushables(triggerline, caller, dist))
+				return false;
+			break;
 		case 317: // continuous
 		case 318: // once
 			{ // Unlockable triggers required
@@ -1743,111 +1836,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 	// Processing linedef specials //
 	/////////////////////////////////
 
-	ctlsector = triggerline->frontsector;
-	sectori = (size_t)(ctlsector - sectors);
-	linecnt = ctlsector->linecount;
-
-	if (triggerline->flags & ML_EFFECT5) // disregard order for efficiency
-	{
-		for (i = 0; i < linecnt; i++)
-			if (ctlsector->lines[i]->special >= 400
-				&& ctlsector->lines[i]->special < 500)
-			{
-				if (ctlsector->lines[i]->executordelay)
-					P_AddExecutorDelay(ctlsector->lines[i], actor, caller);
-				else
-					P_ProcessLineSpecial(ctlsector->lines[i], actor, caller);
-			}
-	}
-	else // walk around the sector in a defined order
-	{
-		boolean backwards = false;
-		size_t j, masterlineindex = (size_t)-1;
-
-		for (i = 0; i < linecnt; i++)
-			if (ctlsector->lines[i] == triggerline)
-			{
-				masterlineindex = i;
-				break;
-			}
-
-#ifdef PARANOIA
-		if (masterlineindex == (size_t)-1)
-		{
-			const size_t li = (size_t)(ctlsector->lines[i] - lines);
-			I_Error("Line %s isn't linked into its front sector", sizeu1(li));
-		}
-#endif
-
-		// i == masterlineindex
-		for (;;)
-		{
-			if (backwards) // v2 to v1
-			{
-				for (j = 0; j < linecnt; j++)
-				{
-					if (i == j)
-						continue;
-					if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v2)
-					{
-						i = j;
-						break;
-					}
-					if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v1)
-					{
-						i = j;
-						backwards = false;
-						break;
-					}
-				}
-				if (j == linecnt)
-				{
-					const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes);
-					CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n",
-						sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v1->x, ctlsector->lines[i]->v1->y);
-					return false; // abort
-				}
-			}
-			else // v1 to v2
-			{
-				for (j = 0; j < linecnt; j++)
-				{
-					if (i == j)
-						continue;
-					if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v1)
-					{
-						i = j;
-						break;
-					}
-					if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v2)
-					{
-						i = j;
-						backwards = true;
-						break;
-					}
-				}
-				if (j == linecnt)
-				{
-					const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes);
-					CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n",
-						sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v2->x, ctlsector->lines[i]->v2->y);
-					return false; // abort
-				}
-			}
-
-			if (i == masterlineindex)
-				break;
-
-			if (ctlsector->lines[i]->special >= 400
-				&& ctlsector->lines[i]->special < 500)
-			{
-				if (ctlsector->lines[i]->executordelay)
-					P_AddExecutorDelay(ctlsector->lines[i], actor, caller);
-				else
-					P_ProcessLineSpecial(ctlsector->lines[i], actor, caller);
-			}
-		}
-	}
+	if (!P_ActivateLinedefExecutorsInSector(triggerline, actor, caller))
+		return false;
 
 	// "Trigger on X calls" linedefs reset if noclimb is set
 	if ((specialtype == 321 || specialtype == 322) && triggerline->flags & ML_NOCLIMB)
-- 
GitLab