From 670e32908e3a2ed2f7bf67ef53074cb70532bf28 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Thu, 9 Dec 2021 18:56:50 +0100
Subject: [PATCH] Adapt linedef type 308 to UDMF

---
 extras/conf/udb/Includes/SRB222_linedefs.cfg | 65 +++++++++++++++++
 src/p_setup.c                                |  5 ++
 src/p_spec.c                                 | 76 ++++++++++++++------
 src/p_spec.h                                 |  9 +++
 4 files changed, 135 insertions(+), 20 deletions(-)

diff --git a/extras/conf/udb/Includes/SRB222_linedefs.cfg b/extras/conf/udb/Includes/SRB222_linedefs.cfg
index 76bb2c5ba6..b4ef7f36a0 100644
--- a/extras/conf/udb/Includes/SRB222_linedefs.cfg
+++ b/extras/conf/udb/Includes/SRB222_linedefs.cfg
@@ -2542,6 +2542,71 @@ udmf
 			}
 		}
 
+		308
+		{
+			title = "Gametype";
+			prefix = "(308)";
+			arg0
+			{
+				title = "Trigger type";
+				type = 11;
+				enum = "triggertype";
+			}
+			arg1
+			{
+				title = "Rules";
+				type = 12;
+				enum
+				{
+					1 = "Campaign";
+					2 = "Ringslinger";
+					4 = "Spectators";
+					8 = "Lives";
+					16 = "Teams";
+					32 = "First person";
+					64 = "Match emeralds";
+					128 = "Team flags";
+					256 = "Coop";
+					512 = "Allow special stages";
+					1024 = "Spawn emerald tokens";
+					2048 = "Emerald hunt";
+					4096 = "Race";
+					8192 = "Tag";
+					16384 = "Point limit";
+					32768 = "Time limit";
+					65536 = "Overtime";
+					131072 = "Hurt messages";
+					262144 = "Friendly fire";
+					524288 = "Hide time countdown";
+					1048576 = "Frozen after hide time";
+					2097152 = "Blindfolded view";
+					4194304 = "Respawn delay";
+					8388608 = "Award pity shield";
+					16777216 = "Death score penalty";
+					33554432 = "No spectator spawn";
+					67108864 = "Use match starts";
+					134217728 = "Spawn invincibility";
+					268435456 = "Allow enemies";
+					536870912 = "Allow exit sectors";
+					1073741824 = "No title card";
+					2147483648 = "Allow cutscenes";
+				}
+			}
+			arg2
+			{
+				title = "Check if";
+				type = 11;
+				enum
+				{
+					0 = "Has all";
+					1 = "Has any";
+					2 = "Has exactly";
+					3 = "Doesn't have all";
+					4 = "Doesn't have any";
+				}
+			}
+		}
+
 		309
 		{
 			title = "CTF Team";
diff --git a/src/p_setup.c b/src/p_setup.c
index a459e64016..6b98ed738a 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -3737,6 +3737,11 @@ static void P_ConvertBinaryMap(void)
 			lines[i].args[3] = !!(lines[i].flags & ML_EFFECT4);
 			lines[i].special = 303;
 			break;
+		case 308: //Race only - once
+			lines[i].args[0] = TMT_ONCE;
+			lines[i].args[1] = GTR_RACE;
+			lines[i].args[2] = TMG_HASANY;
+			break;
 		case 309: //CTF red team - continuous
 		case 310: //CTF red team - each time
 		case 311: //CTF blue team - continuous
diff --git a/src/p_spec.c b/src/p_spec.c
index 5f3ce50d85..be0455fba8 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -1844,7 +1844,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 	if ((specialtype == 300 && triggerline->args[0] == TMT_ONCE)  // Basic
 	 || (specialtype == 303 && triggerline->args[0] == TMT_ONCE)  // Ring count
 	 || specialtype == 307  // Character ability - Once
-	 || specialtype == 308  // Race only - Once
+	 || (specialtype == 308 && triggerline->args[0] == TMT_ONCE)  // Gametype
 	 || (specialtype == 309 && triggerline->args[0] == TMT_ONCE)  // CTF team
 	 || specialtype == 313  // No More Enemies - Once
 	 || (specialtype == 314 && triggerline->args[0] == TMT_ONCE)  // No of pushables
@@ -1891,16 +1891,26 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
 			continue;
 
 		// "No More Enemies" and "Level Load" take care of themselves.
-		if (lines[masterline].special == 313
-		 || lines[masterline].special == 399
-		 // Each-time executors handle themselves, too
-		 || (lines[masterline].special == 300 && lines[masterline].args[0] > TMT_EACHTIMEMASK) // Each time
-		 || lines[masterline].special == 306 // Character ability - Each time
-		 || lines[masterline].special == 310 // CTF Red team - Each time
-		 || lines[masterline].special == 312 // CTF Blue team - Each time
-		 || (lines[masterline].special == 321 && lines[masterline].args[0] > TMXT_EACHTIMEMASK) // Trigger after X calls - Each time
-		 || lines[masterline].special == 332 // Skin - Each time
-		 || lines[masterline].special == 335)// Dye - Each time
+		if (lines[masterline].special == 313  || lines[masterline].special == 399)
+			continue;
+
+		// Each-time executors handle themselves, too
+		if ((lines[masterline].special == 300 // Basic
+			|| lines[masterline].special == 303 // Ring count
+			|| lines[masterline].special == 308 // Gametype
+			|| lines[masterline].special == 309 // CTF team
+			|| lines[masterline].special == 314 // Number of pushables
+			|| lines[masterline].special == 317 // Condition set trigger
+			|| lines[masterline].special == 319) // Unlockable trigger
+			&& lines[masterline].args[0] > TMT_EACHTIMEMASK)
+			continue;
+
+		if (lines[masterline].special == 321 && lines[masterline].args[0] > TMXT_EACHTIMEMASK) // Trigger after X calls
+			continue;
+
+		if (lines[masterline].special == 306 // Character ability
+		 || lines[masterline].special == 332 // Skin
+		 || lines[masterline].special == 335)// Dye
 			continue;
 
 		if (!P_RunTriggerLinedef(&lines[masterline], actor, caller))
@@ -5857,6 +5867,24 @@ static void P_MakeFOFBouncy(line_t *paramline, line_t *masterline)
 
 }
 
+static boolean P_CheckGametypeRules(INT32 checktype, UINT32 target)
+{
+	switch (checktype)
+	{
+		case TMG_HASALL:
+		default:
+			return (gametyperules & target) == target;
+		case TMG_HASANY:
+			return !!(gametyperules & target);
+		case TMG_HASEXACTLY:
+			return gametyperules == target;
+		case TMG_DOESNTHAVEALL:
+			return (gametyperules & target) != target;
+		case TMG_DOESNTHAVEANY:
+			return !(gametyperules & target);
+	}
+}
+
 /** After the map has loaded, scans for specials that spawn 3Dfloors and
   * thinkers.
   *
@@ -6657,14 +6685,6 @@ void P_SpawnSpecials(boolean fromnetsave)
 				}
 				break;
 
-				// Linedef executor triggers for CTF teams.
-			case 309:
-				if (!(gametyperules & GTR_TEAMFLAGS))
-				{
-					lines[i].special = 0;
-					break;
-				}
-				/* FALLTHRU */
 			case 300: // Trigger linedef executor
 			case 303: // Count rings
 			case 314: // Pushable linedef executors (count # of pushables)
@@ -6680,8 +6700,24 @@ void P_SpawnSpecials(boolean fromnetsave)
 				break;
 
 			case 308: // Race-only linedef executor. Triggers once.
-				if (!(gametyperules & GTR_RACE))
+				if (!P_CheckGametypeRules(lines[i].args[2], (UINT32)lines[i].args[1]))
+				{
+					lines[i].special = 0;
+					break;
+				}
+				if (lines[i].args[0] > TMT_EACHTIMEMASK)
+					P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT);
+				break;
+
+			// Linedef executor triggers for CTF teams.
+			case 309:
+				if (!(gametyperules & GTR_TEAMFLAGS))
+				{
 					lines[i].special = 0;
+					break;
+				}
+				if (lines[i].args[0] > TMT_EACHTIMEMASK)
+					P_AddEachTimeThinker(&lines[i], lines[i].args[0] == TMT_EACHTIMEENTERANDEXIT);
 				break;
 
 			// Each time executors
diff --git a/src/p_spec.h b/src/p_spec.h
index a317467f89..c60bdda66b 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -122,6 +122,15 @@ typedef enum
 	TMXT_EACHTIMEENTERANDEXIT = 2,
 } textmapxtriggertype_t;
 
+typedef enum
+{
+	TMG_HASALL        = 0,
+	TMG_HASANY        = 1,
+	TMG_HASEXACTLY    = 2,
+	TMG_DOESNTHAVEALL = 3,
+	TMG_DOESNTHAVEANY = 4,
+} textmapgametypecheck_t;
+
 typedef enum
 {
 	TMT_RED  = 0,
-- 
GitLab