From 5568e445ed2211ea5cd931180661ee36c641aa3c Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Fri, 3 Jan 2020 16:21:08 -0300
Subject: [PATCH 001/251] Colored title cards

---
 src/st_stuff.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/src/st_stuff.c b/src/st_stuff.c
index 9c4f0abd5..659ed8c2f 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -1301,6 +1301,16 @@ void ST_drawTitleCard(void)
 	INT32 ttlscroll = FixedInt(lt_scroll);
 	INT32 zzticker;
 	patch_t *actpat, *zigzag, *zztext;
+	UINT8 colornum;
+	const UINT8 *colormap;
+	stplyr = &players[consoleplayer];
+	
+	if (stplyr)
+		colornum = stplyr->skincolor;
+	else
+		colornum = cv_playercolor.value;
+	
+	colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE);
 
 	if (!G_IsTitleCardAvailable())
 		return;
@@ -1340,16 +1350,16 @@ void ST_drawTitleCard(void)
 	if (!splitscreen || (splitscreen && stplyr == &players[displayplayer]))
 	{
 		zzticker = lt_ticker;
-		V_DrawScaledPatch(FixedInt(lt_zigzag), (-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag);
-		V_DrawScaledPatch(FixedInt(lt_zigzag), (zigzag->height-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag);
-		V_DrawScaledPatch(FixedInt(lt_zigzag), (-zigzag->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext);
-		V_DrawScaledPatch(FixedInt(lt_zigzag), (zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext);
+		V_DrawMappedPatch(FixedInt(lt_zigzag), (-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap);
+		V_DrawMappedPatch(FixedInt(lt_zigzag), (zigzag->height-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap);
+		V_DrawMappedPatch(FixedInt(lt_zigzag), (-zigzag->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap);
+		V_DrawMappedPatch(FixedInt(lt_zigzag), (zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap);
 	}
 
 	if (actnum)
 	{
 		if (!splitscreen)
-			V_DrawScaledPatch(ttlnumxpos + ttlscroll, 104 - ttlscroll, 0, actpat);
+			V_DrawMappedPatch(ttlnumxpos + ttlscroll, 104 - ttlscroll, 0, actpat, colormap);
 		V_DrawLevelActNum(ttlnumxpos + ttlscroll, 104, V_PERPLAYER, actnum);
 	}
 

From 423d1af48d41e2595bd30ae6e219ee3b5205dc56 Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Fri, 3 Jan 2020 16:39:39 -0300
Subject: [PATCH 002/251] I see trees of green

---
 src/st_stuff.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/st_stuff.c b/src/st_stuff.c
index 659ed8c2f..708034c03 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -1305,7 +1305,7 @@ void ST_drawTitleCard(void)
 	const UINT8 *colormap;
 	stplyr = &players[consoleplayer];
 	
-	if (stplyr)
+	if (stplyr->skincolor)
 		colornum = stplyr->skincolor;
 	else
 		colornum = cv_playercolor.value;

From 5d33ca42cfef4e57e38013815d9ae2d390244b2a Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Sat, 11 Jan 2020 20:40:57 -0300
Subject: [PATCH 003/251] Expose colorization to mappers and SOC

---
 src/d_netcmd.c |  7 ++++---
 src/d_player.h |  2 ++
 src/dehacked.c |  6 +++++-
 src/info.h     |  1 +
 src/p_enemy.c  | 34 ++++++++++++++++++++++++++++++++++
 src/p_setup.c  |  4 ++++
 src/p_spec.c   | 39 +++++++++++++++++++++++++++++++++++++--
 src/p_user.c   | 13 ++++++++++++-
 8 files changed, 99 insertions(+), 7 deletions(-)

diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 29e68143c..4bf592810 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -1251,7 +1251,7 @@ static void SendNameAndColor(void)
 
 		players[consoleplayer].skincolor = cv_playercolor.value;
 
-		if (players[consoleplayer].mo)
+		if (players[consoleplayer].mo && !players[consoleplayer].powers[pw_dye])
 			players[consoleplayer].mo->color = players[consoleplayer].skincolor;
 
 		if (metalrecording)
@@ -1363,8 +1363,9 @@ static void SendNameAndColor2(void)
 	if (botingame)
 	{
 		players[secondplaya].skincolor = botcolor;
-		if (players[secondplaya].mo)
+		if (players[secondplaya].mo && !players[secondplaya].powers[pw_dye])
 			players[secondplaya].mo->color = players[secondplaya].skincolor;
+
 		SetPlayerSkinByNum(secondplaya, botskin-1);
 		return;
 	}
@@ -1377,7 +1378,7 @@ static void SendNameAndColor2(void)
 
 		// don't use secondarydisplayplayer: the second player must be 1
 		players[secondplaya].skincolor = cv_playercolor2.value;
-		if (players[secondplaya].mo)
+		if (players[secondplaya].mo && !players[secondplaya].powers[pw_dye])
 			players[secondplaya].mo->color = players[secondplaya].skincolor;
 
 		if (cv_forceskin.value >= 0 && (netgame || multiplayer)) // Server wants everyone to use the same player
diff --git a/src/d_player.h b/src/d_player.h
index 62f38193f..2344c9c85 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -278,6 +278,8 @@ typedef enum
 	pw_nights_linkfreeze,
 
 	pw_nocontrol, //for linedef exec 427
+	
+	pw_dye, // for dyes
 
 	NUMPOWERS
 } powertype_t;
diff --git a/src/dehacked.c b/src/dehacked.c
index 091371122..85a020936 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -2918,6 +2918,7 @@ static actionpointer_t actionpointers[] =
 	{{A_SetRandomTics},          "A_SETRANDOMTICS"},
 	{{A_ChangeColorRelative},    "A_CHANGECOLORRELATIVE"},
 	{{A_ChangeColorAbsolute},    "A_CHANGECOLORABSOLUTE"},
+	{{A_Dye},                    "A_DYE"},
 	{{A_MoveRelative},           "A_MOVERELATIVE"},
 	{{A_MoveAbsolute},           "A_MOVEABSOLUTE"},
 	{{A_Thrust},                 "A_THRUST"},
@@ -9129,7 +9130,10 @@ static const char *const POWERS_LIST[] = {
 	"NIGHTS_LINKFREEZE",
 
 	//for linedef exec 427
-	"NOCONTROL"
+	"NOCONTROL",
+	
+	//for dyes
+	"DYE"
 };
 
 static const char *const HUDITEMS_LIST[] = {
diff --git a/src/info.h b/src/info.h
index 324795d45..33f597e61 100644
--- a/src/info.h
+++ b/src/info.h
@@ -165,6 +165,7 @@ void A_SetTics();
 void A_SetRandomTics();
 void A_ChangeColorRelative();
 void A_ChangeColorAbsolute();
+void A_Dye();
 void A_MoveRelative();
 void A_MoveAbsolute();
 void A_Thrust();
diff --git a/src/p_enemy.c b/src/p_enemy.c
index bd7b81d40..d8e75f7f2 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -191,6 +191,7 @@ void A_SetTics(mobj_t *actor);
 void A_SetRandomTics(mobj_t *actor);
 void A_ChangeColorRelative(mobj_t *actor);
 void A_ChangeColorAbsolute(mobj_t *actor);
+void A_Dye(mobj_t *actor);
 void A_MoveRelative(mobj_t *actor);
 void A_MoveAbsolute(mobj_t *actor);
 void A_Thrust(mobj_t *actor);
@@ -8949,6 +8950,39 @@ void A_ChangeColorAbsolute(mobj_t *actor)
 		actor->color = (UINT8)locvar2;
 }
 
+// Function: A_Dye
+//
+// Description: Colorizes an object.
+//
+// var1 = if (var1 > 0), dye your target instead of yourself
+// var2 = if (var1 = 0), color value to dye
+//
+void A_Dye(mobj_t *actor)
+{
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_Dye", actor))
+		return;
+#endif
+	mobj_t *target = ((locvar1 && actor->target) ? actor->target : actor);
+	UINT8 color = (UINT8)locvar2;
+	
+	// What if it's a player?
+	if (target->player)
+	{
+		target->player->powers[pw_dye] = color;
+		return;
+	}
+	
+	target->color = color;
+	
+	if (!color)
+		target->colorized = false;
+	else
+		target->colorized = true;
+}
+
 // Function: A_MoveRelative
 //
 // Description: Moves an object (wrapper for P_Thrust)
diff --git a/src/p_setup.c b/src/p_setup.c
index cfe141381..20dfc633b 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1185,10 +1185,14 @@ static void P_LoadSidedefs(UINT8 *data)
 			case 9: // Mace parameters
 			case 14: // Bustable block parameters
 			case 15: // Fan particle spawner parameters
+			case 334: // Trigger linedef executor: Object dye - Continuous
+			case 335: // Trigger linedef executor: Object dye - Each time
+			case 336: // Trigger linedef executor: Object dye - Once
 			case 425: // Calls P_SetMobjState on calling mobj
 			case 434: // Custom Power
 			case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors
 			case 461: // Spawns an object on the map based on texture offsets
+			case 463: // Colorizes an object
 			{
 				char process[8*3+1];
 				memset(process,0,8*3+1);
diff --git a/src/p_spec.c b/src/p_spec.c
index f2cb17e0e..8089896a7 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -2034,6 +2034,17 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 			if (!(actor && actor->player && ((stricmp(triggerline->text, skins[actor->player->skin].name) == 0) ^ ((triggerline->flags & ML_NOCLIMB) == ML_NOCLIMB))))
 				return false;
 			break;
+		case 334: // object dye - continuous
+		case 335: // object dye - each time
+		case 336: // object dye - once
+			{
+				INT32 triggercolor = (INT32)sides[triggerline->sidenum[0]].toptexture;
+				UINT8 color = (actor->player ? actor->player->powers[pw_dye] : actor->color);
+				boolean invert = (triggerline->flags & ML_NOCLIMB ? true : false);
+				
+				if (invert ^ (triggercolor != color))
+					return false;
+			}
 		default:
 			break;
 	}
@@ -2167,6 +2178,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 	 || specialtype == 328 // Nights lap - Once
 	 || specialtype == 330 // Nights Bonus Time - Once
 	 || specialtype == 333 // Skin - Once
+	 || specialtype == 336 // Dye - Once
 	 || specialtype == 399) // Level Load
 		triggerline->special = 0; // Clear it out
 
@@ -2208,7 +2220,8 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
 		 || lines[masterline].special == 310 // CTF Red team - Each time
 		 || lines[masterline].special == 312 // CTF Blue team - Each time
 		 || lines[masterline].special == 322 // Trigger on X calls - Each Time
-		 || lines[masterline].special == 332)// Skin - Each time
+		 || lines[masterline].special == 332 // Skin - Each time
+		 || lines[masterline].special == 335)// Dye - Each time
 			continue;
 
 		if (lines[masterline].special < 300
@@ -4041,7 +4054,23 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				}
 			}
 			break;
-
+		
+		case 463: // Dye object
+			{
+				INT32 color = sides[line->sidenum[0]].toptexture;
+				
+				if (mo)
+				{
+					if (color < 0 || color > MAXSKINCOLORS)
+						return;
+					
+					var1 = 0;
+					var2 = color;
+					A_Dye(mo);
+				}
+			}
+			break;
+		
 #ifdef POLYOBJECTS
 		case 480: // Polyobj_DoorSlide
 		case 481: // Polyobj_DoorSwing
@@ -7208,6 +7237,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 			case 310:
 			case 312:
 			case 332:
+			case 335:
 				sec = sides[*lines[i].sidenum].sector - sectors;
 				P_AddEachTimeThinker(&sectors[sec], &lines[i]);
 				break;
@@ -7260,6 +7290,11 @@ void P_SpawnSpecials(boolean fromnetsave)
 			case 331:
 			case 333:
 				break;
+			
+			// Object dye executors
+			case 334:
+			case 336:
+				break;
 
 			case 399: // Linedef execute on map load
 				// This is handled in P_RunLevelLoadExecutors.
diff --git a/src/p_user.c b/src/p_user.c
index 2bd856481..aa632d365 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -12270,7 +12270,18 @@ void P_PlayerThink(player_t *player)
 		player->powers[pw_nocontrol]--;
 	else
 		player->powers[pw_nocontrol] = 0;
-
+	
+	if (player->powers[pw_dye])
+	{
+		player->mo->colorized = true;
+		player->mo->color = player->powers[pw_dye];
+	}
+	else
+	{
+		player->mo->colorized = false;
+		player->mo->color = player->skincolor;
+	}
+	
 	//pw_super acts as a timer now
 	if (player->powers[pw_super]
 	&& (player->mo->state < &states[S_PLAY_SUPER_TRANS1]

From 4221f08a7c82e6650ab48b6adad41ce22b39d260 Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Sat, 11 Jan 2020 21:35:19 -0300
Subject: [PATCH 004/251] toaster guidance

---
 src/p_user.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/p_user.c b/src/p_user.c
index aa632d365..0d96ced30 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -12271,17 +12271,6 @@ void P_PlayerThink(player_t *player)
 	else
 		player->powers[pw_nocontrol] = 0;
 	
-	if (player->powers[pw_dye])
-	{
-		player->mo->colorized = true;
-		player->mo->color = player->powers[pw_dye];
-	}
-	else
-	{
-		player->mo->colorized = false;
-		player->mo->color = player->skincolor;
-	}
-	
 	//pw_super acts as a timer now
 	if (player->powers[pw_super]
 	&& (player->mo->state < &states[S_PLAY_SUPER_TRANS1]
@@ -12927,6 +12916,17 @@ void P_PlayerAfterThink(player_t *player)
 		player->mo->flags2 |= MF2_DONTDRAW;
 		player->mo->flags |= MF_NOGRAVITY;
 	}
+	
+	if (player->powers[pw_dye])
+	{
+		player->mo->colorized = true;
+		player->mo->color = player->powers[pw_dye];
+	}
+	else
+	{
+		player->mo->colorized = false;
+		player->mo->color = player->skincolor;
+	}
 
 	if (player->followmobj && (player->spectator || player->mo->health <= 0 || player->followmobj->type != player->followitem))
 	{

From 7b3cc02ddc3d78a3337defaeb5df375c197a1b64 Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Sat, 11 Jan 2020 21:38:10 -0300
Subject: [PATCH 005/251] Range check

---
 src/p_enemy.c | 7 +++++--
 src/p_spec.c  | 2 +-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/p_enemy.c b/src/p_enemy.c
index d8e75f7f2..bfdd1b8de 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -8954,8 +8954,8 @@ void A_ChangeColorAbsolute(mobj_t *actor)
 //
 // Description: Colorizes an object.
 //
-// var1 = if (var1 > 0), dye your target instead of yourself
-// var2 = if (var1 = 0), color value to dye
+// var1 = if (var1 != 0), dye your target instead of yourself
+// var2 = color value to dye
 //
 void A_Dye(mobj_t *actor)
 {
@@ -8968,6 +8968,9 @@ void A_Dye(mobj_t *actor)
 	mobj_t *target = ((locvar1 && actor->target) ? actor->target : actor);
 	UINT8 color = (UINT8)locvar2;
 	
+	if (color >= MAXTRANSLATIONS)
+		return;
+	
 	// What if it's a player?
 	if (target->player)
 	{
diff --git a/src/p_spec.c b/src/p_spec.c
index 8089896a7..c7558582a 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -4061,7 +4061,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				
 				if (mo)
 				{
-					if (color < 0 || color > MAXSKINCOLORS)
+					if (color < 0 || color >= MAXTRANSLATIONS)
 						return;
 					
 					var1 = 0;

From 0fa638eaf51b9f8b50b757d182e1c27a04dbf328 Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Mon, 13 Jan 2020 19:12:02 -0300
Subject: [PATCH 006/251] Logistical problems

---
 src/p_enemy.c | 9 ++++-----
 src/p_user.c  | 5 -----
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/src/p_enemy.c b/src/p_enemy.c
index bfdd1b8de..21cf672a4 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -8971,6 +8971,9 @@ void A_Dye(mobj_t *actor)
 	if (color >= MAXTRANSLATIONS)
 		return;
 	
+	if (!color)
+		target->colorized = false;
+	
 	// What if it's a player?
 	if (target->player)
 	{
@@ -8979,11 +8982,7 @@ void A_Dye(mobj_t *actor)
 	}
 	
 	target->color = color;
-	
-	if (!color)
-		target->colorized = false;
-	else
-		target->colorized = true;
+	target->colorized = true;
 }
 
 // Function: A_MoveRelative
diff --git a/src/p_user.c b/src/p_user.c
index 0d96ced30..45f4a4562 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -12922,11 +12922,6 @@ void P_PlayerAfterThink(player_t *player)
 		player->mo->colorized = true;
 		player->mo->color = player->powers[pw_dye];
 	}
-	else
-	{
-		player->mo->colorized = false;
-		player->mo->color = player->skincolor;
-	}
 
 	if (player->followmobj && (player->spectator || player->mo->health <= 0 || player->followmobj->type != player->followitem))
 	{

From fb19d25de175264742c7561d3098823c0d763341 Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Tue, 14 Jan 2020 00:52:54 -0300
Subject: [PATCH 007/251] What

---
 src/p_enemy.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/p_enemy.c b/src/p_enemy.c
index 21cf672a4..6b20862ed 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -8973,7 +8973,9 @@ void A_Dye(mobj_t *actor)
 	
 	if (!color)
 		target->colorized = false;
-	
+	else
+		target->colorized = true;
+		
 	// What if it's a player?
 	if (target->player)
 	{
@@ -8982,7 +8984,6 @@ void A_Dye(mobj_t *actor)
 	}
 	
 	target->color = color;
-	target->colorized = true;
 }
 
 // Function: A_MoveRelative

From e8760fe5dd6ec67c21fc1659458bc0078819d730 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Wed, 22 Jan 2020 23:08:57 +0100
Subject: [PATCH 008/251] Update Lua I/O support to 2.2

---
 src/CMakeLists.txt    |   1 +
 src/blua/Makefile.cfg |   1 +
 src/blua/linit.c      |   1 +
 src/blua/liolib.c     | 720 ++++++++++++++++++++++++++++++++++++++++++
 src/blua/lualib.h     |   3 +
 src/d_clisrv.c        |  26 ++
 src/d_clisrv.h        |   6 +
 src/d_main.c          |   3 +
 src/d_net.c           |   8 +
 src/d_netcmd.c        |   4 +-
 src/d_netcmd.h        |   1 +
 src/d_netfil.c        | 252 ++++++++++++++-
 src/d_netfil.h        |  40 +++
 13 files changed, 1058 insertions(+), 8 deletions(-)
 create mode 100644 src/blua/liolib.c

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e8c9c3182..4971736ca 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -279,6 +279,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
 		blua/lfunc.c
 		blua/lgc.c
 		blua/linit.c
+		blua/liolib.c
 		blua/llex.c
 		blua/lmem.c
 		blua/lobject.c
diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg
index 8d2e73714..659faf3c8 100644
--- a/src/blua/Makefile.cfg
+++ b/src/blua/Makefile.cfg
@@ -18,6 +18,7 @@ OBJS:=$(OBJS) \
 	$(OBJDIR)/ldo.o \
 	$(OBJDIR)/lfunc.o \
 	$(OBJDIR)/linit.o \
+	$(OBJDIR)/liolib.o \
 	$(OBJDIR)/llex.o \
 	$(OBJDIR)/lmem.o \
 	$(OBJDIR)/lobject.o \
diff --git a/src/blua/linit.c b/src/blua/linit.c
index 52b02dbe7..d17390b20 100644
--- a/src/blua/linit.c
+++ b/src/blua/linit.c
@@ -17,6 +17,7 @@
 static const luaL_Reg lualibs[] = {
   {"", luaopen_base},
   {LUA_TABLIBNAME, luaopen_table},
+  {LUA_IOLIBNAME, luaopen_io},
   {LUA_STRLIBNAME, luaopen_string},
   {NULL, NULL}
 };
diff --git a/src/blua/liolib.c b/src/blua/liolib.c
new file mode 100644
index 000000000..6ebde08a3
--- /dev/null
+++ b/src/blua/liolib.c
@@ -0,0 +1,720 @@
+/*
+** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $
+** Standard I/O (and system) library
+** See Copyright Notice in lua.h
+*/
+
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define liolib_c
+#define LUA_LIB
+
+#include "lua.h"
+
+#include "lauxlib.h"
+#include "lualib.h"
+#include "../i_system.h"
+#include "../g_game.h"
+#include "../d_netfil.h"
+#include "../lua_libs.h"
+#include "../byteptr.h"
+#include "../lua_script.h"
+#include "../m_misc.h"
+
+
+#define IO_INPUT	1
+#define IO_OUTPUT	2
+
+#define FILELIMIT (1024 * 1024) // Size limit for reading/writing files
+
+#define FMT_FILECALLBACKID "file_callback_%d"
+
+
+static const char *const fnames[] = {"input", "output"};
+static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder
+	".txt",
+	".sav2",
+	".cfg",
+	".png",
+	".bmp"
+};
+
+
+static int pushresult (lua_State *L, int i, const char *filename) {
+  int en = errno;  /* calls to Lua API may change this value */
+  if (i) {
+    lua_pushboolean(L, 1);
+    return 1;
+  }
+  else {
+    lua_pushnil(L);
+    if (filename)
+      lua_pushfstring(L, "%s: %s", filename, strerror(en));
+    else
+      lua_pushfstring(L, "%s", strerror(en));
+    lua_pushinteger(L, en);
+    return 3;
+  }
+}
+
+
+static void fileerror (lua_State *L, int arg, const char *filename) {
+  lua_pushfstring(L, "%s: %s", filename, strerror(errno));
+  luaL_argerror(L, arg, lua_tostring(L, -1));
+}
+
+
+#define tofilep(L)	((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
+
+
+static int io_type (lua_State *L) {
+  void *ud;
+  luaL_checkany(L, 1);
+  ud = lua_touserdata(L, 1);
+  lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
+  if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
+    lua_pushnil(L);  /* not a file */
+  else if (*((FILE **)ud) == NULL)
+    lua_pushliteral(L, "closed file");
+  else
+    lua_pushliteral(L, "file");
+  return 1;
+}
+
+
+static FILE *tofile (lua_State *L) {
+  FILE **f = tofilep(L);
+  if (*f == NULL)
+    luaL_error(L, "attempt to use a closed file");
+  return *f;
+}
+
+
+
+/*
+** When creating file handles, always creates a `closed' file handle
+** before opening the actual file; so, if there is a memory error, the
+** file is not left opened.
+*/
+static FILE **newfile (lua_State *L) {
+  FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
+  *pf = NULL;  /* file handle is currently `closed' */
+  luaL_getmetatable(L, LUA_FILEHANDLE);
+  lua_setmetatable(L, -2);
+  return pf;
+}
+
+
+/*
+** function to (not) close the standard files stdin, stdout, and stderr
+*/
+static int io_noclose (lua_State *L) {
+  lua_pushnil(L);
+  lua_pushliteral(L, "cannot close standard file");
+  return 2;
+}
+
+
+/*
+** function to close regular files
+*/
+static int io_fclose (lua_State *L) {
+  FILE **p = tofilep(L);
+  int ok = (fclose(*p) == 0);
+  *p = NULL;
+  return pushresult(L, ok, NULL);
+}
+
+
+static int aux_close (lua_State *L) {
+  lua_getfenv(L, 1);
+  lua_getfield(L, -1, "__close");
+  return (lua_tocfunction(L, -1))(L);
+}
+
+
+static int io_gc (lua_State *L) {
+  FILE *f = *tofilep(L);
+  /* ignore closed files */
+  if (f != NULL)
+    aux_close(L);
+  return 0;
+}
+
+
+static int io_tostring (lua_State *L) {
+  FILE *f = *tofilep(L);
+  if (f == NULL)
+    lua_pushliteral(L, "file (closed)");
+  else
+    lua_pushfstring(L, "file (%p)", f);
+  return 1;
+}
+
+
+// Create directories in the path
+void MakePathDirs(char *path)
+{
+	char *c;
+
+	for (c = path; *c; c++)
+		if (*c == '/' || *c == '\\')
+		{
+			char sep = *c;
+			*c = '\0';
+			I_mkdir(path, 0755);
+			*c = sep;
+		}
+}
+
+
+static int io_open (lua_State *L) {
+	FILE **pf;
+	const char *filename = luaL_checkstring(L, 1);
+	boolean pass = false;
+	size_t i;
+	int length = strlen(filename);
+	const char *mode = luaL_optstring(L, 2, "r");
+	luafiletransfer_t *filetransfer;
+
+	if (strchr(filename, '\\'))
+	{
+		luaL_error(L, "access denied to %s: \\ is not allowed, use / instead", filename);
+		return pushresult(L,0,filename);
+	}
+
+	for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++)
+		if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i]))
+		{
+			pass = true;
+			break;
+		}
+	if (strstr(filename, "./")
+		|| strstr(filename, "..") || strchr(filename, ':')
+		|| filename[0] == '/'
+		|| !pass)
+	{
+		luaL_error(L, "access denied to %s", filename);
+		return pushresult(L,0,filename);
+	}
+
+	luaL_checktype(L, 4, LUA_TFUNCTION);
+
+	if (lua_isnil(L, 3) && (strchr(mode, 'r') || strchr(mode, '+'))) // Synched reading
+	{
+		AddLuaFileTransfer(filename, mode);
+
+		/*pf = newfile(L);
+		*pf = fopen(realfilename, mode);
+		return (*pf == NULL) ? pushresult(L, 0, filename) : 1;*/
+	}
+	else // Local I/O
+	{
+		char *realfilename = va("%s" PATHSEP "%s", luafiledir, filename);
+		player_t *player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
+
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+
+		if (player != &players[consoleplayer])
+			return 0;
+
+		if (client && strnicmp(filename, "shared/", strlen("shared/")))
+			I_Error("Access denied to %s\n"
+					"Clients can only access files stored in luafiles/shared/\n",
+					filename);
+
+		// Prevent access if the file is being downloaded
+		for (filetransfer = luafiletransfers; filetransfer; filetransfer = filetransfer->next)
+			if (!stricmp(filetransfer->filename, filename))
+				I_Error("Access denied to %s\n"
+						"Files can't be opened while being downloaded\n",
+						filename);
+
+		MakePathDirs(realfilename);
+
+		// The callback is the last argument, no need to push it again
+
+		// Push the first argument (file handle) on the stack
+		pf = newfile(gL); // Create and push the file handle
+		*pf = fopen(realfilename, mode); // Open the file
+		if (!*pf)
+		{
+			lua_pop(gL, 1);
+			lua_pushnil(gL);
+		}
+
+		// Push the second argument (file name) on the stack
+		lua_pushstring(gL, filename);
+
+		// Call the callback
+		LUA_Call(gL, 2);
+
+		// Close the file
+		if (*pf)
+		{
+			fclose(*pf);
+			*pf = NULL;
+		}
+	}
+
+	return 0; // !!! Todo: error handling?
+}
+
+
+void Got_LuaFile(UINT8 **cp, INT32 playernum)
+{
+	FILE **pf;
+	boolean success = READUINT8(*cp); // The first (and only) byte indicates whether the file could be opened
+
+	if (playernum != serverplayer)
+	{
+		CONS_Alert(CONS_WARNING, M_GetText("Illegal luafile command received from %s\n"), player_names[playernum]);
+		if (server)
+			SendKick(playernum, KICK_MSG_CON_FAIL);
+		return;
+	}
+
+	if (!luafiletransfers)
+		I_Error("No Lua file transfer\n");
+
+	// Retrieve the callback and push it on the stack
+	lua_pushfstring(gL, FMT_FILECALLBACKID, luafiletransfers->id);
+	lua_gettable(gL, LUA_REGISTRYINDEX);
+
+	// Push the first argument (file handle or nil) on the stack
+	if (success)
+	{
+		pf = newfile(gL); // Create and push the file handle
+		*pf = fopen(luafiletransfers->realfilename, luafiletransfers->mode); // Open the file
+		if (!*pf)
+			I_Error("Can't open file \"%s\"\n", luafiletransfers->realfilename); // The file SHOULD exist
+	}
+	else
+		lua_pushnil(gL);
+
+	// Push the second argument (file name) on the stack
+	lua_pushstring(gL, luafiletransfers->filename);
+
+	// Call the callback
+	LUA_Call(gL, 2);
+
+	if (success)
+	{
+		// Close the file
+		if (*pf)
+		{
+			fclose(*pf);
+			*pf = NULL;
+		}
+
+		if (client)
+			remove(luafiletransfers->realfilename);
+	}
+
+	RemoveLuaFileTransfer();
+
+	if (server && luafiletransfers)
+	{
+		if (FIL_FileOK(luafiletransfers->realfilename))
+			SV_PrepareSendLuaFileToNextNode();
+		else
+		{
+			// Send a net command with 0 as its first byte to indicate the file couldn't be opened
+			UINT8 success = 0;
+			SendNetXCmd(XD_LUAFILE, &success, 1);
+		}
+	}
+}
+
+
+void StoreLuaFileCallback(INT32 id)
+{
+	lua_pushfstring(gL, FMT_FILECALLBACKID, id);
+	lua_pushvalue(gL, 4); // Parameter 4 is the callback
+	lua_settable(gL, LUA_REGISTRYINDEX); // registry[callbackid] = callback
+}
+
+
+void RemoveLuaFileCallback(INT32 id)
+{
+	lua_pushfstring(gL, FMT_FILECALLBACKID, id);
+	lua_pushnil(gL);
+	lua_settable(gL, LUA_REGISTRYINDEX); // registry[callbackid] = nil
+}
+
+static int io_tmpfile (lua_State *L) {
+  FILE **pf = newfile(L);
+  *pf = tmpfile();
+  return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
+}
+
+
+static FILE *getiofile (lua_State *L, int findex) {
+  FILE *f;
+  lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
+  f = *(FILE **)lua_touserdata(L, -1);
+  if (f == NULL)
+    luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
+  return f;
+}
+
+
+static int g_iofile (lua_State *L, int f, const char *mode) {
+  if (!lua_isnoneornil(L, 1)) {
+    const char *filename = lua_tostring(L, 1);
+    if (filename) {
+      FILE **pf = newfile(L);
+      *pf = fopen(filename, mode);
+      if (*pf == NULL)
+        fileerror(L, 1, filename);
+    }
+    else {
+      tofile(L);  /* check that it's a valid file handle */
+      lua_pushvalue(L, 1);
+    }
+    lua_rawseti(L, LUA_ENVIRONINDEX, f);
+  }
+  /* return current value */
+  lua_rawgeti(L, LUA_ENVIRONINDEX, f);
+  return 1;
+}
+
+
+static int io_input (lua_State *L) {
+  return g_iofile(L, IO_INPUT, "r");
+}
+
+
+static int io_output (lua_State *L) {
+  return g_iofile(L, IO_OUTPUT, "w");
+}
+
+
+static int io_readline (lua_State *L);
+
+
+static void aux_lines (lua_State *L, int idx, int toclose) {
+  lua_pushvalue(L, idx);
+  lua_pushboolean(L, toclose);  /* close/not close file when finished */
+  lua_pushcclosure(L, io_readline, 2);
+}
+
+
+static int f_lines (lua_State *L) {
+  tofile(L);  /* check that it's a valid file handle */
+  aux_lines(L, 1, 0);
+  return 1;
+}
+
+
+static int io_lines (lua_State *L) {
+  if (lua_isnoneornil(L, 1)) {  /* no arguments? */
+    /* will iterate over default input */
+    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
+    return f_lines(L);
+  }
+  else {
+    const char *filename = luaL_checkstring(L, 1);
+    FILE **pf = newfile(L);
+    *pf = fopen(filename, "r");
+    if (*pf == NULL)
+      fileerror(L, 1, filename);
+    aux_lines(L, lua_gettop(L), 1);
+    return 1;
+  }
+}
+
+
+/*
+** {======================================================
+** READ
+** =======================================================
+*/
+
+
+static int read_number (lua_State *L, FILE *f) {
+  lua_Number d;
+  if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
+    lua_pushnumber(L, d);
+    return 1;
+  }
+  else return 0;  /* read fails */
+}
+
+
+static int test_eof (lua_State *L, FILE *f) {
+  int c = getc(f);
+  ungetc(c, f);
+  lua_pushlstring(L, NULL, 0);
+  return (c != EOF);
+}
+
+
+static int read_line (lua_State *L, FILE *f) {
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
+  for (;;) {
+    size_t l;
+    char *p = luaL_prepbuffer(&b);
+    if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */
+      luaL_pushresult(&b);  /* close buffer */
+      return (lua_objlen(L, -1) > 0);  /* check whether read something */
+    }
+    l = strlen(p);
+    if (l == 0 || p[l-1] != '\n')
+      luaL_addsize(&b, l);
+    else {
+      luaL_addsize(&b, l - 1);  /* do not include `eol' */
+      luaL_pushresult(&b);  /* close buffer */
+      return 1;  /* read at least an `eol' */
+    }
+  }
+}
+
+
+static int read_chars (lua_State *L, FILE *f, size_t n) {
+  size_t rlen;  /* how much to read */
+  size_t nr;  /* number of chars actually read */
+  luaL_Buffer b;
+  luaL_buffinit(L, &b);
+  rlen = LUAL_BUFFERSIZE;  /* try to read that much each time */
+  do {
+    char *p = luaL_prepbuffer(&b);
+    if (rlen > n) rlen = n;  /* cannot read more than asked */
+    nr = fread(p, sizeof(char), rlen, f);
+    luaL_addsize(&b, nr);
+    n -= nr;  /* still have to read `n' chars */
+  } while (n > 0 && nr == rlen);  /* until end of count or eof */
+  luaL_pushresult(&b);  /* close buffer */
+  return (n == 0 || lua_objlen(L, -1) > 0);
+}
+
+
+static int g_read (lua_State *L, FILE *f, int first) {
+  int nargs = lua_gettop(L) - 1;
+  int success;
+  int n;
+  clearerr(f);
+  if (nargs == 0) {  /* no arguments? */
+    success = read_line(L, f);
+    n = first+1;  /* to return 1 result */
+  }
+  else {  /* ensure stack space for all results and for auxlib's buffer */
+    luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
+    success = 1;
+    for (n = first; nargs-- && success; n++) {
+      if (lua_type(L, n) == LUA_TNUMBER) {
+        size_t l = (size_t)lua_tointeger(L, n);
+        success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
+      }
+      else {
+        const char *p = lua_tostring(L, n);
+        luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
+        switch (p[1]) {
+          case 'n':  /* number */
+            success = read_number(L, f);
+            break;
+          case 'l':  /* line */
+            success = read_line(L, f);
+            break;
+          case 'a':  /* file */
+            read_chars(L, f, ~((size_t)0));  /* read MAX_SIZE_T chars */
+            success = 1; /* always success */
+            break;
+          default:
+            return luaL_argerror(L, n, "invalid format");
+        }
+      }
+    }
+  }
+  if (ferror(f))
+    return pushresult(L, 0, NULL);
+  if (!success) {
+    lua_pop(L, 1);  /* remove last result */
+    lua_pushnil(L);  /* push nil instead */
+  }
+  return n - first;
+}
+
+
+static int io_read (lua_State *L) {
+  return g_read(L, getiofile(L, IO_INPUT), 1);
+}
+
+
+static int f_read (lua_State *L) {
+  return g_read(L, tofile(L), 2);
+}
+
+
+static int io_readline (lua_State *L) {
+  FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
+  int sucess;
+  if (f == NULL)  /* file is already closed? */
+    luaL_error(L, "file is already closed");
+  sucess = read_line(L, f);
+  if (ferror(f))
+    return luaL_error(L, "%s", strerror(errno));
+  if (sucess) return 1;
+  else {  /* EOF */
+    if (lua_toboolean(L, lua_upvalueindex(2))) {  /* generator created file? */
+      lua_settop(L, 0);
+      lua_pushvalue(L, lua_upvalueindex(1));
+      aux_close(L);  /* close it */
+    }
+    return 0;
+  }
+}
+
+/* }====================================================== */
+
+
+static int g_write (lua_State *L, FILE *f, int arg) {
+  int nargs = lua_gettop(L) - 1;
+  int status = 1;
+  size_t count;
+  for (; nargs--; arg++) {
+    if (lua_type(L, arg) == LUA_TNUMBER) {
+      /* optimization: could be done exactly as for strings */
+      status = status &&
+          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+    }
+    else {
+      size_t l;
+      const char *s = luaL_checklstring(L, arg, &l);
+	  count += l;
+	  if (ftell(f) + l > FILELIMIT)
+	  {
+		luaL_error(L,"write limit bypassed in file. Changes have been discarded.");
+		break;
+	  }
+      status = status && (fwrite(s, sizeof(char), l, f) == l);
+    }
+  }
+  return pushresult(L, status, NULL);
+}
+
+
+static int io_write (lua_State *L) {
+  return g_write(L, getiofile(L, IO_OUTPUT), 1);
+}
+
+
+static int f_write (lua_State *L) {
+  return g_write(L, tofile(L), 2);
+}
+
+
+static int f_seek (lua_State *L) {
+  static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
+  static const char *const modenames[] = {"set", "cur", "end", NULL};
+  FILE *f = tofile(L);
+  int op = luaL_checkoption(L, 2, "cur", modenames);
+  long offset = luaL_optlong(L, 3, 0);
+  op = fseek(f, offset, mode[op]);
+  if (op)
+    return pushresult(L, 0, NULL);  /* error */
+  else {
+    lua_pushinteger(L, ftell(f));
+    return 1;
+  }
+}
+
+
+static int f_setvbuf (lua_State *L) {
+  static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
+  static const char *const modenames[] = {"no", "full", "line", NULL};
+  FILE *f = tofile(L);
+  int op = luaL_checkoption(L, 2, NULL, modenames);
+  lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
+  int res = setvbuf(f, NULL, mode[op], sz);
+  return pushresult(L, res == 0, NULL);
+}
+
+
+
+static int io_flush (lua_State *L) {
+  return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
+}
+
+
+static int f_flush (lua_State *L) {
+  return pushresult(L, fflush(tofile(L)) == 0, NULL);
+}
+
+
+static const luaL_Reg iolib[] = {
+  {"flush", io_flush},
+  {"input", io_input},
+  {"lines", io_lines},
+  {"open", io_open},
+  {"output", io_output},
+  {"read", io_read},
+  {"tmpfile", io_tmpfile},
+  {"type", io_type},
+  {"write", io_write},
+  {NULL, NULL}
+};
+
+
+static const luaL_Reg flib[] = {
+  {"flush", f_flush},
+  {"lines", f_lines},
+  {"read", f_read},
+  {"seek", f_seek},
+  {"setvbuf", f_setvbuf},
+  {"write", f_write},
+  {"__gc", io_gc},
+  {"__tostring", io_tostring},
+  {NULL, NULL}
+};
+
+
+static void createmeta (lua_State *L) {
+  luaL_newmetatable(L, LUA_FILEHANDLE);  /* create metatable for file handles */
+  lua_pushvalue(L, -1);  /* push metatable */
+  lua_setfield(L, -2, "__index");  /* metatable.__index = metatable */
+  luaL_register(L, NULL, flib);  /* file methods */
+}
+
+
+static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
+  *newfile(L) = f;
+  if (k > 0) {
+    lua_pushvalue(L, -1);
+    lua_rawseti(L, LUA_ENVIRONINDEX, k);
+  }
+  lua_pushvalue(L, -2);  /* copy environment */
+  lua_setfenv(L, -2);  /* set it */
+  lua_setfield(L, -3, fname);
+}
+
+
+static void newfenv (lua_State *L, lua_CFunction cls) {
+  lua_createtable(L, 0, 1);
+  lua_pushcfunction(L, cls);
+  lua_setfield(L, -2, "__close");
+}
+
+
+LUALIB_API int luaopen_io (lua_State *L) {
+  createmeta(L);
+  /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
+  newfenv(L, io_fclose);
+  lua_replace(L, LUA_ENVIRONINDEX);
+  /* open library */
+  luaL_register(L, LUA_IOLIBNAME, iolib);
+  /* create (and set) default files */
+  newfenv(L, io_noclose);  /* close function for default files */
+  createstdfile(L, stdin, IO_INPUT, "stdin");
+  createstdfile(L, stdout, IO_OUTPUT, "stdout");
+  createstdfile(L, stderr, 0, "stderr");
+  lua_pop(L, 1);  /* pop environment for default files */
+  return 1;
+}
+
diff --git a/src/blua/lualib.h b/src/blua/lualib.h
index 6ebe27287..4ea97edf3 100644
--- a/src/blua/lualib.h
+++ b/src/blua/lualib.h
@@ -21,6 +21,9 @@ LUALIB_API int (luaopen_base) (lua_State *L);
 #define LUA_TABLIBNAME	"table"
 LUALIB_API int (luaopen_table) (lua_State *L);
 
+#define LUA_IOLIBNAME	"io"
+LUALIB_API int (luaopen_io) (lua_State *L);
+
 #define LUA_STRLIBNAME	"string"
 LUALIB_API int (luaopen_string) (lua_State *L);
 
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 8b87672bf..6b0f49544 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -3164,6 +3164,8 @@ void D_QuitNetGame(void)
 
 	// abort send/receive of files
 	CloseNetFile();
+	RemoveLuaFileTransfers();
+	waitingforluafiletransfer = false;
 
 	if (server)
 	{
@@ -3534,6 +3536,10 @@ static void HandleConnect(SINT8 node)
 		SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
 	else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join?
 		SV_SendRefuse(node, M_GetText("No players from\nthis node."));
+#ifdef HAVE_BLUA
+	else if (luafiletransfers)
+		SV_SendRefuse(node, M_GetText("The server is broadcasting a file\nrequested by a Lua script.\nPlease wait a bit and then\ntry rejoining."));
+#endif
 	else
 	{
 #ifndef NONET
@@ -4117,6 +4123,20 @@ static void HandlePacketFromPlayer(SINT8 node)
 			Net_CloseConnection(node);
 			nodeingame[node] = false;
 			break;
+#ifdef HAVE_BLUA
+		case PT_ASKLUAFILE:
+			if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_ASKED)
+			{
+				char *name = va("%s" PATHSEP "%s", luafiledir, luafiletransfers->filename);
+				boolean textmode = !strchr(luafiletransfers->mode, 'b');
+				SV_SendLuaFile(node, name, textmode);
+			}
+			break;
+		case PT_HASLUAFILE:
+			if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_SENDING)
+				SV_HandleLuaFileSent(node);
+			break;
+#endif
 // -------------------------------------------- CLIENT RECEIVE ----------
 		case PT_RESYNCHEND:
 			// Only accept PT_RESYNCHEND from the server.
@@ -4244,6 +4264,12 @@ static void HandlePacketFromPlayer(SINT8 node)
 			if (client)
 				Got_Filetxpak();
 			break;
+#ifdef HAVE_BLUA
+		case PT_SENDINGLUAFILE:
+			if (client)
+				CL_PrepareDownloadLuaFile();
+			break;
+#endif
 		default:
 			DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n",
 				netbuffer->packettype, node));
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index 408d0f8dd..4aaa9be6b 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -67,6 +67,12 @@ typedef enum
 	PT_RESYNCHEND,    // Player is now resynched and is being requested to remake the gametic
 	PT_RESYNCHGET,    // Player got resynch packet
 
+#ifdef HAVE_BLUA
+	PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file
+	PT_ASKLUAFILE,     // Client telling the server they don't have the file
+	PT_HASLUAFILE,     // Client telling the server they have the file
+#endif
+
 	// Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility.
 
 	PT_CANFAIL,       // This is kind of a priority. Anything bigger than CANFAIL
diff --git a/src/d_main.c b/src/d_main.c
index 15d3c8041..b4eebb275 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1113,6 +1113,7 @@ void D_SRB2Main(void)
 			// can't use sprintf since there is %u in savegamename
 			strcatbf(savegamename, srb2home, PATHSEP);
 
+			snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", srb2home);
 #else
 			snprintf(srb2home, sizeof srb2home, "%s", userhome);
 			snprintf(downloaddir, sizeof downloaddir, "%s", userhome);
@@ -1123,6 +1124,8 @@ void D_SRB2Main(void)
 
 			// can't use sprintf since there is %u in savegamename
 			strcatbf(savegamename, userhome, PATHSEP);
+
+			snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome);
 #endif
 		}
 
diff --git a/src/d_net.c b/src/d_net.c
index 573c9cfe9..ddb991235 100644
--- a/src/d_net.c
+++ b/src/d_net.c
@@ -715,6 +715,10 @@ void Net_CloseConnection(INT32 node)
 
 	InitNode(&nodes[node]);
 	SV_AbortSendFiles(node);
+#ifdef HAVE_BLUA
+	if (server)
+		SV_AbortLuaFileTransfer(node);
+#endif
 	I_NetFreeNodenum(node);
 #endif
 }
@@ -799,6 +803,10 @@ static const char *packettypename[NUMPACKETTYPE] =
 	"RESYNCHEND",
 	"RESYNCHGET",
 
+	"SENDINGLUAFILE",
+	"ASKLUAFILE",
+	"HASLUAFILE",
+
 	"FILEFRAGMENT",
 	"TEXTCMD",
 	"TEXTCMD2",
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index a597bad83..42b560a85 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -417,7 +417,8 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
 	"SUICIDE",
 #ifdef HAVE_BLUA
 	"LUACMD",
-	"LUAVAR"
+	"LUAVAR",
+	"LUAFILE"
 #endif
 };
 
@@ -453,6 +454,7 @@ void D_RegisterServerCommands(void)
 	RegisterNetXCmd(XD_RUNSOC, Got_RunSOCcmd);
 #ifdef HAVE_BLUA
 	RegisterNetXCmd(XD_LUACMD, Got_Luacmd);
+	RegisterNetXCmd(XD_LUAFILE, Got_LuaFile);
 #endif
 
 	// Remote Administration
diff --git a/src/d_netcmd.h b/src/d_netcmd.h
index 8f857c6db..5f3967a67 100644
--- a/src/d_netcmd.h
+++ b/src/d_netcmd.h
@@ -145,6 +145,7 @@ typedef enum
 #ifdef HAVE_BLUA
 	XD_LUACMD,      // 22
 	XD_LUAVAR,      // 23
+	XD_LUAFILE,     // 24
 #endif
 	MAXNETXCMD
 } netxcmd_t;
diff --git a/src/d_netfil.c b/src/d_netfil.c
index 93b4b1990..5ceec2aaa 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -69,6 +69,7 @@ typedef struct filetx_s
 	UINT32 size; // Size of the file
 	UINT8 fileid;
 	INT32 node; // Destination
+	boolean textmode; // For files requested by Lua without the "b" option
 	struct filetx_s *next; // Next file in the list
 } filetx_t;
 
@@ -94,6 +95,13 @@ char downloaddir[512] = "DOWNLOAD";
 INT32 lastfilenum = -1;
 #endif
 
+#ifdef HAVE_BLUA
+luafiletransfer_t *luafiletransfers = NULL;
+boolean waitingforluafiletransfer = false;
+char luafiledir[256] = "luafiles";
+#endif
+
+
 /** Fills a serverinfo packet with information about wad files loaded.
   *
   * \todo Give this function a better name since it is in global scope.
@@ -159,6 +167,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
 		fileneeded[i].file = NULL; // The file isn't open yet
 		READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH); // The next bytes are the file name
 		READMEM(p, fileneeded[i].md5sum, 16); // The last 16 bytes are the file checksum
+		fileneeded[i].textmode = false;
 	}
 }
 
@@ -170,6 +179,7 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave)
 	fileneeded[0].file = NULL;
 	memset(fileneeded[0].md5sum, 0, 16);
 	strcpy(fileneeded[0].filename, tmpsave);
+	fileneeded[0].textmode = false;
 }
 
 /** Checks the server to see if we CAN download all the files,
@@ -448,6 +458,164 @@ void CL_LoadServerFiles(void)
 	}
 }
 
+#ifdef HAVE_BLUA
+void AddLuaFileTransfer(const char *filename, const char *mode)
+{
+	luafiletransfer_t **prevnext; // A pointer to the "next" field of the last transfer in the list
+	luafiletransfer_t *filetransfer;
+	static INT32 id;
+
+	//CONS_Printf("AddLuaFileTransfer \"%s\"\n", filename);
+
+	// Find the last transfer in the list and set a pointer to its "next" field
+	prevnext = &luafiletransfers;
+	while (*prevnext)
+		prevnext = &((*prevnext)->next);
+
+	// Allocate file transfer information and append it to the transfer list
+	filetransfer = malloc(sizeof(luafiletransfer_t));
+	if (!filetransfer)
+		I_Error("AddLuaFileTransfer: Out of memory\n");
+	*prevnext = filetransfer;
+    filetransfer->next = NULL;
+
+    // Allocate the file name
+    filetransfer->filename = strdup(filename);
+    if (!filetransfer->filename)
+		I_Error("AddLuaFileTransfer: Out of memory\n");
+
+    // Create and allocate the real file name
+	if (server)
+		filetransfer->realfilename = strdup(va("%s" PATHSEP "%s",
+												luafiledir, filename));
+	else
+		filetransfer->realfilename = strdup(va("%s" PATHSEP "shared" PATHSEP "$$$%d%d.tmp",
+												luafiledir, rand(), rand()));
+    if (!filetransfer->realfilename)
+		I_Error("AddLuaFileTransfer: Out of memory\n");
+
+	strlcpy(filetransfer->mode, mode, sizeof(filetransfer->mode));
+
+	if (server)
+	{
+		INT32 i;
+
+		// Set status to "waiting" for everyone
+		for (i = 0; i < MAXNETNODES; i++)
+			filetransfer->nodestatus[i] = LFTNS_WAITING;
+
+		if (!luafiletransfers->next) // Only if there is no transfer already going on
+		{
+			if (FIL_FileOK(filetransfer->realfilename))
+				SV_PrepareSendLuaFileToNextNode();
+			else
+			{
+				// Send a net command with 0 as its first byte to indicate the file couldn't be opened
+				UINT8 success = 0;
+				SendNetXCmd(XD_LUAFILE, &success, 1);
+			}
+		}
+	}
+
+	// Store the callback so it can be called once everyone has the file
+	filetransfer->id = id;
+	StoreLuaFileCallback(id);
+	id++;
+
+	if (waitingforluafiletransfer)
+	{
+		waitingforluafiletransfer = false;
+		CL_PrepareDownloadLuaFile();
+	}
+}
+
+void SV_PrepareSendLuaFileToNextNode(void)
+{
+	INT32 i;
+	UINT8 success = 1;
+
+    // Find a client to send the file to
+	for (i = 1; i < MAXNETNODES; i++)
+		if (nodeingame[i] && luafiletransfers->nodestatus[i] == LFTNS_WAITING) // Node waiting
+		{
+			// Tell the client we're about to send them the file
+			netbuffer->packettype = PT_SENDINGLUAFILE;
+			if (!HSendPacket(i, true, 0, 0))
+				I_Error("Failed to send a PT_SENDINGLUAFILE packet\n"); // !!! Todo: Handle failure a bit better lol
+
+			luafiletransfers->nodestatus[i] = LFTNS_ASKED;
+
+			return;
+		}
+
+	// No client found, everyone has the file
+	// Send a net command with 1 as its first byte to indicate the file could be opened
+	SendNetXCmd(XD_LUAFILE, &success, 1);
+}
+
+void SV_HandleLuaFileSent(UINT8 node)
+{
+	luafiletransfers->nodestatus[node] = LFTNS_SENT;
+    SV_PrepareSendLuaFileToNextNode();
+}
+
+void RemoveLuaFileTransfer(void)
+{
+	luafiletransfer_t *filetransfer = luafiletransfers;
+
+	RemoveLuaFileCallback(filetransfer->id);
+
+	luafiletransfers = filetransfer->next;
+
+	free(filetransfer->filename);
+	free(filetransfer->realfilename);
+	free(filetransfer);
+}
+
+void RemoveLuaFileTransfers(void)
+{
+	while (luafiletransfers)
+		RemoveLuaFileTransfer();
+}
+
+void SV_AbortLuaFileTransfer(INT32 node)
+{
+	if (luafiletransfers
+	&& (luafiletransfers->nodestatus[node] == LFTNS_ASKED
+	||  luafiletransfers->nodestatus[node] == LFTNS_SENDING))
+	{
+		luafiletransfers->nodestatus[node] = LFTNS_WAITING;
+		SV_PrepareSendLuaFileToNextNode();
+	}
+}
+
+void CL_PrepareDownloadLuaFile(void)
+{
+	// If there is no transfer in the list, this normally means the server
+	// called io.open before us, so we have to wait until we call it too
+	if (!luafiletransfers)
+	{
+		waitingforluafiletransfer = true;
+		return;
+	}
+
+	// Tell the server we are ready to receive the file
+	netbuffer->packettype = PT_ASKLUAFILE;
+	HSendPacket(servernode, true, 0, 0);
+
+	fileneedednum = 1;
+	fileneeded[0].status = FS_REQUESTED;
+	fileneeded[0].totalsize = UINT32_MAX;
+	fileneeded[0].file = NULL;
+	memset(fileneeded[0].md5sum, 0, 16);
+	strcpy(fileneeded[0].filename, luafiletransfers->realfilename);
+	fileneeded[0].textmode = !strchr(luafiletransfers->mode, 'b');
+
+	// Make sure all directories in the file path exist
+	MakePathDirs(fileneeded[0].filename);
+}
+#endif
+
 // Number of files to send
 // Little optimization to quickly test if there is a file in the queue
 static INT32 filestosend = 0;
@@ -458,6 +626,7 @@ static INT32 filestosend = 0;
   * \param filename The file to send
   * \param fileid ???
   * \sa SV_SendRam
+  * \sa SV_SendLuaFile
   *
   */
 static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
@@ -548,6 +717,7 @@ static boolean SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
   * \param freemethod How to free the block after it has been sent
   * \param fileid ???
   * \sa SV_SendFile
+  * \sa SV_SendLuaFile
   *
   */
 void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid)
@@ -579,6 +749,57 @@ void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UI
 	filestosend++;
 }
 
+#ifdef HAVE_BLUA
+/** Adds a file requested by Lua to the file list for a node
+  *
+  * \param node The node to send the file to
+  * \param filename The file to send
+  * \sa SV_SendFile
+  * \sa SV_SendRam
+  *
+  */
+boolean SV_SendLuaFile(INT32 node, const char *filename, boolean textmode)
+{
+	filetx_t **q; // A pointer to the "next" field of the last file in the list
+	filetx_t *p; // The new file request
+	//INT32 i;
+	//char wadfilename[MAX_WADPATH];
+
+	luafiletransfers->nodestatus[node] = LFTNS_SENDING;
+
+	// Find the last file in the list and set a pointer to its "next" field
+	q = &transfer[node].txlist;
+	while (*q)
+		q = &((*q)->next);
+
+	// Allocate a file request and append it to the file list
+	p = *q = (filetx_t *)malloc(sizeof (filetx_t));
+	if (!p)
+		I_Error("SV_SendLuaFile: No more memory\n");
+
+	// Initialise with zeros
+	memset(p, 0, sizeof (filetx_t));
+
+	// Allocate the file name
+	p->id.filename = (char *)malloc(MAX_WADPATH); // !!!
+	if (!p->id.filename)
+		I_Error("SV_SendLuaFile: No more memory\n");
+
+	// Set the file name and get rid of the path
+	strlcpy(p->id.filename, filename, MAX_WADPATH); // !!!
+	//nameonly(p->id.filename);
+
+	// Open in text mode if required by the Lua script
+	p->textmode = textmode;
+
+	DEBFILE(va("Sending Lua file %s to %d\n", filename, node));
+	p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it
+	p->next = NULL; // End of list
+	filestosend++;
+	return true;
+}
+#endif
+
 /** Stops sending a file for a node, and removes the file request from the list,
   * either because the file has been fully sent or because the node was disconnected
   *
@@ -684,7 +905,7 @@ void SV_FileSendTicker(void)
 				long filesize;
 
 				transfer[i].currentfile =
-					fopen(f->id.filename, "rb");
+					fopen(f->id.filename, f->textmode ? "r" : "rb");
 
 				if (!transfer[i].currentfile)
 					I_Error("File %s does not exist",
@@ -715,11 +936,20 @@ void SV_FileSendTicker(void)
 			size = f->size-transfer[i].position;
 		if (ram)
 			M_Memcpy(p->data, &f->id.ram[transfer[i].position], size);
-		else if (fread(p->data, 1, size, transfer[i].currentfile) != size)
-			I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, M_FileError(transfer[i].currentfile));
+		else
+		{
+			size_t n = fread(p->data, 1, size, transfer[i].currentfile);
+			if (n != size) // Either an error or Windows turning CR-LF into LF
+			{
+				if (f->textmode && feof(transfer[i].currentfile))
+                    size = n;
+				else if (fread(p->data, 1, size, transfer[i].currentfile) != size)
+					I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, M_FileError(transfer[i].currentfile));
+			}
+		}
 		p->position = LONG(transfer[i].position);
 		// Put flag so receiver knows the total size
-		if (transfer[i].position + size == f->size)
+		if (transfer[i].position + size == f->size || (f->textmode && feof(transfer[i].currentfile)))
 			p->position |= LONG(0x80000000);
 		p->fileid = f->fileid;
 		p->size = SHORT((UINT16)size);
@@ -728,7 +958,7 @@ void SV_FileSendTicker(void)
 		if (HSendPacket(i, true, 0, FILETXHEADER + size)) // Reliable SEND
 		{ // Success
 			transfer[i].position = (UINT32)(transfer[i].position + size);
-			if (transfer[i].position == f->size) // Finish?
+			if (transfer[i].position == f->size || (f->textmode && feof(transfer[i].currentfile))) // Finish?
 				SV_EndFileSend(i);
 		}
 		else
@@ -772,7 +1002,7 @@ void Got_Filetxpak(void)
 	{
 		if (file->file)
 			I_Error("Got_Filetxpak: already open file\n");
-		file->file = fopen(filename, "wb");
+		file->file = fopen(filename, file->textmode ? "w" : "wb");
 		if (!file->file)
 			I_Error("Can't create file %s: %s", filename, strerror(errno));
 		CONS_Printf("\r%s...\n",filename);
@@ -793,7 +1023,7 @@ void Got_Filetxpak(void)
 		}
 		// We can receive packet in the wrong order, anyway all os support gaped file
 		fseek(file->file, pos, SEEK_SET);
-		if (fwrite(netbuffer->u.filetxpak.data,size,1,file->file) != 1)
+		if (size && fwrite(netbuffer->u.filetxpak.data,size,1,file->file) != 1)
 			I_Error("Can't write to %s: %s\n",filename, M_FileError(file->file));
 		file->currentsize += size;
 
@@ -805,6 +1035,14 @@ void Got_Filetxpak(void)
 			file->status = FS_FOUND;
 			CONS_Printf(M_GetText("Downloading %s...(done)\n"),
 				filename);
+#ifdef HAVE_BLUA
+            if (luafiletransfers)
+			{
+                // Tell the server we have received the file
+                netbuffer->packettype = PT_HASLUAFILE;
+                HSendPacket(servernode, true, 0, 0);
+			}
+#endif
 		}
 	}
 	else
diff --git a/src/d_netfil.h b/src/d_netfil.h
index 17aeb8b7e..0d0b16975 100644
--- a/src/d_netfil.h
+++ b/src/d_netfil.h
@@ -13,6 +13,7 @@
 #ifndef __D_NETFIL__
 #define __D_NETFIL__
 
+#include "d_net.h"
 #include "w_wad.h"
 
 typedef enum
@@ -43,6 +44,7 @@ typedef struct
 	UINT32 currentsize;
 	UINT32 totalsize;
 	filestatus_t status; // The value returned by recsearch
+	boolean textmode; // For files requested by Lua without the "b" option
 } fileneeded_t;
 
 extern INT32 fileneedednum;
@@ -70,6 +72,44 @@ boolean CL_CheckDownloadable(void);
 boolean CL_SendRequestFile(void);
 boolean Got_RequestFilePak(INT32 node);
 
+#ifdef HAVE_BLUA
+typedef enum
+{
+	LFTNS_WAITING, // This node is waiting for the server to send the file
+	LFTNS_ASKED, // The server has told the node they're ready to send the file
+	LFTNS_SENDING, // The server is sending the file to this node
+	LFTNS_SENT // The node already has the file
+} luafiletransfernodestatus_t;
+
+typedef struct luafiletransfer_s
+{
+	char *filename;
+	char *realfilename;
+	char mode[4]; // rb+/wb+/ab+ + null character
+	INT32 id; // Callback ID
+	luafiletransfernodestatus_t nodestatus[MAXNETNODES];
+	struct luafiletransfer_s *next;
+} luafiletransfer_t;
+
+extern luafiletransfer_t *luafiletransfers;
+extern boolean waitingforluafiletransfer;
+extern char luafiledir[256];
+
+void AddLuaFileTransfer(const char *filename, const char *mode);
+void SV_PrepareSendLuaFileToNextNode(void);
+boolean SV_SendLuaFile(INT32 node, const char *filename, boolean textmode);
+void SV_PrepareSendLuaFile(const char *filename);
+void SV_HandleLuaFileSent(UINT8 node);
+void RemoveLuaFileTransfer(void);
+void RemoveLuaFileTransfers(void);
+void SV_AbortLuaFileTransfer(INT32 node);
+void CL_PrepareDownloadLuaFile(void);
+void Got_LuaFile(UINT8 **cp, INT32 playernum);
+void StoreLuaFileCallback(INT32 id);
+void RemoveLuaFileCallback(INT32 id);
+void MakePathDirs(char *path);
+#endif
+
 void SV_AbortSendFiles(INT32 node);
 void CloseNetFile(void);
 

From 3b22a84296a239859adba85f6b27f4947631cff4 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Fri, 24 Jan 2020 02:47:51 +0100
Subject: [PATCH 009/251] Split open() into open() and openlocal()

open() for normal, consistency-friendly reading,
openlocal() for writing and local reading.
---
 src/blua/liolib.c | 122 +++++++++++++++++++++++-----------------------
 1 file changed, 62 insertions(+), 60 deletions(-)

diff --git a/src/blua/liolib.c b/src/blua/liolib.c
index 6ebde08a3..dc425f3c0 100644
--- a/src/blua/liolib.c
+++ b/src/blua/liolib.c
@@ -137,6 +137,14 @@ static int aux_close (lua_State *L) {
 }
 
 
+static int io_close (lua_State *L) {
+  if (lua_isnone(L, 1))
+    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
+  tofile(L);  /* make sure argument is a file */
+  return aux_close(L);
+}
+
+
 static int io_gc (lua_State *L) {
   FILE *f = *tofilep(L);
   /* ignore closed files */
@@ -172,14 +180,11 @@ void MakePathDirs(char *path)
 }
 
 
-static int io_open (lua_State *L) {
-	FILE **pf;
-	const char *filename = luaL_checkstring(L, 1);
+static int CheckFileName(lua_State *L, const char *filename)
+{
+	int length = strlen(filename);
 	boolean pass = false;
 	size_t i;
-	int length = strlen(filename);
-	const char *mode = luaL_optstring(L, 2, "r");
-	luafiletransfer_t *filetransfer;
 
 	if (strchr(filename, '\\'))
 	{
@@ -202,67 +207,60 @@ static int io_open (lua_State *L) {
 		return pushresult(L,0,filename);
 	}
 
-	luaL_checktype(L, 4, LUA_TFUNCTION);
+	return 0;
+}
 
-	if (lua_isnil(L, 3) && (strchr(mode, 'r') || strchr(mode, '+'))) // Synched reading
-	{
-		AddLuaFileTransfer(filename, mode);
+static int io_open (lua_State *L) {
+	const char *filename = luaL_checkstring(L, 1);
+	const char *mode = luaL_optstring(L, 2, "r");
+	int checkresult;
 
-		/*pf = newfile(L);
-		*pf = fopen(realfilename, mode);
-		return (*pf == NULL) ? pushresult(L, 0, filename) : 1;*/
-	}
-	else // Local I/O
-	{
-		char *realfilename = va("%s" PATHSEP "%s", luafiledir, filename);
-		player_t *player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
+	checkresult = CheckFileName(L, filename);
+	if (checkresult)
+		return checkresult;
 
-		if (!player)
-			return LUA_ErrInvalid(L, "player_t");
+	luaL_checktype(L, 3, LUA_TFUNCTION);
 
-		if (player != &players[consoleplayer])
-			return 0;
+	if (!(strchr(mode, 'r') || strchr(mode, '+')))
+		luaL_error(L, "open() is only for reading, use openlocal() for writing");
 
-		if (client && strnicmp(filename, "shared/", strlen("shared/")))
+	AddLuaFileTransfer(filename, mode);
+
+	return 0;
+}
+
+
+static int io_openlocal (lua_State *L) {
+	FILE **pf;
+	const char *filename = luaL_checkstring(L, 1);
+	const char *mode = luaL_optstring(L, 2, "r");
+	luafiletransfer_t *filetransfer;
+	int checkresult;
+
+	checkresult = CheckFileName(L, filename);
+	if (checkresult)
+		return checkresult;
+
+	char *realfilename = va("%s" PATHSEP "%s", luafiledir, filename);
+
+	if (client && strnicmp(filename, "shared/", strlen("shared/")))
+		I_Error("Access denied to %s\n"
+		        "Clients can only access files stored in luafiles/shared/\n",
+		        filename);
+
+	// Prevent access if the file is being downloaded
+	for (filetransfer = luafiletransfers; filetransfer; filetransfer = filetransfer->next)
+		if (!stricmp(filetransfer->filename, filename))
 			I_Error("Access denied to %s\n"
-					"Clients can only access files stored in luafiles/shared/\n",
-					filename);
+			        "Files can't be opened while being downloaded\n",
+			        filename);
 
-		// Prevent access if the file is being downloaded
-		for (filetransfer = luafiletransfers; filetransfer; filetransfer = filetransfer->next)
-			if (!stricmp(filetransfer->filename, filename))
-				I_Error("Access denied to %s\n"
-						"Files can't be opened while being downloaded\n",
-						filename);
+	MakePathDirs(realfilename);
 
-		MakePathDirs(realfilename);
-
-		// The callback is the last argument, no need to push it again
-
-		// Push the first argument (file handle) on the stack
-		pf = newfile(gL); // Create and push the file handle
-		*pf = fopen(realfilename, mode); // Open the file
-		if (!*pf)
-		{
-			lua_pop(gL, 1);
-			lua_pushnil(gL);
-		}
-
-		// Push the second argument (file name) on the stack
-		lua_pushstring(gL, filename);
-
-		// Call the callback
-		LUA_Call(gL, 2);
-
-		// Close the file
-		if (*pf)
-		{
-			fclose(*pf);
-			*pf = NULL;
-		}
-	}
-
-	return 0; // !!! Todo: error handling?
+	// Open and return the file
+	pf = newfile(L);
+	*pf = fopen(realfilename, mode);
+	return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
 }
 
 
@@ -335,7 +333,7 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
 void StoreLuaFileCallback(INT32 id)
 {
 	lua_pushfstring(gL, FMT_FILECALLBACKID, id);
-	lua_pushvalue(gL, 4); // Parameter 4 is the callback
+	lua_pushvalue(gL, 3); // Parameter 3 is the callback
 	lua_settable(gL, LUA_REGISTRYINDEX); // registry[callbackid] = callback
 }
 
@@ -347,6 +345,7 @@ void RemoveLuaFileCallback(INT32 id)
 	lua_settable(gL, LUA_REGISTRYINDEX); // registry[callbackid] = nil
 }
 
+
 static int io_tmpfile (lua_State *L) {
   FILE **pf = newfile(L);
   *pf = tmpfile();
@@ -649,10 +648,12 @@ static int f_flush (lua_State *L) {
 
 
 static const luaL_Reg iolib[] = {
+  {"close", io_close},
   {"flush", io_flush},
   {"input", io_input},
   {"lines", io_lines},
   {"open", io_open},
+  {"openlocal", io_openlocal},
   {"output", io_output},
   {"read", io_read},
   {"tmpfile", io_tmpfile},
@@ -663,6 +664,7 @@ static const luaL_Reg iolib[] = {
 
 
 static const luaL_Reg flib[] = {
+  {"close", io_close},
   {"flush", f_flush},
   {"lines", f_lines},
   {"read", f_read},

From 295f052f2decc703acd60d2b6f4c648bc0e40579 Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Fri, 24 Jan 2020 01:03:38 -0300
Subject: [PATCH 010/251] I don't know how these even come up

---
 src/p_user.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_user.c b/src/p_user.c
index 45f4a4562..288f0dbb5 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -12916,7 +12916,7 @@ void P_PlayerAfterThink(player_t *player)
 		player->mo->flags2 |= MF2_DONTDRAW;
 		player->mo->flags |= MF_NOGRAVITY;
 	}
-	
+
 	if (player->powers[pw_dye])
 	{
 		player->mo->colorized = true;

From e0f0984fcc8e5d1f4e6881b1826662f24ff1b4e9 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Fri, 24 Jan 2020 17:11:00 +0100
Subject: [PATCH 011/251] Rename "luafiles/shared/" to "luafiles/client/"

---
 src/blua/liolib.c | 4 ++--
 src/d_netfil.c    | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/blua/liolib.c b/src/blua/liolib.c
index dc425f3c0..244c13d15 100644
--- a/src/blua/liolib.c
+++ b/src/blua/liolib.c
@@ -243,9 +243,9 @@ static int io_openlocal (lua_State *L) {
 
 	char *realfilename = va("%s" PATHSEP "%s", luafiledir, filename);
 
-	if (client && strnicmp(filename, "shared/", strlen("shared/")))
+	if (client && strnicmp(filename, "client/", strlen("client/")))
 		I_Error("Access denied to %s\n"
-		        "Clients can only access files stored in luafiles/shared/\n",
+		        "Clients can only access files stored in luafiles/client/\n",
 		        filename);
 
 	// Prevent access if the file is being downloaded
diff --git a/src/d_netfil.c b/src/d_netfil.c
index 5ceec2aaa..71449caca 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -489,7 +489,7 @@ void AddLuaFileTransfer(const char *filename, const char *mode)
 		filetransfer->realfilename = strdup(va("%s" PATHSEP "%s",
 												luafiledir, filename));
 	else
-		filetransfer->realfilename = strdup(va("%s" PATHSEP "shared" PATHSEP "$$$%d%d.tmp",
+		filetransfer->realfilename = strdup(va("%s" PATHSEP "client" PATHSEP "$$$%d%d.tmp",
 												luafiledir, rand(), rand()));
     if (!filetransfer->realfilename)
 		I_Error("AddLuaFileTransfer: Out of memory\n");

From 9658ef2c5bf4becdb8ab9473686d1726683510a1 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Fri, 24 Jan 2020 17:51:20 +0100
Subject: [PATCH 012/251] Add .dat and .csv to whitelisted file extensions

---
 src/blua/liolib.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/blua/liolib.c b/src/blua/liolib.c
index 244c13d15..4ef3b4274 100644
--- a/src/blua/liolib.c
+++ b/src/blua/liolib.c
@@ -36,11 +36,13 @@
 
 static const char *const fnames[] = {"input", "output"};
 static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder
-	".txt",
-	".sav2",
+	".bmp",
 	".cfg",
+	".csv",
+	".dat",
 	".png",
-	".bmp"
+	".sav2",
+	".txt",
 };
 
 

From 51947319ee7ab0bed90128c41acf03e056468dd2 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Fri, 24 Jan 2020 23:24:54 +0100
Subject: [PATCH 013/251] Fix two compiler warnings

---
 src/blua/liolib.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/blua/liolib.c b/src/blua/liolib.c
index 4ef3b4274..489a4ae16 100644
--- a/src/blua/liolib.c
+++ b/src/blua/liolib.c
@@ -268,8 +268,8 @@ static int io_openlocal (lua_State *L) {
 
 void Got_LuaFile(UINT8 **cp, INT32 playernum)
 {
-	FILE **pf;
-	boolean success = READUINT8(*cp); // The first (and only) byte indicates whether the file could be opened
+	FILE **pf = NULL;
+	UINT8 success = READUINT8(*cp); // The first (and only) byte indicates whether the file could be opened
 
 	if (playernum != serverplayer)
 	{

From 16c7981bb8dc4af071e4dbbf8ad0bc4867ce31bf Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Fri, 24 Jan 2020 23:34:39 +0100
Subject: [PATCH 014/251] Fix the compiler warning fix

---
 src/blua/liolib.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/blua/liolib.c b/src/blua/liolib.c
index 489a4ae16..74bedc060 100644
--- a/src/blua/liolib.c
+++ b/src/blua/liolib.c
@@ -325,7 +325,7 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum)
 		else
 		{
 			// Send a net command with 0 as its first byte to indicate the file couldn't be opened
-			UINT8 success = 0;
+			success = 0;
 			SendNetXCmd(XD_LUAFILE, &success, 1);
 		}
 	}

From 2d142f734faadd67b07e9527dfabcdf80e7a85f3 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Sat, 25 Jan 2020 01:37:50 +0100
Subject: [PATCH 015/251] Remove all potentially dangerous functions

Basically any function that calls fopen() is gone,
except the ones created by me.

And no access to stdin/stdout/stderr
through io.read()/io.write().
Not really harmful but why would you want that in SRB2.
---
 src/blua/liolib.c | 87 -----------------------------------------------
 1 file changed, 87 deletions(-)

diff --git a/src/blua/liolib.c b/src/blua/liolib.c
index 74bedc060..e1a64c8d8 100644
--- a/src/blua/liolib.c
+++ b/src/blua/liolib.c
@@ -64,12 +64,6 @@ static int pushresult (lua_State *L, int i, const char *filename) {
 }
 
 
-static void fileerror (lua_State *L, int arg, const char *filename) {
-  lua_pushfstring(L, "%s: %s", filename, strerror(errno));
-  luaL_argerror(L, arg, lua_tostring(L, -1));
-}
-
-
 #define tofilep(L)	((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
 
 
@@ -355,47 +349,6 @@ static int io_tmpfile (lua_State *L) {
 }
 
 
-static FILE *getiofile (lua_State *L, int findex) {
-  FILE *f;
-  lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
-  f = *(FILE **)lua_touserdata(L, -1);
-  if (f == NULL)
-    luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
-  return f;
-}
-
-
-static int g_iofile (lua_State *L, int f, const char *mode) {
-  if (!lua_isnoneornil(L, 1)) {
-    const char *filename = lua_tostring(L, 1);
-    if (filename) {
-      FILE **pf = newfile(L);
-      *pf = fopen(filename, mode);
-      if (*pf == NULL)
-        fileerror(L, 1, filename);
-    }
-    else {
-      tofile(L);  /* check that it's a valid file handle */
-      lua_pushvalue(L, 1);
-    }
-    lua_rawseti(L, LUA_ENVIRONINDEX, f);
-  }
-  /* return current value */
-  lua_rawgeti(L, LUA_ENVIRONINDEX, f);
-  return 1;
-}
-
-
-static int io_input (lua_State *L) {
-  return g_iofile(L, IO_INPUT, "r");
-}
-
-
-static int io_output (lua_State *L) {
-  return g_iofile(L, IO_OUTPUT, "w");
-}
-
-
 static int io_readline (lua_State *L);
 
 
@@ -413,24 +366,6 @@ static int f_lines (lua_State *L) {
 }
 
 
-static int io_lines (lua_State *L) {
-  if (lua_isnoneornil(L, 1)) {  /* no arguments? */
-    /* will iterate over default input */
-    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
-    return f_lines(L);
-  }
-  else {
-    const char *filename = luaL_checkstring(L, 1);
-    FILE **pf = newfile(L);
-    *pf = fopen(filename, "r");
-    if (*pf == NULL)
-      fileerror(L, 1, filename);
-    aux_lines(L, lua_gettop(L), 1);
-    return 1;
-  }
-}
-
-
 /*
 ** {======================================================
 ** READ
@@ -543,11 +478,6 @@ static int g_read (lua_State *L, FILE *f, int first) {
 }
 
 
-static int io_read (lua_State *L) {
-  return g_read(L, getiofile(L, IO_INPUT), 1);
-}
-
-
 static int f_read (lua_State *L) {
   return g_read(L, tofile(L), 2);
 }
@@ -601,11 +531,6 @@ static int g_write (lua_State *L, FILE *f, int arg) {
 }
 
 
-static int io_write (lua_State *L) {
-  return g_write(L, getiofile(L, IO_OUTPUT), 1);
-}
-
-
 static int f_write (lua_State *L) {
   return g_write(L, tofile(L), 2);
 }
@@ -638,12 +563,6 @@ static int f_setvbuf (lua_State *L) {
 }
 
 
-
-static int io_flush (lua_State *L) {
-  return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
-}
-
-
 static int f_flush (lua_State *L) {
   return pushresult(L, fflush(tofile(L)) == 0, NULL);
 }
@@ -651,16 +570,10 @@ static int f_flush (lua_State *L) {
 
 static const luaL_Reg iolib[] = {
   {"close", io_close},
-  {"flush", io_flush},
-  {"input", io_input},
-  {"lines", io_lines},
   {"open", io_open},
   {"openlocal", io_openlocal},
-  {"output", io_output},
-  {"read", io_read},
   {"tmpfile", io_tmpfile},
   {"type", io_type},
-  {"write", io_write},
   {NULL, NULL}
 };
 

From 0218f58f489e7ca00f1c8a6747f3837a1df95171 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Sun, 2 Feb 2020 15:08:22 -0800
Subject: [PATCH 016/251] userdataType can check light userdata too!

---
 src/lua_baselib.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 66bd30e32..7c53fa99a 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -220,10 +220,16 @@ static const char *GetUserdataUType(lua_State *L)
 //   or players[0].powers -> "player_t.powers"
 static int lib_userdataType(lua_State *L)
 {
+	int type;
 	lua_settop(L, 1); // pop everything except arg 1 (in case somebody decided to add more)
-	luaL_checktype(L, 1, LUA_TUSERDATA);
-	lua_pushstring(L, GetUserdataUType(L));
-	return 1;
+	type = lua_type(L, 1);
+	if (type == LUA_TLIGHTUSERDATA || type == LUA_TUSERDATA)
+	{
+		lua_pushstring(L, GetUserdataUType(L));
+		return 1;
+	}
+	else
+		return luaL_typerror(L, 1, "userdata");
 }
 
 static int lib_isPlayerAdmin(lua_State *L)

From deaf5cfa2895c21e50b10f7b0b3e4831729c4759 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Sun, 2 Feb 2020 15:19:19 -0800
Subject: [PATCH 017/251] LUA_PushLightUserdata takes the fun out of
 lib_cvFindVar

---
 src/lua_consolelib.c | 18 ++----------------
 src/lua_script.c     | 22 ++++++++++++++++++++++
 src/lua_script.h     |  1 +
 3 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c
index 48f2e20a8..62d59e582 100644
--- a/src/lua_consolelib.c
+++ b/src/lua_consolelib.c
@@ -431,22 +431,8 @@ static int lib_cvRegisterVar(lua_State *L)
 
 static int lib_cvFindVar(lua_State *L)
 {
-	consvar_t *cv;
-	if (( cv = CV_FindVar(luaL_checkstring(L,1)) ))
-	{
-		lua_settop(L,1);/* We only want one argument in the stack. */
-		lua_pushlightuserdata(L, cv);/* Now the second value on stack. */
-		luaL_getmetatable(L, META_CVAR);
-		/*
-		The metatable is the last value on the stack, so this
-		applies it to the second value, which is the cvar.
-		*/
-		lua_setmetatable(L,2);
-		lua_pushvalue(L,2);
-		return 1;
-	}
-	else
-		return 0;
+	LUA_PushLightUserdata(L, CV_FindVar(luaL_checkstring(L,1)), META_CVAR);
+	return 1;
 }
 
 // CONS_Printf for a single player
diff --git a/src/lua_script.c b/src/lua_script.c
index 2538fb711..9d0a80f90 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -568,6 +568,28 @@ fixed_t LUA_EvalMath(const char *word)
 	return res;
 }
 
+/*
+LUA_PushUserdata but no userdata is created.
+You can't invalidate it therefore.
+*/
+
+void LUA_PushLightUserdata (lua_State *L, void *data, const char *meta)
+{
+	if (data)
+	{
+		lua_pushlightuserdata(L, data);
+		luaL_getmetatable(L, meta);
+		/*
+		The metatable is the last value on the stack, so this
+		applies it to the second value, which is the userdata.
+		*/
+		lua_setmetatable(L, -2);
+		lua_pushvalue(L, -1);
+	}
+	else
+		lua_pushnil(L);
+}
+
 // Takes a pointer, any pointer, and a metatable name
 // Creates a userdata for that pointer with the given metatable
 // Pushes it to the stack and stores it in the registry.
diff --git a/src/lua_script.h b/src/lua_script.h
index 8f27dcb4c..d54387175 100644
--- a/src/lua_script.h
+++ b/src/lua_script.h
@@ -46,6 +46,7 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump);
 void LUA_DumpFile(const char *filename);
 #endif
 fixed_t LUA_EvalMath(const char *word);
+void LUA_PushLightUserdata(lua_State *L, void *data, const char *meta);
 void LUA_PushUserdata(lua_State *L, void *data, const char *meta);
 void LUA_InvalidateUserdata(void *data);
 void LUA_InvalidateLevel(void);

From 35f1a4b76c600526a53f4a154bda6cfaca65340b Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Sun, 2 Feb 2020 17:22:28 -0800
Subject: [PATCH 018/251] lua_pushvalue is unneeded

---
 src/lua_script.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/lua_script.c b/src/lua_script.c
index 9d0a80f90..02f78cd35 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -584,7 +584,6 @@ void LUA_PushLightUserdata (lua_State *L, void *data, const char *meta)
 		applies it to the second value, which is the userdata.
 		*/
 		lua_setmetatable(L, -2);
-		lua_pushvalue(L, -1);
 	}
 	else
 		lua_pushnil(L);

From 2eaf02d234ab0287af9fbd41b50ca2015121cca7 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Mon, 3 Feb 2020 19:42:37 +0100
Subject: [PATCH 019/251] Let Lua access spectators mobjs

---
 src/lua_playerlib.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index 1dd4c45b5..9ce1fed9b 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -97,6 +97,10 @@ static int player_get(lua_State *L)
 		lua_pushboolean(L, true);
 	else if (fastcmp(field,"name"))
 		lua_pushstring(L, player_names[plr-players]);
+	else if (fastcmp(field,"realmo"))
+		LUA_PushUserdata(L, plr->mo, META_MOBJ);
+	// Kept for backward-compatibility
+	// Should be fixed to work like "realmo" later
 	else if (fastcmp(field,"mo"))
 	{
 		if (plr->spectator)
@@ -396,7 +400,7 @@ static int player_set(lua_State *L)
 	if (hud_running)
 		return luaL_error(L, "Do not alter player_t in HUD rendering code!");
 
-	if (fastcmp(field,"mo")) {
+	if (fastcmp(field,"mo") || fastcmp(field,"realmo")) {
 		mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
 		plr->mo->player = NULL; // remove player pointer from old mobj
 		(newmo->player = plr)->mo = newmo; // set player pointer for new mobj, and set new mobj as the player's mobj

From 57a4545fdff6710782497601cd2223b4d3026afc Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Fri, 7 Feb 2020 00:01:20 -0600
Subject: [PATCH 020/251] PK3: Proper ignorance for file comments/extra data

---
 src/w_wad.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/w_wad.c b/src/w_wad.c
index 1df2eacc7..00bdb7183 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -580,7 +580,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 			return NULL;
 		}
 
-		lump_p->position = zentry->offset + zentry->namelen + zentry->xtralen + sizeof(zlentry_t);
+		lump_p->position = zentry->offset + zentry->namelen + sizeof(zlentry_t);
 		lump_p->disksize = zentry->compsize;
 		lump_p->size = zentry->size;
 
@@ -629,6 +629,15 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 			lump_p->compression = CM_UNSUPPORTED;
 			break;
 		}
+
+		// skip and ignore comments/extra fields
+		if (fseek(handle, zentry->xtralen + zentry->commlen, SEEK_CUR) != 0)
+		{
+			CONS_Alert(CONS_ERROR, "Central directory %d is corrupt (%02x%02x%02x%02x)\n", i, zentry->signature[0], zentry->signature[1], zentry->signature[2], zentry->signature[3]);
+			Z_Free(lumpinfo);
+			free(zentries);
+			return NULL;
+		}
 	}
 
 	free(zentries);

From 8cb9d6f670c1982171f41d0a4ec715a6cd918c0c Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Fri, 7 Feb 2020 00:04:02 -0600
Subject: [PATCH 021/251] Uhhh do VerifyPk3 too

---
 src/w_wad.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/w_wad.c b/src/w_wad.c
index 00bdb7183..9f36e5d2a 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -1819,6 +1819,10 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status)
 		}
 
 		free(fullname);
+
+		// skip and ignore comments/extra fields
+		if (fseek(fp, zentry->xtralen + zentry->commlen, SEEK_CUR) != 0)
+			return true;
 	}
 
 	return true;

From c4ee113c710b6859cf837e9c0e8f1d7d694ed746 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Fri, 7 Feb 2020 00:53:56 -0800
Subject: [PATCH 022/251] Let MUSICDEF set loop point

---
 src/s_sound.c | 15 +++++++++++++++
 src/s_sound.h |  1 +
 2 files changed, 16 insertions(+)

diff --git a/src/s_sound.c b/src/s_sound.c
index d84e20ab4..0854d9b67 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -1456,6 +1456,7 @@ musicdef_t soundtestsfx = {
 	0, // with no conditions
 	0,
 	0,
+	0,
 	false,
 	NULL
 };
@@ -1651,6 +1652,8 @@ ReadMusicDefFields (UINT16 wadnum, int line, boolean fields, char *stoken,
 				fixed_t bpmf = FLOAT_TO_FIXED(bpm);
 				if (bpmf > 0)
 					def->bpm = FixedDiv((60*TICRATE)<<FRACBITS, bpmf);
+			} else if (!stricmp(stoken, "loopms")) {
+				def->loop_ms = atoi(textline);
 			} else {
 				CONS_Alert(CONS_WARNING,
 						"MUSICDEF: Invalid field '%s'. (file %s, line %d)\n",
@@ -2262,6 +2265,8 @@ static void S_UnloadMusic(void)
 
 static boolean S_PlayMusic(boolean looping, UINT32 fadeinms)
 {
+	musicdef_t *def;
+
 	if (S_MusicDisabled())
 		return false;
 
@@ -2273,6 +2278,16 @@ static boolean S_PlayMusic(boolean looping, UINT32 fadeinms)
 		return false;
 	}
 
+	/* set loop point from MUSICDEF */
+	for (def = musicdefstart; def; def = def->next)
+	{
+		if (strcasecmp(def->name, music_name) == 0)
+		{
+			S_SetMusicLoopPoint(def->loop_ms);
+			break;
+		}
+	}
+
 	S_InitMusicVolume(); // switch between digi and sequence volume
 
 	if (S_MusicNotInFocus())
diff --git a/src/s_sound.h b/src/s_sound.h
index 9a4cbe48b..c7ec7e5d1 100644
--- a/src/s_sound.h
+++ b/src/s_sound.h
@@ -208,6 +208,7 @@ typedef struct musicdef_s
 	INT16 soundtestcond; // +ve for map, -ve for conditionset, 0 for already here
 	tic_t stoppingtics;
 	fixed_t bpm;
+	UINT32 loop_ms;/* override LOOPPOINT/LOOPMS */
 	boolean allowed; // question marks or listenable on sound test?
 	struct musicdef_s *next;
 } musicdef_t;

From 3d00596c6a53c3e20cee7a8ebfd4a7057987003b Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Fri, 7 Feb 2020 12:51:21 -0800
Subject: [PATCH 023/251] Don't override loop point if unset in MUSICDEF

---
 src/s_sound.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/s_sound.c b/src/s_sound.c
index 0854d9b67..4a335bbe6 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -2283,7 +2283,8 @@ static boolean S_PlayMusic(boolean looping, UINT32 fadeinms)
 	{
 		if (strcasecmp(def->name, music_name) == 0)
 		{
-			S_SetMusicLoopPoint(def->loop_ms);
+			if (def->loop_ms)
+				S_SetMusicLoopPoint(def->loop_ms);
 			break;
 		}
 	}

From f7cf8e50f86824084307a71a6d3f146707e921ae Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Fri, 7 Feb 2020 18:43:20 -0600
Subject: [PATCH 024/251] Oops

---
 src/w_wad.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/w_wad.c b/src/w_wad.c
index 9f36e5d2a..3e8502b5e 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -633,7 +633,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 		// skip and ignore comments/extra fields
 		if (fseek(handle, zentry->xtralen + zentry->commlen, SEEK_CUR) != 0)
 		{
-			CONS_Alert(CONS_ERROR, "Central directory %d is corrupt (%02x%02x%02x%02x)\n", i, zentry->signature[0], zentry->signature[1], zentry->signature[2], zentry->signature[3]);
+			CONS_Alert(CONS_ERROR, "Central directory is corrupt\n");
 			Z_Free(lumpinfo);
 			free(zentries);
 			return NULL;
@@ -1821,7 +1821,7 @@ W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status)
 		free(fullname);
 
 		// skip and ignore comments/extra fields
-		if (fseek(fp, zentry->xtralen + zentry->commlen, SEEK_CUR) != 0)
+		if (fseek(fp, zentry.xtralen + zentry.commlen, SEEK_CUR) != 0)
 			return true;
 	}
 

From ee9aa86ecd8ffdbcd7913193a02365e5a536df84 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Fri, 7 Feb 2020 18:46:46 -0600
Subject: [PATCH 025/251] Use the proper numbers to adjust lump's offset
 position

---
 src/w_wad.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/w_wad.c b/src/w_wad.c
index 3e8502b5e..874b99cc7 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -529,6 +529,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
     zend_t zend;
     zentry_t* zentries;
     zentry_t* zentry;
+    zlentry_t zlentry;
 
 	UINT16 numlumps = *nlmp;
 	lumpinfo_t* lumpinfo;
@@ -580,7 +581,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 			return NULL;
 		}
 
-		lump_p->position = zentry->offset + zentry->namelen + sizeof(zlentry_t);
+		lump_p->position = zentry->offset; // NOT ACCURATE YET: we still need to read the local entry to find our true position
 		lump_p->disksize = zentry->compsize;
 		lump_p->size = zentry->size;
 
@@ -642,6 +643,20 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 
 	free(zentries);
 
+	// Adjust lump position values properly
+	for (i = 0, lump_p = lumpinfo; i < numlumps; i++, lump_p++)
+	{
+		// skip and ignore comments/extra fields
+		if ((fseek(handle, lump_p->position, SEEK_SET) != 0) || (fread(&zlentry, 1, sizeof(zlentry_t), handle) < sizeof(zlentry_t)))
+		{
+			CONS_Alert(CONS_ERROR, "Local headers for lump %s are corrupt\n", lump_p->name2);
+			Z_Free(lumpinfo);
+			return NULL;
+		}
+
+		lump_p->position += sizeof(zlentry_t) + zlentry.namelen + zlentry.xtralen;
+	}
+
 	*nlmp = numlumps;
 	return lumpinfo;
 }

From fb7c4ab812a26ec3b1007cd5adbd9c300061cf38 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Fri, 7 Feb 2020 18:47:56 -0600
Subject: [PATCH 026/251] zentries is unnecessary

---
 src/w_wad.c | 34 +++++++++++++---------------------
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/src/w_wad.c b/src/w_wad.c
index 874b99cc7..9137c477f 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -527,8 +527,7 @@ typedef struct zlentry_s
 static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 {
     zend_t zend;
-    zentry_t* zentries;
-    zentry_t* zentry;
+    zentry_t zentry;
     zlentry_t zlentry;
 
 	UINT16 numlumps = *nlmp;
@@ -557,40 +556,36 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 	numlumps = zend.entries;
 
 	lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL);
-	zentry = zentries = malloc(numlumps * sizeof (*zentries));
 
 	fseek(handle, zend.cdiroffset, SEEK_SET);
-	for (i = 0; i < numlumps; i++, zentry++, lump_p++)
+	for (i = 0; i < numlumps; i++, lump_p++)
 	{
 		char* fullname;
 		char* trimname;
 		char* dotpos;
 
-		if (fread(zentry, 1, sizeof(zentry_t), handle) < sizeof(zentry_t))
+		if (fread(&zentry, 1, sizeof(zentry_t), handle) < sizeof(zentry_t))
 		{
 			CONS_Alert(CONS_ERROR, "Failed to read central directory (%s)\n", M_FileError(handle));
 			Z_Free(lumpinfo);
-			free(zentries);
 			return NULL;
 		}
-		if (memcmp(zentry->signature, pat_central, 4))
+		if (memcmp(zentry.signature, pat_central, 4))
 		{
 			CONS_Alert(CONS_ERROR, "Central directory is corrupt\n");
 			Z_Free(lumpinfo);
-			free(zentries);
 			return NULL;
 		}
 
-		lump_p->position = zentry->offset; // NOT ACCURATE YET: we still need to read the local entry to find our true position
-		lump_p->disksize = zentry->compsize;
-		lump_p->size = zentry->size;
+		lump_p->position = zentry.offset; // NOT ACCURATE YET: we still need to read the local entry to find our true position
+		lump_p->disksize = zentry.compsize;
+		lump_p->size = zentry.size;
 
-		fullname = malloc(zentry->namelen + 1);
-		if (fgets(fullname, zentry->namelen + 1, handle) != fullname)
+		fullname = malloc(zentry.namelen + 1);
+		if (fgets(fullname, zentry.namelen + 1, handle) != fullname)
 		{
 			CONS_Alert(CONS_ERROR, "Unable to read lumpname (%s)\n", M_FileError(handle));
 			Z_Free(lumpinfo);
-			free(zentries);
 			free(fullname);
 			return NULL;
 		}
@@ -607,12 +602,12 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 		memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
 		strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
 
-		lump_p->name2 = Z_Calloc(zentry->namelen + 1, PU_STATIC, NULL);
-		strncpy(lump_p->name2, fullname, zentry->namelen);
+		lump_p->name2 = Z_Calloc(zentry.namelen + 1, PU_STATIC, NULL);
+		strncpy(lump_p->name2, fullname, zentry.namelen);
 
 		free(fullname);
 
-		switch(zentry->compression)
+		switch(zentry.compression)
 		{
 		case 0:
 			lump_p->compression = CM_NOCOMPRESSION;
@@ -632,17 +627,14 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 		}
 
 		// skip and ignore comments/extra fields
-		if (fseek(handle, zentry->xtralen + zentry->commlen, SEEK_CUR) != 0)
+		if (fseek(handle, zentry.xtralen + zentry.commlen, SEEK_CUR) != 0)
 		{
 			CONS_Alert(CONS_ERROR, "Central directory is corrupt\n");
 			Z_Free(lumpinfo);
-			free(zentries);
 			return NULL;
 		}
 	}
 
-	free(zentries);
-
 	// Adjust lump position values properly
 	for (i = 0, lump_p = lumpinfo; i < numlumps; i++, lump_p++)
 	{

From 0a53f91820d116e23a2af9260074c5ab778308bc Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Fri, 7 Feb 2020 19:41:45 -0800
Subject: [PATCH 027/251] Don't skip the first directory entry of PK3 if it's a
 file

Also puts the marker skipping in the WAD API.
---
 src/r_data.c   | 20 ++++++--------------
 src/r_things.c |  6 ++----
 src/w_wad.c    | 23 +++++++++++++++++++----
 src/w_wad.h    |  3 +++
 4 files changed, 30 insertions(+), 22 deletions(-)

diff --git a/src/r_data.c b/src/r_data.c
index 5608fdbde..e94368288 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -716,14 +716,12 @@ Rloadflats (INT32 i, INT32 w)
 	}
 	else
 	{
-		texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0);
+		texstart = W_CheckNumForMarkerStartPwad("F_START", (UINT16)w, 0);
 		texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart);
 	}
 
 	if (!( texstart == INT16_MAX || texend == INT16_MAX ))
 	{
-		texstart++; // Do not count the first marker
-
 		// Work through each lump between the markers in the WAD.
 		for (j = 0; j < (texend - texstart); j++)
 		{
@@ -836,7 +834,7 @@ Rloadtextures (INT32 i, INT32 w)
 	}
 	else
 	{
-		texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
+		texstart = W_CheckNumForMarkerStartPwad(TX_START, (UINT16)w, 0);
 		texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
 		texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
 		if (texturesLumpPos != INT16_MAX)
@@ -845,8 +843,6 @@ Rloadtextures (INT32 i, INT32 w)
 
 	if (!( texstart == INT16_MAX || texend == INT16_MAX ))
 	{
-		texstart++; // Do not count the first marker
-
 		// Work through each lump between the markers in the WAD.
 		for (j = 0; j < (texend - texstart); j++)
 		{
@@ -953,14 +949,12 @@ void R_LoadTextures(void)
 		}
 		else
 		{
-			texstart = W_CheckNumForNamePwad("F_START", (UINT16)w, 0);
+			texstart = W_CheckNumForMarkerStartPwad("F_START", (UINT16)w, 0);
 			texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart);
 		}
 
 		if (!( texstart == INT16_MAX || texend == INT16_MAX ))
 		{
-			texstart++; // Do not count the first marker
-
 			// PK3s have subfolders, so we can't just make a simple sum
 			if (wadfiles[w]->type == RET_PK3)
 			{
@@ -993,15 +987,13 @@ void R_LoadTextures(void)
 		}
 		else
 		{
-			texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
+			texstart = W_CheckNumForMarkerStartPwad(TX_START, (UINT16)w, 0);
 			texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
 		}
 
 		if (texstart == INT16_MAX || texend == INT16_MAX)
 			continue;
 
-		texstart++; // Do not count the first marker
-
 		// PK3s have subfolders, so we can't just make a simple sum
 		if (wadfiles[w]->type == RET_PK3)
 		{
@@ -1587,9 +1579,9 @@ lumpnum_t R_GetFlatNumForName(const char *name)
 		switch (wadfiles[i]->type)
 		{
 		case RET_WAD:
-			if ((start = W_CheckNumForNamePwad("F_START", (UINT16)i, 0)) == INT16_MAX)
+			if ((start = W_CheckNumForMarkerStartPwad("F_START", (UINT16)i, 0)) == INT16_MAX)
 			{
-				if ((start = W_CheckNumForNamePwad("FF_START", (UINT16)i, 0)) == INT16_MAX)
+				if ((start = W_CheckNumForMarkerStartPwad("FF_START", (UINT16)i, 0)) == INT16_MAX)
 					continue;
 				else if ((end = W_CheckNumForNamePwad("FF_END", (UINT16)i, start)) == INT16_MAX)
 					continue;
diff --git a/src/r_things.c b/src/r_things.c
index 7f0f43281..75210d4ab 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -437,9 +437,9 @@ void R_AddSpriteDefs(UINT16 wadnum)
 	switch (wadfiles[wadnum]->type)
 	{
 	case RET_WAD:
-		start = W_CheckNumForNamePwad("S_START", wadnum, 0);
+		start = W_CheckNumForMarkerStartPwad("S_START", wadnum, 0);
 		if (start == INT16_MAX)
-			start = W_CheckNumForNamePwad("SS_START", wadnum, 0); //deutex compatib.
+			start = W_CheckNumForMarkerStartPwad("SS_START", wadnum, 0); //deutex compatib.
 
 		end = W_CheckNumForNamePwad("S_END",wadnum,start);
 		if (end == INT16_MAX)
@@ -461,8 +461,6 @@ void R_AddSpriteDefs(UINT16 wadnum)
 
 		start = 0; //let say S_START is lump 0
 	}
-	else
-		start++;   // just after S_START
 
 	if (end == INT16_MAX || start >= end)
 	{
diff --git a/src/w_wad.c b/src/w_wad.c
index 1df2eacc7..ea8a444b0 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -194,7 +194,6 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum, boolean mainfile)
 	if (posStart != INT16_MAX)
 	{
 		posEnd = W_CheckNumForFolderEndPK3("Lua/", wadnum, posStart);
-		posStart++; // first "lump" will be "Lua/" folder itself, so ignore it
 		for (; posStart < posEnd; posStart++)
 			LUA_LoadLump(wadnum, posStart);
 	}
@@ -204,7 +203,6 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum, boolean mainfile)
 	{
 		posEnd = W_CheckNumForFolderEndPK3("SOC/", wadnum, posStart);
 
-		posStart++; // first "lump" will be "SOC/" folder itself, so ignore it
 		for(; posStart < posEnd; posStart++)
 		{
 			lumpinfo_t *lump_p = &wadfiles[wadnum]->lumpinfo[posStart];
@@ -912,15 +910,32 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
 	return INT16_MAX;
 }
 
+UINT16
+W_CheckNumForMarkerStartPwad (const char *name, UINT16 wad, UINT16 startlump)
+{
+	UINT16 marker;
+	marker = W_CheckNumForNamePwad(name, wad, startlump);
+	if (marker != INT16_MAX)
+		marker++; // Do not count the first marker
+	return marker;
+}
+
 // Look for the first lump from a folder.
 UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump)
 {
+	size_t name_length;
 	INT32 i;
 	lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
+	name_length = strlen(name);
 	for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
 	{
-		if (strnicmp(name, lump_p->name2, strlen(name)) == 0)
+		if (strnicmp(name, lump_p->name2, name_length) == 0)
+		{
+			/* SLADE is special and puts a single directory entry. Skip that. */
+			if (strlen(lump_p->name2) == name_length)
+				i++;
 			break;
+		}
 	}
 	return i;
 }
@@ -1023,7 +1038,7 @@ lumpnum_t W_CheckNumForMap(const char *name)
 			else
 				continue;
 			// Now look for the specified map.
-			for (++lumpNum; lumpNum < end; lumpNum++)
+			for (; lumpNum < end; lumpNum++)
 				if (!strnicmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
 					return (i<<16) + lumpNum;
 		}
diff --git a/src/w_wad.h b/src/w_wad.h
index aca67c00f..e07ceaf2e 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -157,6 +157,9 @@ const char *W_CheckNameForNum(lumpnum_t lumpnum);
 
 UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump); // checks only in one pwad
 
+/* Find the first lump after F_START for instance. */
+UINT16 W_CheckNumForMarkerStartPwad(const char *name, UINT16 wad, UINT16 startlump);
+
 UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump);
 UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump);
 UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump);

From 934808ef6202ffb4eec2f3753fc98cd22c630bec Mon Sep 17 00:00:00 2001
From: Sally Cochenour <tehrealsalt@gmail.com>
Date: Wed, 12 Feb 2020 14:16:23 -0500
Subject: [PATCH 028/251] BotRespawn hook

Lets you force when and when not to respawn the bot
---
 src/b_bot.c       | 15 +++++++++++++++
 src/lua_hook.h    |  2 ++
 src/lua_hooklib.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 63 insertions(+)

diff --git a/src/b_bot.c b/src/b_bot.c
index f83aaa34c..3e8275bdd 100644
--- a/src/b_bot.c
+++ b/src/b_bot.c
@@ -463,6 +463,21 @@ boolean B_CheckRespawn(player_t *player)
 	if (!sonic || sonic->health <= 0)
 		return false;
 
+#ifdef HAVE_BLUA
+	// B_RespawnBot doesn't do anything if the condition above this isn't met
+	{
+		UINT8 shouldForce = LUAh_BotRespawn(sonic, tails);
+
+		if (P_MobjWasRemoved(sonic) || P_MobjWasRemoved(tails))
+			return (shouldForce == 1); // mobj was removed
+
+		if (shouldForce == 1)
+			return true;
+		else if (shouldForce == 2)
+			return false;
+	}
+#endif
+
 	// Check if Sonic is busy first.
 	// If he's doing any of these things, he probably doesn't want to see us.
 	if (sonic->player->pflags & (PF_GLIDING|PF_SLIDING|PF_BOUNCING)
diff --git a/src/lua_hook.h b/src/lua_hook.h
index 94d2239f7..4bacf573a 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -42,6 +42,7 @@ enum hook {
 	hook_JumpSpinSpecial,
 	hook_BotTiccmd,
 	hook_BotAI,
+	hook_BotRespawn,
 	hook_LinedefExecute,
 	hook_PlayerMsg,
 	hook_HurtMsg,
@@ -92,6 +93,7 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8
 #define LUAh_JumpSpinSpecial(player) LUAh_PlayerHook(player, hook_JumpSpinSpecial) // Hook for P_DoJumpStuff (Spin button effect (mid-air))
 boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd
 boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name
+boolean LUAh_BotRespawn(mobj_t *sonic, mobj_t *tails); // Hook for B_CheckRespawn
 boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors
 boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages
 boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); // Hook for hurt messages
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 306bf6839..5c6b97ce0 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -53,6 +53,7 @@ const char *const hookNames[hook_MAX+1] = {
 	"JumpSpinSpecial",
 	"BotTiccmd",
 	"BotAI",
+	"BotRespawn",
 	"LinedefExecute",
 	"PlayerMsg",
 	"HurtMsg",
@@ -1122,6 +1123,51 @@ boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
 	return hooked;
 }
 
+// Hook for B_CheckRespawn
+boolean LUAh_BotRespawn(mobj_t *sonic, mobj_t *tails)
+{
+	hook_p hookp;
+	UINT8 shouldRespawn = 0; // 0 = default, 1 = force yes, 2 = force no.
+	if (!gL || !(hooksAvailable[hook_BotRespawn/8] & (1<<(hook_BotRespawn%8))))
+		return false;
+
+	lua_settop(gL, 0);
+
+	for (hookp = roothook; hookp; hookp = hookp->next)
+	{
+		if (hookp->type != hook_BotRespawn)
+			continue;
+
+		if (lua_gettop(gL) == 0)
+		{
+			LUA_PushUserdata(gL, sonic, META_MOBJ);
+			LUA_PushUserdata(gL, tails, META_MOBJ);
+		}
+		lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+		lua_gettable(gL, LUA_REGISTRYINDEX);
+		lua_pushvalue(gL, -3);
+		lua_pushvalue(gL, -3);
+		if (lua_pcall(gL, 2, 1, 0)) {
+			if (!hookp->error || cv_debug & DBG_LUA)
+				CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+			lua_pop(gL, 1);
+			hookp->error = true;
+			continue;
+		}
+		if (!lua_isnil(gL, -1))
+		{
+			if (lua_toboolean(gL, -1))
+				shouldRespawn = 1; // Force yes
+			else
+				shouldRespawn = 2; // Force no
+		}
+		lua_pop(gL, 1);
+	}
+
+	lua_settop(gL, 0);
+	return shouldRespawn;
+}
+
 // Hook for linedef executors
 boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
 {

From 64b7a5e4d6d71e53a10e6cefef4ce04993230882 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Wed, 12 Feb 2020 18:03:39 -0800
Subject: [PATCH 029/251] SF_NONIGHTSSUPER for disabling super colors in NiGHTS

---
 src/d_player.h | 1 +
 src/dehacked.c | 1 +
 src/p_user.c   | 2 +-
 src/r_things.c | 1 +
 4 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/d_player.h b/src/d_player.h
index db55a9913..250410c3b 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -48,6 +48,7 @@ typedef enum
 	SF_FASTEDGE         = 1<<12, // Faster edge teeter?
 	SF_MULTIABILITY     = 1<<13, // Revenge of Final Demo.
 	SF_NONIGHTSROTATION = 1<<14, // Disable sprite rotation for NiGHTS
+	SF_NONIGHTSSUPER    = 1<<15, // Disable super colors for NiGHTS (if you have SF_SUPER)
 	// free up to and including 1<<31
 } skinflags_t;
 
diff --git a/src/dehacked.c b/src/dehacked.c
index e7ff6e400..e48b1cb90 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -9477,6 +9477,7 @@ struct {
 	{"SF_FASTEDGE",SF_FASTEDGE},
 	{"SF_MULTIABILITY",SF_MULTIABILITY},
 	{"SF_NONIGHTSROTATION",SF_NONIGHTSROTATION},
+	{"SF_NONIGHTSSUPER",SF_NONIGHTSSUPER},
 
 	// Dashmode constants
 	{"DASHMODE_THRESHOLD",DASHMODE_THRESHOLD},
diff --git a/src/p_user.c b/src/p_user.c
index 176b07d0a..5b88148d5 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -8040,7 +8040,7 @@ static void P_MovePlayer(player_t *player)
 			&& player->mo->state < &states[S_PLAY_NIGHTS_TRANS6]))) // Note the < instead of <=
 		{
 			skin_t *skin = ((skin_t *)(player->mo->skin));
-			if (skin->flags & SF_SUPER)
+			if (( skin->flags & (SF_SUPER|SF_NONIGHTSSUPER) ) == SF_SUPER)
 			{
 				player->mo->color = skin->supercolor
 					+ ((player->nightstime == player->startedtime)
diff --git a/src/r_things.c b/src/r_things.c
index 7f0f43281..ae4ccb5a8 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -3463,6 +3463,7 @@ static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
 	GETFLAG(DASHMODE)
 	GETFLAG(FASTEDGE)
 	GETFLAG(MULTIABILITY)
+	GETFLAG(NONIGHTSSUPER)
 #undef GETFLAG
 
 	else // let's check if it's a sound, otherwise error out

From 71319dce6b5cd1706c693942877149249e75b494 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Wed, 12 Feb 2020 18:15:15 -0800
Subject: [PATCH 030/251] Revert "Update file hashes"

This reverts commit 4281de3b89e4ace77bff9dca003feb26d9e4dbc5.
---
 src/config.h.in | 8 ++++----
 src/d_main.c    | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/config.h.in b/src/config.h.in
index d4a613fdc..233cbdc53 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -26,12 +26,12 @@
 #else
 
 /* Manually defined asset hashes for non-CMake builds
- * Last updated 2020 / 02 / 09 - v2.2.1 - main assets
+ * Last updated 2019 / 12 / 06 - v2.2.0 - main assets
  * Last updated 20?? / ?? / ?? - v2.2.? - patch.pk3
  */
-#define ASSET_HASH_SRB2_PK3   "0277c9416756627004e83cbb5b2e3e28"
-#define ASSET_HASH_ZONES_PK3  "89627822f5a5c7fb022d836b138144b2"
-#define ASSET_HASH_PLAYER_DTA "129fa7d4b273a4b3dcacaa44eccead4f"
+#define ASSET_HASH_SRB2_PK3   "51419a33b4982d840c6772c159ba7c0a"
+#define ASSET_HASH_ZONES_PK3  "df74843919fd51af26a0baa8e21e4c19"
+#define ASSET_HASH_PLAYER_DTA "56a247e074dd0dc794b6617efef1e918"
 #ifdef USE_PATCH_DTA
 #define ASSET_HASH_PATCH_PK3  "there is no patch.pk3, only zuul"
 #endif
diff --git a/src/d_main.c b/src/d_main.c
index 27f250017..dc9bfbfea 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1213,7 +1213,7 @@ void D_SRB2Main(void)
 #endif
 	D_CleanFile();
 
-#ifndef DEVELOP // md5s last updated 09/02/20 (ddmmyy)
+#ifndef DEVELOP // md5s last updated 06/12/19 (ddmmyy)
 
 	// Check MD5s of autoloaded files
 	W_VerifyFileMD5(0, ASSET_HASH_SRB2_PK3); // srb2.pk3

From b6089ccdaf9746446b229c14cdb34c0c3ad24544 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Mon, 27 Jan 2020 01:57:55 -0300
Subject: [PATCH 031/251] Fix -OGLlib

---
 src/i_video.h     | 13 +++++++++--
 src/screen.c      |  2 +-
 src/sdl/i_video.c | 58 +++++++++++++++++++++++++++++++++++++++--------
 src/sdl/ogl_sdl.c |  8 +++----
 4 files changed, 65 insertions(+), 16 deletions(-)

diff --git a/src/i_video.h b/src/i_video.h
index 76b984d25..8f87a360e 100644
--- a/src/i_video.h
+++ b/src/i_video.h
@@ -32,10 +32,13 @@ typedef enum
 	render_none = 3  // for dedicated server
 } rendermode_t;
 
-/**	\brief currect render mode
+/**	\brief current render mode
 */
 extern rendermode_t rendermode;
 
+/**	\brief hardware renderer loaded
+*/
+extern boolean hwrenderloaded;
 
 /**	\brief use highcolor modes if true
 */
@@ -44,6 +47,9 @@ extern boolean highcolor;
 /**	\brief setup video mode
 */
 void I_StartupGraphics(void);
+
+/**	\brief setup hardware mode
+*/
 void I_StartupHardwareGraphics(void);
 
 /**	\brief restore old video mode
@@ -82,9 +88,12 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h);
 
 	\param	modenum	video mode to set to
 
-	\return	currect video mode
+	\return	current video mode
 */
 INT32 VID_SetMode(INT32 modenum);
+
+/**	\brief Checks the render state
+*/
 void VID_CheckRenderer(void);
 
 /**	\brief	The VID_GetModeName function
diff --git a/src/screen.c b/src/screen.c
index fcf6c6b0b..b5faaef7e 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -464,7 +464,7 @@ void SCR_ChangeRenderer(void)
 	{
 		target_renderer = cv_renderer.value;
 #ifdef HWRENDER
-		if (M_CheckParm("-opengl"))
+		if (M_CheckParm("-opengl") && hwrenderloaded)
 			target_renderer = rendermode = render_opengl;
 		else
 #endif
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 13e2423c4..a37e94fad 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -93,7 +93,8 @@ static INT32 numVidModes = -1;
 */
 static char vidModeName[33][32]; // allow 33 different modes
 
-rendermode_t rendermode=render_soft;
+rendermode_t rendermode = render_soft;
+static rendermode_t chosenrendermode = render_soft; // set by command line arguments
 
 boolean highcolor = false;
 
@@ -103,6 +104,7 @@ static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff
 static consvar_t cv_alwaysgrabmouse = {"alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 
 UINT8 graphics_started = 0; // Is used in console.c and screen.c
+boolean hwrenderloaded = false;
 
 // To disable fullscreen at startup; is set in VID_PrepareModeList
 boolean allow_fullscreen = false;
@@ -1468,14 +1470,44 @@ static SDL_bool Impl_CreateContext(void)
 	return SDL_TRUE;
 }
 
+#ifdef HWRENDER
+static void VID_CheckGLLoaded(rendermode_t oldrender)
+{
+	if (!hwrenderloaded) // Well, it didn't work the first time anyway.
+	{
+		CONS_Alert(CONS_ERROR, "OpenGL never loaded\n");
+		rendermode = oldrender;
+		if (chosenrendermode == render_opengl) // fallback to software
+			rendermode = render_soft;
+		if (setrenderneeded)
+		{
+			CV_StealthSetValue(&cv_renderer, oldrender);
+			CV_StealthSetValue(&cv_newrenderer, oldrender);
+			setrenderneeded = 0;
+		}
+	}
+}
+#endif
+
 void VID_CheckRenderer(void)
 {
+	rendermode_t oldrenderer = rendermode;
+
 	if (dedicated)
 		return;
 
+#ifdef HWRENDER
+	if (!graphics_started)
+		VID_CheckGLLoaded(oldrenderer);
+#endif
+
 	if (setrenderneeded)
 	{
 		rendermode = setrenderneeded;
+#ifdef HWRENDER
+		if (setrenderneeded == render_opengl)
+			VID_CheckGLLoaded(oldrenderer);
+#endif
 		Impl_CreateContext();
 	}
 
@@ -1498,9 +1530,15 @@ void VID_CheckRenderer(void)
 	else if (rendermode == render_opengl)
 	{
 		I_StartupHardwareGraphics();
-		R_InitHardwareMode();
-		HWR_Switch();
+		// Needs to check if switching failed somehow, too.
+		if (rendermode == render_opengl)
+		{
+			R_InitHardwareMode();
+			HWR_Switch();
+		}
 	}
+#else
+	(void)oldrenderer;
 #endif
 }
 
@@ -1665,10 +1703,10 @@ void I_StartupGraphics(void)
 
 #ifdef HWRENDER
 	if (M_CheckParm("-opengl"))
-		rendermode = render_opengl;
+		chosenrendermode = rendermode = render_opengl;
 	else if (M_CheckParm("-software"))
 #endif
-		rendermode = render_soft;
+		chosenrendermode = rendermode = render_soft;
 
 	usesdl2soft = M_CheckParm("-softblit");
 	borderlesswindow = M_CheckParm("-borderless");
@@ -1764,13 +1802,15 @@ void I_StartupHardwareGraphics(void)
 		HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL);
 		HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
 		HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
-		// check gl renderer lib
-		if (HWD.pfnGetRenderVersion() != VERSION)
-			I_Error("%s", M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n"));
+
 		if (!HWD.pfnInit(I_Error)) // let load the OpenGL library
+		{
 			rendermode = render_soft;
+			setrenderneeded = 0;
+		}
 		else
-			glstartup = true;
+			hwrenderloaded = true;
+		glstartup = true;
 	}
 #endif
 }
diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c
index 6c0dd35a5..3e02e4ec3 100644
--- a/src/sdl/ogl_sdl.c
+++ b/src/sdl/ogl_sdl.c
@@ -128,15 +128,15 @@ boolean LoadGL(void)
 			return SetupGLfunc();
 		else
 		{
-			I_OutputMsg("Could not load GLU Library: %s\n", GLULibname);
+			CONS_Alert(CONS_ERROR, "Could not load GLU Library: %s\n", GLULibname);
 			if (!M_CheckParm ("-GLUlib"))
-				I_OutputMsg("If you know what is the GLU library's name, use -GLUlib\n");
+				CONS_Alert(CONS_ERROR, "If you know what is the GLU library's name, use -GLUlib\n");
 		}
 	}
 	else
 	{
-		I_OutputMsg("Could not load GLU Library\n");
-		I_OutputMsg("If you know what is the GLU library's name, use -GLUlib\n");
+		CONS_Alert(CONS_ERROR, "Could not load GLU Library\n");
+		CONS_Alert(CONS_ERROR, "If you know what is the GLU library's name, use -GLUlib\n");
 	}
 #endif
 	return SetupGLfunc();

From cca366552519495e120ce798e1dd82930f4f16a2 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 15 Feb 2020 13:51:32 -0300
Subject: [PATCH 032/251] Fallback to Software if the renderer version doesn't
 match

---
 src/sdl/i_video.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index a37e94fad..4b30fc676 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -1803,13 +1803,19 @@ void I_StartupHardwareGraphics(void)
 		HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
 		HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
 
-		if (!HWD.pfnInit(I_Error)) // let load the OpenGL library
+		if (HWD.pfnGetRenderVersion() != VERSION)
+		{
+			CONS_Alert(CONS_ERROR, M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n"));
+			hwrenderloaded = false;
+		}
+		else
+			hwrenderloaded = HWD.pfnInit(I_Error); // let load the OpenGL library
+
+		if (!hwrenderloaded)
 		{
 			rendermode = render_soft;
 			setrenderneeded = 0;
 		}
-		else
-			hwrenderloaded = true;
 		glstartup = true;
 	}
 #endif

From 6c5db5f4628f199206e1183414716839d563a5d5 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 15 Feb 2020 14:25:28 -0300
Subject: [PATCH 033/251] Missing comment

---
 src/sdl/i_video.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 4b30fc676..afaaa2775 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -1803,6 +1803,7 @@ void I_StartupHardwareGraphics(void)
 		HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL);
 		HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL);
 
+		// check gl renderer lib
 		if (HWD.pfnGetRenderVersion() != VERSION)
 		{
 			CONS_Alert(CONS_ERROR, M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n"));

From 07afd7520fb53bc110c5c97a890e82e5f8b67854 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 15 Feb 2020 14:10:55 -0300
Subject: [PATCH 034/251] Only initialise OpenGL if you actually intend to use
 it.

---
 src/i_video.h     |  3 ++-
 src/sdl/i_video.c | 24 +++++++++++++++---------
 src/sdl/ogl_sdl.c |  4 ++--
 3 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/src/i_video.h b/src/i_video.h
index 8f87a360e..294b7ef84 100644
--- a/src/i_video.h
+++ b/src/i_video.h
@@ -37,8 +37,9 @@ typedef enum
 extern rendermode_t rendermode;
 
 /**	\brief hardware renderer loaded
+	0 = never loaded, 1 = loaded successfully, -1 = failed loading
 */
-extern boolean hwrenderloaded;
+extern INT32 hwrenderloaded;
 
 /**	\brief use highcolor modes if true
 */
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index afaaa2775..18cce3eab 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -104,7 +104,7 @@ static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff
 static consvar_t cv_alwaysgrabmouse = {"alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 
 UINT8 graphics_started = 0; // Is used in console.c and screen.c
-boolean hwrenderloaded = false;
+INT32 hwrenderloaded = 0;
 
 // To disable fullscreen at startup; is set in VID_PrepareModeList
 boolean allow_fullscreen = false;
@@ -1473,7 +1473,7 @@ static SDL_bool Impl_CreateContext(void)
 #ifdef HWRENDER
 static void VID_CheckGLLoaded(rendermode_t oldrender)
 {
-	if (!hwrenderloaded) // Well, it didn't work the first time anyway.
+	if (hwrenderloaded == -1) // Well, it didn't work the first time anyway.
 	{
 		CONS_Alert(CONS_ERROR, "OpenGL never loaded\n");
 		rendermode = oldrender;
@@ -1505,8 +1505,13 @@ void VID_CheckRenderer(void)
 	{
 		rendermode = setrenderneeded;
 #ifdef HWRENDER
-		if (setrenderneeded == render_opengl)
+		if (rendermode == render_opengl)
+		{
 			VID_CheckGLLoaded(oldrenderer);
+			// Initialise OpenGL before calling SDLSetMode!!!
+			if (hwrenderloaded != 1)
+				I_StartupHardwareGraphics();
+		}
 #endif
 		Impl_CreateContext();
 	}
@@ -1522,14 +1527,14 @@ void VID_CheckRenderer(void)
 			bufSurface = NULL;
 		}
 #ifdef HWRENDER
-		HWR_FreeTextureCache();
+		if (hwrenderloaded == 1) // Only if OpenGL ever loaded!
+			HWR_FreeTextureCache();
 #endif
 		SCR_SetDrawFuncs();
 	}
 #ifdef HWRENDER
 	else if (rendermode == render_opengl)
 	{
-		I_StartupHardwareGraphics();
 		// Needs to check if switching failed somehow, too.
 		if (rendermode == render_opengl)
 		{
@@ -1714,7 +1719,8 @@ void I_StartupGraphics(void)
 	//SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2);
 	VID_Command_ModeList_f();
 #ifdef HWRENDER
-	I_StartupHardwareGraphics();
+	if (chosenrendermode == render_opengl)
+		I_StartupHardwareGraphics();
 #endif
 
 	// Fury: we do window initialization after GL setup to allow
@@ -1807,12 +1813,12 @@ void I_StartupHardwareGraphics(void)
 		if (HWD.pfnGetRenderVersion() != VERSION)
 		{
 			CONS_Alert(CONS_ERROR, M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n"));
-			hwrenderloaded = false;
+			hwrenderloaded = -1;
 		}
 		else
-			hwrenderloaded = HWD.pfnInit(I_Error); // let load the OpenGL library
+			hwrenderloaded = HWD.pfnInit(I_Error) ? 1 : -1; // let load the OpenGL library
 
-		if (!hwrenderloaded)
+		if (hwrenderloaded == -1)
 		{
 			rendermode = render_soft;
 			setrenderneeded = 0;
diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c
index 3e02e4ec3..6654a75a0 100644
--- a/src/sdl/ogl_sdl.c
+++ b/src/sdl/ogl_sdl.c
@@ -95,10 +95,10 @@ boolean LoadGL(void)
 
 	if (SDL_GL_LoadLibrary(OGLLibname) != 0)
 	{
-		I_OutputMsg("Could not load OpenGL Library: %s\n"
+		CONS_Alert(CONS_ERROR, "Could not load OpenGL Library: %s\n"
 					"Falling back to Software mode.\n", SDL_GetError());
 		if (!M_CheckParm ("-OGLlib"))
-			I_OutputMsg("If you know what is the OpenGL library's name, use -OGLlib\n");
+			CONS_Alert(CONS_ERROR, "If you know what is the OpenGL library's name, use -OGLlib\n");
 		return 0;
 	}
 

From 3fa4db891f9ef693acf6c8e1668dc038e2fb310e Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Mon, 17 Feb 2020 01:13:13 -0300
Subject: [PATCH 035/251] Always load the GL library!

---
 src/sdl/i_video.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 18cce3eab..b50790f77 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -1719,8 +1719,7 @@ void I_StartupGraphics(void)
 	//SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2);
 	VID_Command_ModeList_f();
 #ifdef HWRENDER
-	if (chosenrendermode == render_opengl)
-		I_StartupHardwareGraphics();
+	I_StartupHardwareGraphics();
 #endif
 
 	// Fury: we do window initialization after GL setup to allow

From 9d9de3aff6e5272c62e1c243732ea5af3820a356 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 15 Feb 2020 14:38:16 -0300
Subject: [PATCH 036/251] Only set OpenGL as the target renderer if it loaded
 successfully

---
 src/screen.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/screen.c b/src/screen.c
index b5faaef7e..9c1af11a8 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -464,7 +464,7 @@ void SCR_ChangeRenderer(void)
 	{
 		target_renderer = cv_renderer.value;
 #ifdef HWRENDER
-		if (M_CheckParm("-opengl") && hwrenderloaded)
+		if (M_CheckParm("-opengl") && (hwrenderloaded == 1))
 			target_renderer = rendermode = render_opengl;
 		else
 #endif

From 7ddad9c9ec9fac004d9c19a5a8a97da7c07d3d74 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 15 Feb 2020 21:08:06 -0300
Subject: [PATCH 037/251] Remove redundant check

---
 src/sdl/i_video.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index b50790f77..fa1de19f2 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -1535,12 +1535,8 @@ void VID_CheckRenderer(void)
 #ifdef HWRENDER
 	else if (rendermode == render_opengl)
 	{
-		// Needs to check if switching failed somehow, too.
-		if (rendermode == render_opengl)
-		{
-			R_InitHardwareMode();
-			HWR_Switch();
-		}
+		R_InitHardwareMode();
+		HWR_Switch();
 	}
 #else
 	(void)oldrenderer;

From 04ee6ca12c29fbb7a1a9ec2ca6288d1d60adda5e Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 15 Feb 2020 22:11:54 -0300
Subject: [PATCH 038/251] Don't call HWR_Switch twice

---
 src/sdl/i_video.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index fa1de19f2..ca7b56592 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -1534,10 +1534,7 @@ void VID_CheckRenderer(void)
 	}
 #ifdef HWRENDER
 	else if (rendermode == render_opengl)
-	{
 		R_InitHardwareMode();
-		HWR_Switch();
-	}
 #else
 	(void)oldrenderer;
 #endif

From 8da832986c31debdbba610997634febb880eac08 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 15 Feb 2020 22:23:05 -0300
Subject: [PATCH 039/251] Don't center the window when changing renderers

---
 src/sdl/i_video.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index ca7b56592..bacb4f771 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -176,7 +176,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen);
 //static void Impl_SetWindowName(const char *title);
 static void Impl_SetWindowIcon(void);
 
-static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
+static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool reposition)
 {
 	static SDL_bool wasfullscreen = SDL_FALSE;
 	Uint32 rmask;
@@ -205,10 +205,13 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
 			}
 			// Reposition window only in windowed mode
 			SDL_SetWindowSize(window, width, height);
-			SDL_SetWindowPosition(window,
-				SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)),
-				SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window))
-			);
+			if (reposition)
+			{
+				SDL_SetWindowPosition(window,
+					SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)),
+					SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window))
+				);
+			}
 		}
 	}
 	else
@@ -1491,6 +1494,7 @@ static void VID_CheckGLLoaded(rendermode_t oldrender)
 
 void VID_CheckRenderer(void)
 {
+	SDL_bool rendererchanged = SDL_FALSE;
 	rendermode_t oldrenderer = rendermode;
 
 	if (dedicated)
@@ -1504,6 +1508,8 @@ void VID_CheckRenderer(void)
 	if (setrenderneeded)
 	{
 		rendermode = setrenderneeded;
+		rendererchanged = SDL_TRUE;
+
 #ifdef HWRENDER
 		if (rendermode == render_opengl)
 		{
@@ -1511,12 +1517,15 @@ void VID_CheckRenderer(void)
 			// Initialise OpenGL before calling SDLSetMode!!!
 			if (hwrenderloaded != 1)
 				I_StartupHardwareGraphics();
+			else if (hwrenderloaded == -1)
+				rendererchanged = SDL_FALSE;
 		}
 #endif
+
 		Impl_CreateContext();
 	}
 
-	SDLSetMode(vid.width, vid.height, USE_FULLSCREEN);
+	SDLSetMode(vid.width, vid.height, USE_FULLSCREEN, (rendererchanged ? SDL_FALSE : SDL_TRUE));
 	Impl_VideoSetupBuffer();
 
 	if (rendermode == render_soft)

From cac5f9d1714676f53fbe0f35531db17a3bc9ebfd Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Mon, 17 Feb 2020 12:14:51 -0300
Subject: [PATCH 040/251] add -nogl parm

---
 src/d_main.c      |  9 ++++++++-
 src/m_menu.c      | 28 ++++++++++++++++++++++++++--
 src/screen.c      | 14 ++++++++++++++
 src/sdl/i_video.c | 11 +++++++----
 4 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/src/d_main.c b/src/d_main.c
index 6616dfaa6..d9f67675c 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1291,11 +1291,18 @@ void D_SRB2Main(void)
 	// Lactozilla: Does the render mode need to change?
 	if ((setrenderneeded != 0) && (setrenderneeded != rendermode))
 	{
-		CONS_Printf("Switching the renderer...\n");
+		CONS_Printf(M_GetText("Switching the renderer...\n"));
+		Z_PreparePatchFlush();
+
+		// set needpatchflush / needpatchrecache true for D_CheckRendererState
 		needpatchflush = true;
 		needpatchrecache = true;
+
+		// Set cv_renderer to the new render mode
 		VID_CheckRenderer();
 		SCR_ChangeRendererCVars(setrenderneeded);
+
+		// check the renderer's state, and then clear setrenderneeded
 		D_CheckRendererState();
 		setrenderneeded = 0;
 	}
diff --git a/src/m_menu.c b/src/m_menu.c
index 97c04ebd5..0349ed3bc 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -310,6 +310,7 @@ static void M_AssignJoystick(INT32 choice);
 static void M_ChangeControl(INT32 choice);
 
 // Video & Sound
+static void M_VideoOptions(INT32 choice);
 menu_t OP_VideoOptionsDef, OP_VideoModeDef, OP_ColorOptionsDef;
 #ifdef HWRENDER
 static void M_OpenGLOptionsMenu(void);
@@ -1031,7 +1032,7 @@ static menuitem_t OP_MainMenu[] =
 	{IT_SUBMENU | IT_STRING, NULL, "Player 2 Controls...", &OP_P2ControlsDef,   20},
 	{IT_CVAR    | IT_STRING, NULL, "Controls per key",     &cv_controlperkey,   30},
 
-	{IT_SUBMENU | IT_STRING, NULL, "Video Options...",     &OP_VideoOptionsDef, 50},
+	{IT_CALL    | IT_STRING, NULL, "Video Options...",     M_VideoOptions,      50},
 	{IT_SUBMENU | IT_STRING, NULL, "Sound Options...",     &OP_SoundOptionsDef, 60},
 
 	{IT_CALL    | IT_STRING, NULL, "Server Options...",    M_ServerOptions,     80},
@@ -1282,6 +1283,16 @@ static menuitem_t OP_Camera2ExtendedOptionsMenu[] =
 	{IT_STRING  | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 126},
 };
 
+enum
+{
+	op_video_resolution = 1,
+#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
+	op_video_fullscreen,
+#endif
+	op_video_vsync,
+	op_video_renderer,
+};
+
 static menuitem_t OP_VideoOptionsMenu[] =
 {
 	{IT_HEADER, NULL, "Screen", NULL, 0},
@@ -2078,6 +2089,20 @@ menu_t OP_PlaystyleDef = {
 	0, 0, 0, NULL
 };
 
+static void M_VideoOptions(INT32 choice)
+{
+	(void)choice;
+#ifdef HWRENDER
+	if (hwrenderloaded == -1)
+	{
+		OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR);
+		OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer";
+		OP_VideoOptionsMenu[op_video_renderer].text = "Software";
+	}
+
+#endif
+	M_SetupNextMenu(&OP_VideoOptionsDef);
+}
 
 menu_t OP_VideoOptionsDef =
 {
@@ -12005,7 +12030,6 @@ static void M_VideoModeMenu(INT32 choice)
 
 static void M_DrawMainVideoMenu(void)
 {
-
 	M_DrawGenericScrollMenu();
 	if (itemOn < 8) // where it starts to go offscreen; change this number if you change the layout of the video menu
 	{
diff --git a/src/screen.c b/src/screen.c
index 9c1af11a8..9c61f5689 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -450,6 +450,20 @@ static int target_renderer = 0;
 void SCR_ActuallyChangeRenderer(void)
 {
 	setrenderneeded = target_renderer;
+
+#ifdef HWRENDER
+	// Well, it didn't even load anyway.
+	if ((hwrenderloaded == -1) && (setrenderneeded == render_opengl))
+	{
+		if (M_CheckParm("-nogl"))
+			CONS_Alert(CONS_ERROR, "OpenGL rendering was disabled!\n");
+		else
+			CONS_Alert(CONS_ERROR, "OpenGL never loaded\n");
+		setrenderneeded = 0;
+		return;
+	}
+#endif
+
 	// setting the same renderer twice WILL crash your game, so let's not, please
 	if (rendermode == setrenderneeded)
 		setrenderneeded = 0;
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index bacb4f771..1dbaf06bd 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -1440,7 +1440,7 @@ static SDL_bool Impl_CreateContext(void)
 {
 	// Renderer-specific stuff
 #ifdef HWRENDER
-	if (rendermode == render_opengl)
+	if ((rendermode == render_opengl) && (hwrenderloaded != -1))
 	{
 		if (!sdlglcontext)
 			sdlglcontext = SDL_GL_CreateContext(window);
@@ -1478,7 +1478,6 @@ static void VID_CheckGLLoaded(rendermode_t oldrender)
 {
 	if (hwrenderloaded == -1) // Well, it didn't work the first time anyway.
 	{
-		CONS_Alert(CONS_ERROR, "OpenGL never loaded\n");
 		rendermode = oldrender;
 		if (chosenrendermode == render_opengl) // fallback to software
 			rendermode = render_soft;
@@ -1587,7 +1586,8 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 		flags |= SDL_WINDOW_BORDERLESS;
 
 #ifdef HWRENDER
-	flags |= SDL_WINDOW_OPENGL;
+	if (hwrenderloaded != -1)
+		flags |= SDL_WINDOW_OPENGL;
 #endif
 
 	// Create a window
@@ -1721,7 +1721,10 @@ void I_StartupGraphics(void)
 	//SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2);
 	VID_Command_ModeList_f();
 #ifdef HWRENDER
-	I_StartupHardwareGraphics();
+	if (M_CheckParm("-nogl"))
+		hwrenderloaded = -1; // Don't call SDL_GL_LoadLibrary
+	else
+		I_StartupHardwareGraphics();
 #endif
 
 	// Fury: we do window initialization after GL setup to allow

From e53a17bb528800c6a3ec7ec2fcc36c5c6f96ba20 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Mon, 17 Feb 2020 21:11:56 -0300
Subject: [PATCH 041/251] Rename stuff around

---
 src/android/i_video.c   | 10 ++++------
 src/djgppdos/i_video.c  |  5 +----
 src/djgppdos/vid_vesa.c |  6 ++----
 src/dummy/i_video.c     | 10 ++++------
 src/i_video.h           | 18 +++++++++++-------
 src/m_menu.c            |  2 +-
 src/screen.c            |  4 ++--
 src/sdl/i_video.c       | 39 +++++++++++++++++----------------------
 src/win32/win_vid.c     | 11 +++--------
 9 files changed, 45 insertions(+), 60 deletions(-)

diff --git a/src/android/i_video.c b/src/android/i_video.c
index b8bb4fefb..1909cd71a 100644
--- a/src/android/i_video.c
+++ b/src/android/i_video.c
@@ -19,10 +19,10 @@ boolean allow_fullscreen = false;
 consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 
 void I_StartupGraphics(void){}
-void I_StartupHardwareGraphics(void){}
-
 void I_ShutdownGraphics(void){}
 
+void VID_StartupOpenGL(void){}
+
 void I_SetPalette(RGBA_t *palette)
 {
   (void)palette;
@@ -52,10 +52,8 @@ INT32 VID_SetMode(INT32 modenum)
   return 0;
 }
 
-void VID_CheckRenderer(void)
-{
-	// ..............
-}
+void VID_CheckRenderer(void) {}
+void VID_CheckGLLoaded(rendermode_t oldrender) {}
 
 const char *VID_GetModeName(INT32 modenum)
 {
diff --git a/src/djgppdos/i_video.c b/src/djgppdos/i_video.c
index 02c7a842b..f525b96ca 100644
--- a/src/djgppdos/i_video.c
+++ b/src/djgppdos/i_video.c
@@ -339,7 +339,4 @@ void I_StartupGraphics(void)
 
 }
 
-void I_StartupHardwareGraphics(void)
-{
-	// oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo y
-}
+void VID_StartupOpenGL(void) {}
diff --git a/src/djgppdos/vid_vesa.c b/src/djgppdos/vid_vesa.c
index c8ce7dae5..61ed18e4b 100644
--- a/src/djgppdos/vid_vesa.c
+++ b/src/djgppdos/vid_vesa.c
@@ -378,10 +378,8 @@ INT32 VID_SetMode (INT32 modenum)  //, UINT8 *palette)
 	return 1;
 }
 
-void VID_CheckRenderer(void)
-{
-	// ..............
-}
+void VID_CheckRenderer(void) {}
+void VID_CheckGLLoaded(rendermode_t oldrender) {}
 
 
 
diff --git a/src/dummy/i_video.c b/src/dummy/i_video.c
index fafeee000..56ead3672 100644
--- a/src/dummy/i_video.c
+++ b/src/dummy/i_video.c
@@ -11,10 +11,10 @@ boolean allow_fullscreen = false;
 consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 
 void I_StartupGraphics(void){}
-void I_StartupHardwareGraphics(void){}
-
 void I_ShutdownGraphics(void){}
 
+void VID_StartupOpenGL(void){}
+
 void I_SetPalette(RGBA_t *palette)
 {
 	(void)palette;
@@ -40,10 +40,8 @@ INT32 VID_SetMode(INT32 modenum)
 	return 0;
 }
 
-void VID_CheckRenderer(void)
-{
-	// ..............
-}
+void VID_CheckRenderer(void) {}
+void VID_CheckGLLoaded(rendermode_t oldrender) {}
 
 const char *VID_GetModeName(INT32 modenum)
 {
diff --git a/src/i_video.h b/src/i_video.h
index 294b7ef84..2b40356ea 100644
--- a/src/i_video.h
+++ b/src/i_video.h
@@ -36,10 +36,10 @@ typedef enum
 */
 extern rendermode_t rendermode;
 
-/**	\brief hardware renderer loaded
+/**	\brief OpenGL state
 	0 = never loaded, 1 = loaded successfully, -1 = failed loading
 */
-extern INT32 hwrenderloaded;
+extern INT32 vid_opengl_state;
 
 /**	\brief use highcolor modes if true
 */
@@ -49,11 +49,7 @@ extern boolean highcolor;
 */
 void I_StartupGraphics(void);
 
-/**	\brief setup hardware mode
-*/
-void I_StartupHardwareGraphics(void);
-
-/**	\brief restore old video mode
+/**	\brief shutdown video mode
 */
 void I_ShutdownGraphics(void);
 
@@ -97,6 +93,14 @@ INT32 VID_SetMode(INT32 modenum);
 */
 void VID_CheckRenderer(void);
 
+/**	\brief Load OpenGL mode
+*/
+void VID_StartupOpenGL(void);
+
+/**	\brief Checks if OpenGL loaded
+*/
+void VID_CheckGLLoaded(rendermode_t oldrender);
+
 /**	\brief	The VID_GetModeName function
 
 	\param	modenum	video mode number
diff --git a/src/m_menu.c b/src/m_menu.c
index 0349ed3bc..82793ab9a 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -2093,7 +2093,7 @@ static void M_VideoOptions(INT32 choice)
 {
 	(void)choice;
 #ifdef HWRENDER
-	if (hwrenderloaded == -1)
+	if (vid_opengl_state == -1)
 	{
 		OP_VideoOptionsMenu[op_video_renderer].status = (IT_TRANSTEXT | IT_PAIR);
 		OP_VideoOptionsMenu[op_video_renderer].patch = "Renderer";
diff --git a/src/screen.c b/src/screen.c
index 9c61f5689..828454a9b 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -453,7 +453,7 @@ void SCR_ActuallyChangeRenderer(void)
 
 #ifdef HWRENDER
 	// Well, it didn't even load anyway.
-	if ((hwrenderloaded == -1) && (setrenderneeded == render_opengl))
+	if ((vid_opengl_state == -1) && (setrenderneeded == render_opengl))
 	{
 		if (M_CheckParm("-nogl"))
 			CONS_Alert(CONS_ERROR, "OpenGL rendering was disabled!\n");
@@ -478,7 +478,7 @@ void SCR_ChangeRenderer(void)
 	{
 		target_renderer = cv_renderer.value;
 #ifdef HWRENDER
-		if (M_CheckParm("-opengl") && (hwrenderloaded == 1))
+		if (M_CheckParm("-opengl") && (vid_opengl_state == 1))
 			target_renderer = rendermode = render_opengl;
 		else
 #endif
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 1dbaf06bd..5d1baee74 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -104,7 +104,7 @@ static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff
 static consvar_t cv_alwaysgrabmouse = {"alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 
 UINT8 graphics_started = 0; // Is used in console.c and screen.c
-INT32 hwrenderloaded = 0;
+INT32 vid_opengl_state = 0;
 
 // To disable fullscreen at startup; is set in VID_PrepareModeList
 boolean allow_fullscreen = false;
@@ -1440,7 +1440,7 @@ static SDL_bool Impl_CreateContext(void)
 {
 	// Renderer-specific stuff
 #ifdef HWRENDER
-	if ((rendermode == render_opengl) && (hwrenderloaded != -1))
+	if ((rendermode == render_opengl) && (vid_opengl_state != -1))
 	{
 		if (!sdlglcontext)
 			sdlglcontext = SDL_GL_CreateContext(window);
@@ -1473,10 +1473,10 @@ static SDL_bool Impl_CreateContext(void)
 	return SDL_TRUE;
 }
 
-#ifdef HWRENDER
-static void VID_CheckGLLoaded(rendermode_t oldrender)
+void VID_CheckGLLoaded(rendermode_t oldrender)
 {
-	if (hwrenderloaded == -1) // Well, it didn't work the first time anyway.
+#ifdef HWRENDER
+	if (vid_opengl_state == -1) // Well, it didn't work the first time anyway.
 	{
 		rendermode = oldrender;
 		if (chosenrendermode == render_opengl) // fallback to software
@@ -1488,8 +1488,8 @@ static void VID_CheckGLLoaded(rendermode_t oldrender)
 			setrenderneeded = 0;
 		}
 	}
-}
 #endif
+}
 
 void VID_CheckRenderer(void)
 {
@@ -1499,11 +1499,6 @@ void VID_CheckRenderer(void)
 	if (dedicated)
 		return;
 
-#ifdef HWRENDER
-	if (!graphics_started)
-		VID_CheckGLLoaded(oldrenderer);
-#endif
-
 	if (setrenderneeded)
 	{
 		rendermode = setrenderneeded;
@@ -1514,9 +1509,9 @@ void VID_CheckRenderer(void)
 		{
 			VID_CheckGLLoaded(oldrenderer);
 			// Initialise OpenGL before calling SDLSetMode!!!
-			if (hwrenderloaded != 1)
-				I_StartupHardwareGraphics();
-			else if (hwrenderloaded == -1)
+			if (vid_opengl_state != 1)
+				VID_StartupOpenGL();
+			else if (vid_opengl_state == -1)
 				rendererchanged = SDL_FALSE;
 		}
 #endif
@@ -1535,7 +1530,7 @@ void VID_CheckRenderer(void)
 			bufSurface = NULL;
 		}
 #ifdef HWRENDER
-		if (hwrenderloaded == 1) // Only if OpenGL ever loaded!
+		if (vid_opengl_state == 1) // Only if OpenGL ever loaded!
 			HWR_FreeTextureCache();
 #endif
 		SCR_SetDrawFuncs();
@@ -1586,7 +1581,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 		flags |= SDL_WINDOW_BORDERLESS;
 
 #ifdef HWRENDER
-	if (hwrenderloaded != -1)
+	if (vid_opengl_state != -1)
 		flags |= SDL_WINDOW_OPENGL;
 #endif
 
@@ -1722,9 +1717,9 @@ void I_StartupGraphics(void)
 	VID_Command_ModeList_f();
 #ifdef HWRENDER
 	if (M_CheckParm("-nogl"))
-		hwrenderloaded = -1; // Don't call SDL_GL_LoadLibrary
+		vid_opengl_state = -1; // Don't call SDL_GL_LoadLibrary
 	else
-		I_StartupHardwareGraphics();
+		VID_StartupOpenGL();
 #endif
 
 	// Fury: we do window initialization after GL setup to allow
@@ -1779,7 +1774,7 @@ void I_StartupGraphics(void)
 	graphics_started = true;
 }
 
-void I_StartupHardwareGraphics(void)
+void VID_StartupOpenGL(void)
 {
 #ifdef HWRENDER
 	static boolean glstartup = false;
@@ -1817,12 +1812,12 @@ void I_StartupHardwareGraphics(void)
 		if (HWD.pfnGetRenderVersion() != VERSION)
 		{
 			CONS_Alert(CONS_ERROR, M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n"));
-			hwrenderloaded = -1;
+			vid_opengl_state = -1;
 		}
 		else
-			hwrenderloaded = HWD.pfnInit(I_Error) ? 1 : -1; // let load the OpenGL library
+			vid_opengl_state = HWD.pfnInit(I_Error) ? 1 : -1; // let load the OpenGL library
 
-		if (hwrenderloaded == -1)
+		if (vid_opengl_state == -1)
 		{
 			rendermode = render_soft;
 			setrenderneeded = 0;
diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c
index d0aab92b3..4e7bab569 100644
--- a/src/win32/win_vid.c
+++ b/src/win32/win_vid.c
@@ -239,10 +239,7 @@ void I_StartupGraphics(void)
 	if (!dedicated) graphics_started = true;
 }
 
-void I_StartupHardwareGraphics(void)
-{
-	// oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo yeah oh yeah woo y
-}
+void VID_StartupOpenGL(void){}
 
 // ------------------
 // I_ShutdownGraphics
@@ -951,10 +948,8 @@ INT32 VID_SetMode(INT32 modenum)
 	return 1;
 }
 
-void VID_CheckRenderer(void)
-{
-	// ..............
-}
+void VID_CheckRenderer(void) {}
+void VID_CheckGLLoaded(rendermode_t oldrender) {}
 
 // ========================================================================
 // Free the video buffer of the last video mode,

From a9a0601c84bcddbef577a458ced27e652b4df44c Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Mon, 17 Feb 2020 16:37:13 -0800
Subject: [PATCH 042/251] Revert "Revert "Let the console open in menus""

This reverts commit 705cf9fd4078ce34857d98043023612e9205773c.
---
 src/console.c | 11 +----------
 src/d_main.c  | 15 +++++++--------
 2 files changed, 8 insertions(+), 18 deletions(-)

diff --git a/src/console.c b/src/console.c
index 59d2b3e6c..8746bf036 100644
--- a/src/console.c
+++ b/src/console.c
@@ -613,15 +613,6 @@ void CON_Ticker(void)
 	con_tick++;
 	con_tick &= 7;
 
-	// if the menu is open then close the console.
-	if (menuactive && con_destlines)
-	{
-		consoletoggle = false;
-		con_destlines = 0;
-		CON_ClearHUD();
-		I_UpdateMouseGrab();
-	}
-
 	// console key was pushed
 	if (consoletoggle)
 	{
@@ -793,7 +784,7 @@ boolean CON_Responder(event_t *ev)
 		// check other keys only if console prompt is active
 		if (!consoleready && key < NUMINPUTS) // metzgermeister: boundary check!!
 		{
-			if (bindtable[key])
+			if (! menuactive && bindtable[key])
 			{
 				COM_BufAddText(bindtable[key]);
 				COM_BufAddText("\n");
diff --git a/src/d_main.c b/src/d_main.c
index 2ff0042fd..149fb3071 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -188,14 +188,14 @@ void D_ProcessEvents(void)
 				continue;
 		}
 
-		// Menu input
-		if (M_Responder(ev))
-			continue; // menu ate the event
-
 		// console input
 		if (CON_Responder(ev))
 			continue; // ate the event
 
+		// Menu input
+		if (M_Responder(ev))
+			continue; // menu ate the event
+
 		G_Responder(ev);
 	}
 }
@@ -502,13 +502,12 @@ static void D_Display(void)
 	// vid size change is now finished if it was on...
 	vid.recalc = 0;
 
-	// FIXME: draw either console or menu, not the two
-	if (gamestate != GS_TIMEATTACK)
-		CON_Drawer();
-
 	M_Drawer(); // menu is drawn even on top of everything
 	// focus lost moved to M_Drawer
 
+	if (gamestate != GS_TIMEATTACK)
+		CON_Drawer();
+
 	//
 	// wipe update
 	//

From b2733eba73146c9b87ebdcff26cc0e10d4107408 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Sat, 15 Feb 2020 17:08:07 -0800
Subject: [PATCH 043/251] Draw console in the Record/NiGHTS Attack menus

(cherry picked from commit 4efd915d28d0f193528d141b04c5f88b84877f97)
---
 src/d_main.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/d_main.c b/src/d_main.c
index 149fb3071..6b5164894 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -505,8 +505,7 @@ static void D_Display(void)
 	M_Drawer(); // menu is drawn even on top of everything
 	// focus lost moved to M_Drawer
 
-	if (gamestate != GS_TIMEATTACK)
-		CON_Drawer();
+	CON_Drawer();
 
 	//
 	// wipe update

From bef6cb532b9d414eff831a40ae0321eb7a79b983 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Mon, 17 Feb 2020 21:58:32 -0300
Subject: [PATCH 044/251] Fix what !785 tried to fix, but correctly

---
 src/hardware/hw_main.c |  1 -
 src/sdl/i_video.c      | 66 +++++++++++++++++++++++++++++++++---------
 2 files changed, 53 insertions(+), 14 deletions(-)

diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 7e913c4c7..eed1b4644 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -6611,7 +6611,6 @@ void HWR_Shutdown(void)
 	CONS_Printf("HWR_Shutdown()\n");
 	HWR_FreeExtraSubsectors();
 	HWR_FreePolyPool();
-	HWR_FreeMipmapCache();
 	HWR_FreeTextureCache();
 	HWD.pfnFlushScreenTextures();
 }
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 5d1baee74..3c1e01384 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -1493,7 +1493,8 @@ void VID_CheckGLLoaded(rendermode_t oldrender)
 
 void VID_CheckRenderer(void)
 {
-	SDL_bool rendererchanged = SDL_FALSE;
+	boolean rendererchanged = false;
+	boolean contextcreated = false;
 	rendermode_t oldrenderer = rendermode;
 
 	if (dedicated)
@@ -1502,21 +1503,51 @@ void VID_CheckRenderer(void)
 	if (setrenderneeded)
 	{
 		rendermode = setrenderneeded;
-		rendererchanged = SDL_TRUE;
+		rendererchanged = true;
 
 #ifdef HWRENDER
 		if (rendermode == render_opengl)
 		{
 			VID_CheckGLLoaded(oldrenderer);
+
 			// Initialise OpenGL before calling SDLSetMode!!!
-			if (vid_opengl_state != 1)
+			// This is because SDLSetMode calls OglSdlSurface.
+			if (vid_opengl_state == 0)
+			{
 				VID_StartupOpenGL();
+				// Loaded successfully!
+				if (vid_opengl_state == 1)
+				{
+					// Destroy the current window, if it exists.
+					if (window)
+					{
+						SDL_DestroyWindow(window);
+						window = NULL;
+					}
+
+					// Destroy the current window rendering context, if that also exists.
+					if (renderer)
+					{
+						SDL_DestroyRenderer(renderer);
+						renderer = NULL;
+					}
+
+					// Create a new window.
+					Impl_CreateWindow(USE_FULLSCREEN);
+
+					// From there, the OpenGL context was already created.
+					contextcreated = true;
+				}
+			}
 			else if (vid_opengl_state == -1)
-				rendererchanged = SDL_FALSE;
+				rendererchanged = false;
 		}
 #endif
 
-		Impl_CreateContext();
+		if (!contextcreated)
+			Impl_CreateContext();
+
+		setrenderneeded = 0;
 	}
 
 	SDLSetMode(vid.width, vid.height, USE_FULLSCREEN, (rendererchanged ? SDL_FALSE : SDL_TRUE));
@@ -1529,15 +1560,22 @@ void VID_CheckRenderer(void)
 			SDL_FreeSurface(bufSurface);
 			bufSurface = NULL;
 		}
+
+		if (rendererchanged)
+		{
 #ifdef HWRENDER
-		if (vid_opengl_state == 1) // Only if OpenGL ever loaded!
-			HWR_FreeTextureCache();
+			if (vid_opengl_state == 1) // Only if OpenGL ever loaded!
+				HWR_FreeTextureCache();
 #endif
-		SCR_SetDrawFuncs();
+			SCR_SetDrawFuncs();
+		}
 	}
 #ifdef HWRENDER
 	else if (rendermode == render_opengl)
-		R_InitHardwareMode();
+	{
+		if (rendererchanged)
+			R_InitHardwareMode();
+	}
 #else
 	(void)oldrenderer;
 #endif
@@ -1581,7 +1619,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 		flags |= SDL_WINDOW_BORDERLESS;
 
 #ifdef HWRENDER
-	if (vid_opengl_state != -1)
+	if (vid_opengl_state == 1)
 		flags |= SDL_WINDOW_OPENGL;
 #endif
 
@@ -1715,10 +1753,11 @@ void I_StartupGraphics(void)
 
 	//SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2);
 	VID_Command_ModeList_f();
+
 #ifdef HWRENDER
 	if (M_CheckParm("-nogl"))
-		vid_opengl_state = -1; // Don't call SDL_GL_LoadLibrary
-	else
+		vid_opengl_state = -1; // Don't startup OpenGL
+	else if (chosenrendermode == render_opengl)
 		VID_StartupOpenGL();
 #endif
 
@@ -1780,6 +1819,7 @@ void VID_StartupOpenGL(void)
 	static boolean glstartup = false;
 	if (!glstartup)
 	{
+		CONS_Printf("VID_StartupOpenGL()...\n");
 		HWD.pfnInit             = hwSym("Init",NULL);
 		HWD.pfnFinishUpdate     = NULL;
 		HWD.pfnDraw2DLine       = hwSym("Draw2DLine",NULL);
@@ -1811,7 +1851,7 @@ void VID_StartupOpenGL(void)
 		// check gl renderer lib
 		if (HWD.pfnGetRenderVersion() != VERSION)
 		{
-			CONS_Alert(CONS_ERROR, M_GetText("The version of the renderer doesn't match the version of the executable\nBe sure you have installed SRB2 properly.\n"));
+			CONS_Alert(CONS_ERROR, M_GetText("The version of the renderer doesn't match the version of the executable!\nBe sure you have installed SRB2 properly.\n"));
 			vid_opengl_state = -1;
 		}
 		else

From b78fc670d0824e2054d102706813087d0086c331 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Mon, 17 Feb 2020 17:10:29 -0800
Subject: [PATCH 045/251] Don't let console open with menu keys while the menu
 is open

---
 src/d_main.c | 8 ++++----
 src/m_menu.c | 4 ++++
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/d_main.c b/src/d_main.c
index 6b5164894..cff6b8805 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -188,14 +188,14 @@ void D_ProcessEvents(void)
 				continue;
 		}
 
-		// console input
-		if (CON_Responder(ev))
-			continue; // ate the event
-
 		// Menu input
 		if (M_Responder(ev))
 			continue; // menu ate the event
 
+		// console input
+		if (CON_Responder(ev))
+			continue; // ate the event
+
 		G_Responder(ev);
 	}
 }
diff --git a/src/m_menu.c b/src/m_menu.c
index dbe5d854f..687f87051 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -3150,6 +3150,9 @@ boolean M_Responder(event_t *ev)
 	if (gamestate == GS_TITLESCREEN && finalecount < TICRATE)
 		return false;
 
+	if (CON_Ready())
+		return false;
+
 	if (noFurtherInput)
 	{
 		// Ignore input after enter/escape/other buttons
@@ -3509,6 +3512,7 @@ boolean M_Responder(event_t *ev)
 			return false;
 
 		default:
+			CON_Responder(ev);
 			break;
 	}
 

From d3abf5dcfa83b2935294bd49a28d6b1968b81050 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Mon, 17 Feb 2020 22:31:34 -0300
Subject: [PATCH 046/251] Set the palette :)

---
 src/sdl/i_video.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 3c1e01384..dc263f457 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -1574,7 +1574,10 @@ void VID_CheckRenderer(void)
 	else if (rendermode == render_opengl)
 	{
 		if (rendererchanged)
+		{
 			R_InitHardwareMode();
+			V_SetPalette(0);
+		}
 	}
 #else
 	(void)oldrenderer;

From bd7b2fcb936e104bd3f63278cd743797efdbf70b Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Mon, 17 Feb 2020 22:33:36 -0300
Subject: [PATCH 047/251] setrenderneeded is already cleared earlier

---
 src/d_main.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/d_main.c b/src/d_main.c
index d9f67675c..c4b445089 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1300,11 +1300,10 @@ void D_SRB2Main(void)
 
 		// Set cv_renderer to the new render mode
 		VID_CheckRenderer();
-		SCR_ChangeRendererCVars(setrenderneeded);
+		SCR_ChangeRendererCVars(rendermode);
 
-		// check the renderer's state, and then clear setrenderneeded
+		// check the renderer's state
 		D_CheckRendererState();
-		setrenderneeded = 0;
 	}
 
 	wipegamestate = gamestate;

From b1ad7787f44bec6a0000728e68f97ea0cbb46e98 Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Tue, 18 Feb 2020 22:54:11 -0300
Subject: [PATCH 048/251] Standards 3

---
 src/p_enemy.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/p_enemy.c b/src/p_enemy.c
index 6b20862ed..b7ccdb01b 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -8961,13 +8961,13 @@ void A_Dye(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
+
+	mobj_t *target = ((locvar1 && actor->target) ? actor->target : actor);
+	UINT8 color = (UINT8)locvar2;
 #ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Dye", actor))
 		return;
 #endif
-	mobj_t *target = ((locvar1 && actor->target) ? actor->target : actor);
-	UINT8 color = (UINT8)locvar2;
-	
 	if (color >= MAXTRANSLATIONS)
 		return;
 	

From ebc1809da987b47746a537ee5bdaa8824b6c7b3f Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Wed, 19 Feb 2020 22:01:33 +0100
Subject: [PATCH 049/251] Fix bad tabulation

---
 src/d_netfil.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/d_netfil.c b/src/d_netfil.c
index 71449caca..413eef1ef 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -477,21 +477,21 @@ void AddLuaFileTransfer(const char *filename, const char *mode)
 	if (!filetransfer)
 		I_Error("AddLuaFileTransfer: Out of memory\n");
 	*prevnext = filetransfer;
-    filetransfer->next = NULL;
+	filetransfer->next = NULL;
 
-    // Allocate the file name
-    filetransfer->filename = strdup(filename);
-    if (!filetransfer->filename)
+	// Allocate the file name
+	filetransfer->filename = strdup(filename);
+	if (!filetransfer->filename)
 		I_Error("AddLuaFileTransfer: Out of memory\n");
 
-    // Create and allocate the real file name
+	// Create and allocate the real file name
 	if (server)
 		filetransfer->realfilename = strdup(va("%s" PATHSEP "%s",
 												luafiledir, filename));
 	else
 		filetransfer->realfilename = strdup(va("%s" PATHSEP "client" PATHSEP "$$$%d%d.tmp",
 												luafiledir, rand(), rand()));
-    if (!filetransfer->realfilename)
+	if (!filetransfer->realfilename)
 		I_Error("AddLuaFileTransfer: Out of memory\n");
 
 	strlcpy(filetransfer->mode, mode, sizeof(filetransfer->mode));
@@ -556,7 +556,7 @@ void SV_PrepareSendLuaFileToNextNode(void)
 void SV_HandleLuaFileSent(UINT8 node)
 {
 	luafiletransfers->nodestatus[node] = LFTNS_SENT;
-    SV_PrepareSendLuaFileToNextNode();
+	SV_PrepareSendLuaFileToNextNode();
 }
 
 void RemoveLuaFileTransfer(void)
@@ -1036,7 +1036,7 @@ void Got_Filetxpak(void)
 			CONS_Printf(M_GetText("Downloading %s...(done)\n"),
 				filename);
 #ifdef HAVE_BLUA
-            if (luafiletransfers)
+			if (luafiletransfers)
 			{
                 // Tell the server we have received the file
                 netbuffer->packettype = PT_HASLUAFILE;

From 20d054a679acdf70971ad0e90d992dc942fe3679 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Wed, 19 Feb 2020 22:37:30 +0100
Subject: [PATCH 050/251] Minor code cleanup

---
 src/d_clisrv.c | 2 +-
 src/d_netfil.c | 4 ++--
 src/d_netfil.h | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 6b0f49544..9f0d2439e 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -3164,7 +3164,7 @@ void D_QuitNetGame(void)
 
 	// abort send/receive of files
 	CloseNetFile();
-	RemoveLuaFileTransfers();
+	RemoveAllLuaFileTransfers();
 	waitingforluafiletransfer = false;
 
 	if (server)
diff --git a/src/d_netfil.c b/src/d_netfil.c
index 413eef1ef..1d1e7d203 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -506,7 +506,7 @@ void AddLuaFileTransfer(const char *filename, const char *mode)
 
 		if (!luafiletransfers->next) // Only if there is no transfer already going on
 		{
-			if (FIL_FileOK(filetransfer->realfilename))
+			if (FIL_ReadFileOK(filetransfer->realfilename))
 				SV_PrepareSendLuaFileToNextNode();
 			else
 			{
@@ -572,7 +572,7 @@ void RemoveLuaFileTransfer(void)
 	free(filetransfer);
 }
 
-void RemoveLuaFileTransfers(void)
+void RemoveAllLuaFileTransfers(void)
 {
 	while (luafiletransfers)
 		RemoveLuaFileTransfer();
diff --git a/src/d_netfil.h b/src/d_netfil.h
index 0d0b16975..0473b5f44 100644
--- a/src/d_netfil.h
+++ b/src/d_netfil.h
@@ -101,7 +101,7 @@ boolean SV_SendLuaFile(INT32 node, const char *filename, boolean textmode);
 void SV_PrepareSendLuaFile(const char *filename);
 void SV_HandleLuaFileSent(UINT8 node);
 void RemoveLuaFileTransfer(void);
-void RemoveLuaFileTransfers(void);
+void RemoveAllLuaFileTransfers(void);
 void SV_AbortLuaFileTransfer(INT32 node);
 void CL_PrepareDownloadLuaFile(void);
 void Got_LuaFile(UINT8 **cp, INT32 playernum);

From 3502278f8a5a5232adadbeddd524a7bf3687798a Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Thu, 20 Feb 2020 01:15:54 +0100
Subject: [PATCH 051/251] SpaceSpaceSpaceSpace

---
 src/d_netfil.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/d_netfil.c b/src/d_netfil.c
index 1d1e7d203..ed81a51b1 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -1038,9 +1038,9 @@ void Got_Filetxpak(void)
 #ifdef HAVE_BLUA
 			if (luafiletransfers)
 			{
-                // Tell the server we have received the file
-                netbuffer->packettype = PT_HASLUAFILE;
-                HSendPacket(servernode, true, 0, 0);
+				// Tell the server we have received the file
+				netbuffer->packettype = PT_HASLUAFILE;
+				HSendPacket(servernode, true, 0, 0);
 			}
 #endif
 		}

From 400366802c2d77a31b40da5ff57f366ca197383b Mon Sep 17 00:00:00 2001
From: Sally Cochenour <tehrealsalt@gmail.com>
Date: Thu, 20 Feb 2020 16:40:39 -0500
Subject: [PATCH 052/251] Make hook_FollowMobj a mobj hook instead of a player
 hook

Makes more logical sense, as if you have a custom follow item for a custom skin, you probably want your new thinker to only run for your new MT_ and not the vanilla ones.
---
 src/lua_hooklib.c | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index f9dad6cb7..99f41aef1 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -142,6 +142,7 @@ static int lib_addHook(lua_State *L)
 	case hook_HurtMsg:
 	case hook_MobjMoveBlocked:
 	case hook_MapThingSpawn:
+	case hook_FollowMobj:
 		hook.s.mt = MT_NULL;
 		if (lua_isnumber(L, 2))
 			hook.s.mt = lua_tonumber(L, 2);
@@ -203,6 +204,7 @@ static int lib_addHook(lua_State *L)
 	case hook_MobjRemoved:
 	case hook_MobjMoveBlocked:
 	case hook_MapThingSpawn:
+	case hook_FollowMobj:
 		lastp = &mobjhooks[hook.s.mt];
 		break;
 	case hook_JumpSpecial:
@@ -210,7 +212,6 @@ static int lib_addHook(lua_State *L)
 	case hook_SpinSpecial:
 	case hook_JumpSpinSpecial:
 	case hook_PlayerSpawn:
-	case hook_FollowMobj:
 	case hook_PlayerCanDamage:
 	case hook_TeamSwitch:
 	case hook_ViewpointSwitch:
@@ -1364,7 +1365,34 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj)
 
 	lua_settop(gL, 0);
 
-	for (hookp = playerhooks; hookp; hookp = hookp->next)
+	// Look for all generic mobj follow item hooks
+	for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
+	{
+		if (hookp->type != hook_FollowMobj)
+			continue;
+
+		if (lua_gettop(gL) == 0)
+		{
+			LUA_PushUserdata(gL, player, META_PLAYER);
+			LUA_PushUserdata(gL, mobj, META_MOBJ);
+		}
+		lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+		lua_gettable(gL, LUA_REGISTRYINDEX);
+		lua_pushvalue(gL, -3);
+		lua_pushvalue(gL, -3);
+		if (lua_pcall(gL, 2, 1, 0)) {
+			if (!hookp->error || cv_debug & DBG_LUA)
+				CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+			lua_pop(gL, 1);
+			hookp->error = true;
+			continue;
+		}
+		if (lua_toboolean(gL, -1))
+			hooked = true;
+		lua_pop(gL, 1);
+	}
+
+	for (hookp = mobjhooks[mobj->type]; hookp; hookp = hookp->next)
 	{
 		if (hookp->type != hook_FollowMobj)
 			continue;

From 2a93ddc2dd01264234f66bd7bb37d89ff340dde9 Mon Sep 17 00:00:00 2001
From: Snu <coolzach5@gmail.com>
Date: Thu, 20 Feb 2020 21:53:21 +0000
Subject: [PATCH 053/251] Change SKINCOLOR_SUPERGOLD1-5

---
 src/r_draw.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/r_draw.c b/src/r_draw.c
index 743965cfb..60ff67680 100644
--- a/src/r_draw.c
+++ b/src/r_draw.c
@@ -229,11 +229,11 @@ const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = {
 	{0x00, 0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46}, // SKINCOLOR_SUPERORANGE4
 	{0xd0, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x44, 0x45, 0x46, 0x47}, // SKINCOLOR_SUPERORANGE5
 
-	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x52, 0x53, 0x48}, // SKINCOLOR_SUPERGOLD1
-	{0x00, 0x50, 0x51, 0x52, 0x53, 0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41}, // SKINCOLOR_SUPERGOLD2
-	{0x51, 0x52, 0x53, 0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43}, // SKINCOLOR_SUPERGOLD3
-	{0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46}, // SKINCOLOR_SUPERGOLD4
-	{0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47}, // SKINCOLOR_SUPERGOLD5
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x50, 0x51, 0x52, 0x53, 0x48, 0x48, 0x48}, // SKINCOLOR_SUPERGOLD1
+	{0x00, 0x50, 0x51, 0x52, 0x53, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x41, 0x41}, // SKINCOLOR_SUPERGOLD2
+	{0x51, 0x52, 0x53, 0x53, 0x48, 0x49, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x43, 0x43}, // SKINCOLOR_SUPERGOLD3
+	{0x53, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x46, 0x46}, // SKINCOLOR_SUPERGOLD4
+	{0x48, 0x48, 0x49, 0x49, 0x49, 0x40, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x47, 0x47}, // SKINCOLOR_SUPERGOLD5
 
 	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc}, // SKINCOLOR_SUPERPERIDOT1
 	{0x00, 0x58, 0x58, 0x58, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbe, 0xbe}, // SKINCOLOR_SUPERPERIDOT2

From cce53081085b256165940e8ff38cc8d97880ae62 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Thu, 20 Feb 2020 17:18:26 -0800
Subject: [PATCH 054/251] Fix compiler warnings

---
 src/blua/liolib.c | 4 ++--
 src/d_netfil.c    | 2 +-
 src/d_netfil.h    | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/blua/liolib.c b/src/blua/liolib.c
index e1a64c8d8..378b8c86d 100644
--- a/src/blua/liolib.c
+++ b/src/blua/liolib.c
@@ -34,7 +34,6 @@
 #define FMT_FILECALLBACKID "file_callback_%d"
 
 
-static const char *const fnames[] = {"input", "output"};
 static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder
 	".bmp",
 	".cfg",
@@ -230,6 +229,7 @@ static int io_openlocal (lua_State *L) {
 	FILE **pf;
 	const char *filename = luaL_checkstring(L, 1);
 	const char *mode = luaL_optstring(L, 2, "r");
+	char *realfilename;
 	luafiletransfer_t *filetransfer;
 	int checkresult;
 
@@ -237,7 +237,7 @@ static int io_openlocal (lua_State *L) {
 	if (checkresult)
 		return checkresult;
 
-	char *realfilename = va("%s" PATHSEP "%s", luafiledir, filename);
+	realfilename = va("%s" PATHSEP "%s", luafiledir, filename);
 
 	if (client && strnicmp(filename, "client/", strlen("client/")))
 		I_Error("Access denied to %s\n"
diff --git a/src/d_netfil.c b/src/d_netfil.c
index ed81a51b1..a5d4b71e2 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -98,7 +98,7 @@ INT32 lastfilenum = -1;
 #ifdef HAVE_BLUA
 luafiletransfer_t *luafiletransfers = NULL;
 boolean waitingforluafiletransfer = false;
-char luafiledir[256] = "luafiles";
+char luafiledir[MAX_WADPATH] = "luafiles";
 #endif
 
 
diff --git a/src/d_netfil.h b/src/d_netfil.h
index 0473b5f44..13087dfb2 100644
--- a/src/d_netfil.h
+++ b/src/d_netfil.h
@@ -93,7 +93,7 @@ typedef struct luafiletransfer_s
 
 extern luafiletransfer_t *luafiletransfers;
 extern boolean waitingforluafiletransfer;
-extern char luafiledir[256];
+extern char luafiledir[MAX_WADPATH];
 
 void AddLuaFileTransfer(const char *filename, const char *mode);
 void SV_PrepareSendLuaFileToNextNode(void);

From 2df4717f18475835c5924c84624d44d2674c6aa7 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Thu, 20 Feb 2020 17:20:50 -0800
Subject: [PATCH 055/251] Fix NO_LUA compiling

---
 src/d_clisrv.c | 2 ++
 src/d_main.c   | 6 +++++-
 src/d_net.c    | 2 ++
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index f31c2bcd4..3ad8db3c7 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -3197,8 +3197,10 @@ void D_QuitNetGame(void)
 
 	// abort send/receive of files
 	CloseNetFile();
+#ifdef HAVE_BLUA
 	RemoveAllLuaFileTransfers();
 	waitingforluafiletransfer = false;
+#endif
 
 	if (server)
 	{
diff --git a/src/d_main.c b/src/d_main.c
index 715c90aa9..a54cdfc8d 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1126,8 +1126,10 @@ void D_SRB2Main(void)
 			// can't use sprintf since there is %u in savegamename
 			strcatbf(savegamename, srb2home, PATHSEP);
 
+#ifdef HAVE_BLUA
 			snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", srb2home);
-#else
+#endif
+#else/*DEFAULTDIR*/
 			snprintf(srb2home, sizeof srb2home, "%s", userhome);
 			snprintf(downloaddir, sizeof downloaddir, "%s", userhome);
 			if (dedicated)
@@ -1138,8 +1140,10 @@ void D_SRB2Main(void)
 			// can't use sprintf since there is %u in savegamename
 			strcatbf(savegamename, userhome, PATHSEP);
 
+#ifdef HAVE_BLUA
 			snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome);
 #endif
+#endif/*DEFAULTDIR*/
 		}
 
 		configfile[sizeof configfile - 1] = '\0';
diff --git a/src/d_net.c b/src/d_net.c
index ddb991235..a83d6d0ff 100644
--- a/src/d_net.c
+++ b/src/d_net.c
@@ -803,9 +803,11 @@ static const char *packettypename[NUMPACKETTYPE] =
 	"RESYNCHEND",
 	"RESYNCHGET",
 
+#ifdef HAVE_BLUA
 	"SENDINGLUAFILE",
 	"ASKLUAFILE",
 	"HASLUAFILE",
+#endif
 
 	"FILEFRAGMENT",
 	"TEXTCMD",

From ec5b88e79fcf314fd4e4190ee343709ee74f7616 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Fri, 21 Feb 2020 17:17:39 +0100
Subject: [PATCH 056/251] Fix weird comment style

---
 src/d_main.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/d_main.c b/src/d_main.c
index a54cdfc8d..2553dc8e6 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1129,7 +1129,7 @@ void D_SRB2Main(void)
 #ifdef HAVE_BLUA
 			snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", srb2home);
 #endif
-#else/*DEFAULTDIR*/
+#else // DEFAULTDIR
 			snprintf(srb2home, sizeof srb2home, "%s", userhome);
 			snprintf(downloaddir, sizeof downloaddir, "%s", userhome);
 			if (dedicated)
@@ -1143,7 +1143,7 @@ void D_SRB2Main(void)
 #ifdef HAVE_BLUA
 			snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome);
 #endif
-#endif/*DEFAULTDIR*/
+#endif // DEFAULTDIR
 		}
 
 		configfile[sizeof configfile - 1] = '\0';

From 472befd183143764218b466bbcda269aa3bb310a Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Fri, 21 Feb 2020 17:31:32 +0100
Subject: [PATCH 057/251] Replace MAX_WADPATH with plain numbers

This is not ideal either, but I would rather
not use a constant for something unrelated.
---
 src/d_netfil.c | 2 +-
 src/d_netfil.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/d_netfil.c b/src/d_netfil.c
index a5d4b71e2..ecb2229a6 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -98,7 +98,7 @@ INT32 lastfilenum = -1;
 #ifdef HAVE_BLUA
 luafiletransfer_t *luafiletransfers = NULL;
 boolean waitingforluafiletransfer = false;
-char luafiledir[MAX_WADPATH] = "luafiles";
+char luafiledir[256 + 16] = "luafiles";
 #endif
 
 
diff --git a/src/d_netfil.h b/src/d_netfil.h
index 13087dfb2..830293ca8 100644
--- a/src/d_netfil.h
+++ b/src/d_netfil.h
@@ -93,7 +93,7 @@ typedef struct luafiletransfer_s
 
 extern luafiletransfer_t *luafiletransfers;
 extern boolean waitingforluafiletransfer;
-extern char luafiledir[MAX_WADPATH];
+extern char luafiledir[256 + 16];
 
 void AddLuaFileTransfer(const char *filename, const char *mode);
 void SV_PrepareSendLuaFileToNextNode(void);

From af9164f336a65634f6908e677b47773d88f583af Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Sat, 22 Feb 2020 02:17:21 +0100
Subject: [PATCH 058/251] Improve join refusal handling

---
 src/d_clisrv.c | 81 ++++++++++++++++++++++++++++++--------------------
 src/d_clisrv.h |  3 +-
 src/m_menu.c   |  2 +-
 3 files changed, 51 insertions(+), 35 deletions(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 77118110e..ef0c0c33e 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -1289,6 +1289,37 @@ static boolean CL_SendJoin(void)
 	return HSendPacket(servernode, true, 0, sizeof (clientconfig_pak));
 }
 
+static INT32 FindRejoinerNum(SINT8 node)
+{
+	char strippednodeaddress[64];
+	const char *nodeaddress;
+	char *port;
+	INT32 i;
+
+	// Make sure there is no dead dress before proceeding to the stripping
+	if (!I_GetNodeAddress)
+		return -1;
+	nodeaddress = I_GetNodeAddress(node);
+	if (!nodeaddress)
+		return -1;
+
+	// Strip the address of its port
+	strcpy(strippednodeaddress, nodeaddress);
+	port = strchr(strippednodeaddress, ':');
+	if (port)
+		*port = '\0';
+
+	// Check if any player matches the stripped address
+	for (i = 0; i < MAXPLAYERS; i++)
+	{
+		if (playeringame[i] && playeraddress[i][0] && playernode[i] == UINT8_MAX
+		&& !strcmp(playeraddress[i], strippednodeaddress))
+			return i;
+	}
+
+	return -1;
+}
+
 static void SV_SendServerInfo(INT32 node, tic_t servertime)
 {
 	UINT8 *p;
@@ -1306,6 +1337,16 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
 
 	netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers();
 	netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value;
+
+	if (FindRejoinerNum(node) != -1)
+		netbuffer->u.serverinfo.refusereason = 0;
+	else if (!cv_allownewplayer.value)
+		netbuffer->u.serverinfo.refusereason = 1;
+	else if (D_NumPlayers() >= cv_maxplayers.value)
+		netbuffer->u.serverinfo.refusereason = 2;
+	else
+		netbuffer->u.serverinfo.refusereason = 0;
+
 	strncpy(netbuffer->u.serverinfo.gametypename, Gametype_Names[gametype],
 			sizeof netbuffer->u.serverinfo.gametypename);
 	netbuffer->u.serverinfo.modifiedgame = (UINT8)modifiedgame;
@@ -1863,12 +1904,17 @@ static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent)
 		}
 
 		// Quit here rather than downloading files and being refused later.
-		if (serverlist[i].info.numberofplayer >= serverlist[i].info.maxplayer)
+		if (serverlist[i].info.refusereason)
 		{
 			D_QuitNetGame();
 			CL_Reset();
 			D_StartTitle();
-			M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING);
+			if (serverlist[i].info.refusereason == 1)
+				M_StartMessage(M_GetText("The server is not accepting\njoins for the moment.\n\nPress ESC\n"), NULL, MM_NOTHING);
+			else if (serverlist[i].info.refusereason == 2)
+				M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING);
+			else
+				M_StartMessage(M_GetText("You can't join.\nI don't know why,\nbut you can't join.\n\nPress ESC\n"), NULL, MM_NOTHING);
 			return false;
 		}
 
@@ -3230,37 +3276,6 @@ void D_QuitNetGame(void)
 #endif
 }
 
-static INT32 FindRejoinerNum(SINT8 node)
-{
-	char strippednodeaddress[64];
-	const char *nodeaddress;
-	char *port;
-	INT32 i;
-
-	// Make sure there is no dead dress before proceeding to the stripping
-	if (!I_GetNodeAddress)
-		return -1;
-	nodeaddress = I_GetNodeAddress(node);
-	if (!nodeaddress)
-		return -1;
-
-	// Strip the address of its port
-	strcpy(strippednodeaddress, nodeaddress);
-	port = strchr(strippednodeaddress, ':');
-	if (port)
-		*port = '\0';
-
-	// Check if any player matches the stripped address
-	for (i = 0; i < MAXPLAYERS; i++)
-	{
-		if (playeringame[i] && playeraddress[i][0] && playernode[i] == UINT8_MAX
-		&& !strcmp(playeraddress[i], strippednodeaddress))
-			return i;
-	}
-
-	return -1;
-}
-
 // Adds a node to the game (player will follow at map change or at savegame....)
 static inline void SV_AddNode(INT32 node)
 {
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index df93fe31d..8cea2f00a 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -27,7 +27,7 @@ This version is independent of the mod name, and standard
 version and subversion. It should only account for the
 basic fields of the packet, and change infrequently.
 */
-#define PACKETVERSION 2
+#define PACKETVERSION 3
 
 // Network play related stuff.
 // There is a data struct that stores network
@@ -361,6 +361,7 @@ typedef struct
 	UINT8 subversion;
 	UINT8 numberofplayer;
 	UINT8 maxplayer;
+	UINT8 refusereason; // 0: joinable, 1: joins disabled, 2: full
 	char gametypename[24];
 	UINT8 modifiedgame;
 	UINT8 cheatsenabled;
diff --git a/src/m_menu.c b/src/m_menu.c
index 8b564e068..d48714c35 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -10366,7 +10366,7 @@ static void M_DrawConnectMenu(void)
 	for (i = 0; i < min(serverlistcount - serverlistpage * SERVERS_PER_PAGE, SERVERS_PER_PAGE); i++)
 	{
 		INT32 slindex = i + serverlistpage * SERVERS_PER_PAGE;
-		UINT32 globalflags = ((serverlist[slindex].info.numberofplayer >= serverlist[slindex].info.maxplayer) ? V_TRANSLUCENT : 0)
+		UINT32 globalflags = (serverlist[slindex].info.refusereason ? V_TRANSLUCENT : 0)
 			|((itemOn == FIRSTSERVERLINE+i) ? V_YELLOWMAP : 0)|V_ALLOWLOWERCASE;
 
 		V_DrawString(currentMenu->x, S_LINEY(i), globalflags, serverlist[slindex].info.servername);

From 778715f6111a1bbf7d2ae874e5490e1b2ae0dbc1 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Sat, 22 Feb 2020 02:21:27 +0100
Subject: [PATCH 059/251] Cleanup code a little

---
 src/d_clisrv.c | 4 ++--
 src/d_netcmd.c | 4 ----
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index ef0c0c33e..98eff1cd5 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -3606,7 +3606,7 @@ static void HandleConnect(SINT8 node)
 	rejoinernum = FindRejoinerNum(node);
 
 	if (bannednode && bannednode[node])
-		SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server"));
+		SV_SendRefuse(node, M_GetText("You have been banned\nfrom the server."));
 	else if (netbuffer->u.clientcfg._255 != 255 ||
 			netbuffer->u.clientcfg.packetversion != PACKETVERSION)
 		SV_SendRefuse(node, "Incompatible packet formats.");
@@ -3617,7 +3617,7 @@ static void HandleConnect(SINT8 node)
 		|| netbuffer->u.clientcfg.subversion != SUBVERSION)
 		SV_SendRefuse(node, va(M_GetText("Different SRB2 versions cannot\nplay a netgame!\n(server version %d.%d.%d)"), VERSION/100, VERSION%100, SUBVERSION));
 	else if (!cv_allownewplayer.value && node && rejoinernum == -1)
-		SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment"));
+		SV_SendRefuse(node, M_GetText("The server is not accepting\njoins for the moment."));
 	else if (D_NumPlayers() >= cv_maxplayers.value && rejoinernum == -1)
 		SV_SendRefuse(node, va(M_GetText("Maximum players reached: %d"), cv_maxplayers.value));
 	else if (netgame && netbuffer->u.clientcfg.localplayers > 1) // Hacked client?
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 623a83c47..b619621c6 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -3342,10 +3342,6 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
 	boolean kick = false;
 	boolean toomany = false;
 	INT32 i,j;
-	serverinfo_pak *dummycheck = NULL;
-
-	// Shut the compiler up.
-	(void)dummycheck;
 
 	READSTRINGN(*cp, filename, 240);
 	READMEM(*cp, md5sum, 16);

From 0f2b8b8b2cfb431d46468c5a71fad9d4d51d98c6 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Fri, 21 Feb 2020 20:04:28 -0800
Subject: [PATCH 060/251] Register servername etc. under NOMD5

This fixes crashes in the menus.
---
 src/mserv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/mserv.c b/src/mserv.c
index 4ddab05b9..c02a58f99 100644
--- a/src/mserv.c
+++ b/src/mserv.c
@@ -18,7 +18,7 @@
 
 #include <time.h>
 
-#if (defined (NOMD5) || defined (NOMSERV)) && !defined (NONET)
+#if (defined (NOMSERV)) && !defined (NONET)
 #define NONET
 #endif
 

From d19fe295e0556a49c3f5c37df1e2b379a961611e Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Sat, 22 Feb 2020 15:08:17 +0100
Subject: [PATCH 061/251] Fix buffer overrun with nodeless players

---
 src/d_clisrv.c | 27 ++++++++++++---------------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 98eff1cd5..eda6f9c67 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -2485,14 +2485,14 @@ static void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
 	if (!playeringame[playernum])
 		return;
 
-	if (server && !demoplayback)
+	if (server && !demoplayback && playernode[playernum] != UINT8_MAX)
 	{
 		INT32 node = playernode[playernum];
 		playerpernode[node]--;
 		if (playerpernode[node] <= 0)
 		{
-			nodeingame[playernode[playernum]] = false;
-			Net_CloseConnection(playernode[playernum]);
+			nodeingame[node] = false;
+			Net_CloseConnection(node);
 			ResetNode(node);
 		}
 	}
@@ -2838,16 +2838,13 @@ static void Command_Kick(void)
 		if (pn == -1 || pn == 0)
 			return;
 
-		if (server)
+		// Special case if we are trying to kick a player who is downloading the game state:
+		// trigger a timeout instead of kicking them, because a kick would only
+		// take effect after they have finished downloading
+		if (server && playernode[pn] != UINT8_MAX && sendingsavegame[playernode[pn]])
 		{
-			// Special case if we are trying to kick a player who is downloading the game state:
-			// trigger a timeout instead of kicking them, because a kick would only
-			// take effect after they have finished downloading
-			if (sendingsavegame[playernode[pn]])
-			{
-				Net_ConnectionTimeout(playernode[pn]);
-				return;
-			}
+			Net_ConnectionTimeout(playernode[pn]);
+			return;
 		}
 
 		WRITESINT8(p, pn);
@@ -2905,7 +2902,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
 
 	// Is playernum authorized to make this kick?
 	if (playernum != serverplayer && !IsPlayerAdmin(playernum)
-		&& !(playerpernode[playernode[playernum]] == 2
+		&& !(playernode[playernum] != UINT8_MAX && playerpernode[playernode[playernum]] == 2
 		&& nodetoplayer2[playernode[playernum]] == pnum))
 	{
 		// We received a kick command from someone who isn't the
@@ -3064,7 +3061,7 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
 	}
 	else if (keepbody)
 	{
-		if (server && !demoplayback)
+		if (server && !demoplayback && playernode[pnum] != UINT8_MAX)
 		{
 			INT32 node = playernode[pnum];
 			playerpernode[node]--;
@@ -4956,7 +4953,7 @@ void NetUpdate(void)
 			PingUpdate();
 		// update node latency values so we can take an average later.
 		for (i = 0; i < MAXPLAYERS; i++)
-			if (playeringame[i])
+			if (playeringame[i] && playernode[i] != UINT8_MAX)
 				realpingtable[i] += G_TicsToMilliseconds(GetLag(playernode[i]));
 		pingmeasurecount++;
 	}

From 4c00e3309647d6ee4a7f370b514f72ef1cc57027 Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Sat, 22 Feb 2020 21:14:05 -0300
Subject: [PATCH 062/251] Oopsie

---
 src/p_user.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/p_user.c b/src/p_user.c
index 880d932af..9417f752d 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -384,6 +384,9 @@ void P_GiveFinishFlags(player_t *player)
 	if (!player->mo)
 		return;
 
+	if !(netgame||multiplayer)
+		return;
+
 	for (i = 0; i < 3; i++)
 	{
 		angle_t fa = (angle >> ANGLETOFINESHIFT) & FINEMASK;

From ff8a62819b6de93b32d746b6f4cb3c737b7041c2 Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Sat, 22 Feb 2020 22:36:44 -0300
Subject: [PATCH 063/251] Oopsie 2

---
 src/p_user.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_user.c b/src/p_user.c
index 9417f752d..9167d5345 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -384,7 +384,7 @@ void P_GiveFinishFlags(player_t *player)
 	if (!player->mo)
 		return;
 
-	if !(netgame||multiplayer)
+	if (!(netgame||multiplayer))
 		return;
 
 	for (i = 0; i < 3; i++)

From 0362f53e9b9561a6cfb7408301ab80f88de9dcc8 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sun, 23 Feb 2020 12:14:52 -0300
Subject: [PATCH 064/251] Fix incorrect newdisplayplayer in forced
 ViewpointSwitch

---
 src/d_clisrv.c | 2 +-
 src/d_netcmd.c | 6 +++---
 src/g_game.c   | 2 +-
 src/p_user.c   | 6 +++---
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index f5fea366f..a4e1ba423 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -2513,7 +2513,7 @@ static void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
 #ifdef HAVE_BLUA
 		// Call ViewpointSwitch hooks here.
 		// The viewpoint was forcibly changed.
-		LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer], true);
+		LUAh_ViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true);
 #endif
 		displayplayer = consoleplayer;
 	}
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index c25929929..95cb9291f 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -2843,7 +2843,7 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
 		// Call ViewpointSwitch hooks here.
 		// The viewpoint was forcibly changed.
 		if (displayplayer != consoleplayer) // You're already viewing yourself. No big deal.
-			LUAh_ViewpointSwitch(&players[playernum], &players[displayplayer], true);
+			LUAh_ViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true);
 #endif
 		displayplayer = consoleplayer;
 	}
@@ -3753,11 +3753,11 @@ static void ExitMove_OnChange(void)
 			{
 				if (players[i].mo->target && players[i].mo->target->type == MT_SIGN)
 					P_SetTarget(&players[i].mo->target, NULL);
-				
+
 				if (players[i].pflags & PF_FINISHED)
 					P_GiveFinishFlags(&players[i]);
 			}
-			
+
 		CONS_Printf(M_GetText("Players can now move after completing the level.\n"));
 	}
 	else
diff --git a/src/g_game.c b/src/g_game.c
index 08192bfb8..3eeb2fa2b 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -1718,7 +1718,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 #ifdef HAVE_BLUA
 		// Call ViewpointSwitch hooks here.
 		// The viewpoint was forcibly changed.
-		LUAh_ViewpointSwitch(player, &players[displayplayer], true);
+		LUAh_ViewpointSwitch(player, &players[consoleplayer], true);
 #endif
 		displayplayer = consoleplayer;
 	}
diff --git a/src/p_user.c b/src/p_user.c
index 880d932af..9b0be6e53 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -392,7 +392,7 @@ void P_GiveFinishFlags(player_t *player)
 		mobj_t* flag = P_SpawnMobjFromMobj(player->mo, xoffs, yoffs, 0, MT_FINISHFLAG);
 		flag->angle = angle;
 		angle += FixedAngle(120*FRACUNIT);
-		
+
 		P_SetTarget(&flag->target, player->mo);
 	}
 }
@@ -10650,7 +10650,7 @@ boolean P_SpectatorJoinGame(player_t *player)
 #ifdef HAVE_BLUA
 			// Call ViewpointSwitch hooks here.
 			// The viewpoint was forcibly changed.
-			LUAh_ViewpointSwitch(player, &players[displayplayer], true);
+			LUAh_ViewpointSwitch(player, &players[consoleplayer], true);
 #endif
 			displayplayer = consoleplayer;
 		}
@@ -10699,7 +10699,7 @@ boolean P_SpectatorJoinGame(player_t *player)
 #ifdef HAVE_BLUA
 				// Call ViewpointSwitch hooks here.
 				// The viewpoint was forcibly changed.
-				LUAh_ViewpointSwitch(player, &players[displayplayer], true);
+				LUAh_ViewpointSwitch(player, &players[consoleplayer], true);
 #endif
 				displayplayer = consoleplayer;
 			}

From 283bb52e7d381a85bd8026a9fabf8e7daf150bdf Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Sun, 23 Feb 2020 12:45:43 -0600
Subject: [PATCH 065/251] Disable NOHUD/INLEVEL checks on Lua sound functions

None of these are implicitly sync-safe anyway, and most have
no need to be walled off from HUD code or intermission thinkers.
---
 src/lua_baselib.c | 36 +++++++++++++++++-------------------
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 03f142446..e41f81674 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -1675,8 +1675,8 @@ static int lib_pPlayVictorySound(lua_State *L)
 static int lib_pPlayLivesJingle(lua_State *L)
 {
 	player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
-	NOHUD
-	INLEVEL
+	//NOHUD
+	//INLEVEL
 	if (!player)
 		return LUA_ErrInvalid(L, "player_t");
 	P_PlayLivesJingle(player);
@@ -2342,7 +2342,7 @@ static int lib_sStartSound(lua_State *L)
 	const void *origin = NULL;
 	sfxenum_t sound_id = luaL_checkinteger(L, 2);
 	player_t *player = NULL;
-	//NOHUD // kys @whoever did this.
+	//NOHUD
 	if (sound_id >= NUMSFX)
 		return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
 	if (!lua_isnil(L, 1))
@@ -2373,7 +2373,7 @@ static int lib_sStartSoundAtVolume(lua_State *L)
 	sfxenum_t sound_id = luaL_checkinteger(L, 2);
 	INT32 volume = (INT32)luaL_checkinteger(L, 3);
 	player_t *player = NULL;
-	NOHUD
+	//NOHUD
 
 	if (!lua_isnil(L, 1))
 	{
@@ -2397,7 +2397,7 @@ static int lib_sStartSoundAtVolume(lua_State *L)
 static int lib_sStopSound(lua_State *L)
 {
 	void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	NOHUD
+	//NOHUD
 	if (!origin)
 		return LUA_ErrInvalid(L, "mobj_t");
 	S_StopSound(origin);
@@ -2414,7 +2414,7 @@ static int lib_sChangeMusic(lua_State *L)
 	boolean looping;
 	player_t *player = NULL;
 	UINT16 music_flags = 0;
-	NOHUD
+	//NOHUD
 
 	if (lua_isnumber(L, 1))
 	{
@@ -2443,7 +2443,7 @@ static int lib_sChangeMusic(lua_State *L)
 	boolean looping = (boolean)lua_opttrueboolean(L, 2);
 	player_t *player = NULL;
 	UINT16 music_flags = 0;
-	NOHUD
+	//NOHUD
 
 #endif
 	if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
@@ -2474,7 +2474,7 @@ static int lib_sSpeedMusic(lua_State *L)
 	fixed_t fixedspeed = luaL_checkfixed(L, 1);
 	float speed = FIXED_TO_FLOAT(fixedspeed);
 	player_t *player = NULL;
-	NOHUD
+	//NOHUD
 	if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
 	{
 		player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
@@ -2489,7 +2489,7 @@ static int lib_sSpeedMusic(lua_State *L)
 static int lib_sStopMusic(lua_State *L)
 {
 	player_t *player = NULL;
-	NOHUD
+	//NOHUD
 	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
 	{
 		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@@ -2505,7 +2505,7 @@ static int lib_sSetInternalMusicVolume(lua_State *L)
 {
 	UINT32 volume = (UINT32)luaL_checkinteger(L, 1);
 	player_t *player = NULL;
-	NOHUD
+	//NOHUD
 	if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
 	{
 		player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
@@ -2525,7 +2525,7 @@ static int lib_sSetInternalMusicVolume(lua_State *L)
 static int lib_sStopFadingMusic(lua_State *L)
 {
 	player_t *player = NULL;
-	NOHUD
+	//NOHUD
 	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
 	{
 		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@@ -2548,7 +2548,7 @@ static int lib_sFadeMusic(lua_State *L)
 	UINT32 ms;
 	INT32 source_volume;
 	player_t *player = NULL;
-	NOHUD
+	//NOHUD
 	if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
 	{
 		player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
@@ -2576,8 +2576,6 @@ static int lib_sFadeMusic(lua_State *L)
 		ms = (UINT32)luaL_checkinteger(L, 3);
 	}
 
-	NOHUD
-
 	if (!player || P_IsLocalPlayer(player))
 		lua_pushboolean(L, S_FadeMusicFromVolume(target_volume, source_volume, ms));
 	else
@@ -2589,7 +2587,7 @@ static int lib_sFadeOutStopMusic(lua_State *L)
 {
 	UINT32 ms = (UINT32)luaL_checkinteger(L, 1);
 	player_t *player = NULL;
-	NOHUD
+	//NOHUD
 	if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
 	{
 		player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
@@ -2608,7 +2606,7 @@ static int lib_sFadeOutStopMusic(lua_State *L)
 static int lib_sOriginPlaying(lua_State *L)
 {
 	void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	NOHUD
+	//NOHUD
 	INLEVEL
 	if (!origin)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -2619,7 +2617,7 @@ static int lib_sOriginPlaying(lua_State *L)
 static int lib_sIdPlaying(lua_State *L)
 {
 	sfxenum_t id = luaL_checkinteger(L, 1);
-	NOHUD
+	//NOHUD
 	if (id >= NUMSFX)
 		return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1);
 	lua_pushboolean(L, S_IdPlaying(id));
@@ -2630,7 +2628,7 @@ static int lib_sSoundPlaying(lua_State *L)
 {
 	void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
 	sfxenum_t id = luaL_checkinteger(L, 2);
-	NOHUD
+	//NOHUD
 	INLEVEL
 	if (!origin)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -2648,7 +2646,7 @@ static int lib_sStartMusicCaption(lua_State *L)
 	const char *caption = luaL_checkstring(L, 1);
 	UINT16 lifespan = (UINT16)luaL_checkinteger(L, 2);
 	//HUDSAFE
-	INLEVEL
+	//INLEVEL
 
 	if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
 	{

From 40488096c014153680d00a11d2707381930c9b2d Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Sun, 23 Feb 2020 15:40:59 -0600
Subject: [PATCH 066/251] Make P_PlayLivesJingle player optional in Lua

---
 src/lua_baselib.c | 10 +++++++---
 src/p_user.c      |  4 ++--
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index e41f81674..8344fca91 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -1674,11 +1674,15 @@ static int lib_pPlayVictorySound(lua_State *L)
 
 static int lib_pPlayLivesJingle(lua_State *L)
 {
-	player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+	player_t *player = NULL;
 	//NOHUD
 	//INLEVEL
-	if (!player)
-		return LUA_ErrInvalid(L, "player_t");
+	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
+	{
+		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+	}
 	P_PlayLivesJingle(player);
 	return 0;
 }
diff --git a/src/p_user.c b/src/p_user.c
index 880d932af..2dcfd872c 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -392,7 +392,7 @@ void P_GiveFinishFlags(player_t *player)
 		mobj_t* flag = P_SpawnMobjFromMobj(player->mo, xoffs, yoffs, 0, MT_FINISHFLAG);
 		flag->angle = angle;
 		angle += FixedAngle(120*FRACUNIT);
-		
+
 		P_SetTarget(&flag->target, player->mo);
 	}
 }
@@ -1533,7 +1533,7 @@ void P_PlayJingle(player_t *player, jingletype_t jingletype)
 void P_PlayJingleMusic(player_t *player, const char *musname, UINT16 musflags, boolean looping, UINT16 status)
 {
 	// If gamestate != GS_LEVEL, always play the jingle (1-up intermission)
-	if (gamestate == GS_LEVEL && !P_IsLocalPlayer(player))
+	if (gamestate == GS_LEVEL && player && !P_IsLocalPlayer(player))
 		return;
 
 	S_RetainMusic(musname, musflags, looping, 0, status);

From 94738bfd2d18d79698f60b40b04c6ceaad846529 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sun, 23 Feb 2020 19:28:16 -0300
Subject: [PATCH 067/251] Don't get chosen as the tagger if you're a spectator

---
 src/p_setup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index 7b4c6773b..eee90e03d 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -3096,7 +3096,7 @@ static void P_InitTagGametype(void)
 	//Also, you'd never have to loop through all 32 players slots to find anything ever again.
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
-		if (playeringame[i] && !(players[i].spectator && players[i].quittime))
+		if (playeringame[i] && !(players[i].spectator || players[i].quittime))
 		{
 			playersactive[realnumplayers] = i; //stores the player's node in the array.
 			realnumplayers++;

From c5f386881988c51b6e7f752516ac55cc1706a815 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Sun, 23 Feb 2020 17:19:18 -0600
Subject: [PATCH 068/251] Expose P_PlayJingle/Music() to Lua

---
 src/lua_baselib.c | 55 +++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 2 deletions(-)

diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 8344fca91..c360007de 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -1040,11 +1040,60 @@ static int lib_pSetObjectMomZ(lua_State *L)
 	return 0;
 }
 
+static int lib_pPlayJingle(lua_State *L)
+{
+	player_t *player = NULL;
+	jingletype_t jingletype = (jingletype_t)luaL_checkinteger(L, 2);
+	//NOHUD
+	//INLEVEL
+	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
+	{
+		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+	}
+	if (jingletype >= NUMJINGLES)
+		return luaL_error(L, "jingletype %d out of range (0 - %d)", jingletype, NUMJINGLES-1);
+	P_PlayJingle(player, jingletype);
+	return 0;
+}
+
+static int lib_pPlayJingleMusic(lua_State *L)
+{
+	player_t *player = NULL;
+	const char *musnamearg = luaL_checkstring(L, 2);
+	char musname[7], *p = musname;
+	UINT16 musflags = luaL_optinteger(L, 3, 0);
+	boolean looping = lua_opttrueboolean(L, 4);
+	jingletype_t jingletype = (jingletype_t)luaL_optinteger(L, 5, JT_OTHER);
+	//NOHUD
+	//INLEVEL
+	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
+	{
+		player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+		if (!player)
+			return LUA_ErrInvalid(L, "player_t");
+	}
+	if (jingletype >= NUMJINGLES)
+		return luaL_error(L, "jingletype %d out of range (0 - %d)", jingletype, NUMJINGLES-1);
+
+	musname[6] = '\0';
+	strncpy(musname, musnamearg, 6);
+
+	while (*p) {
+		*p = tolower(*p);
+		++p;
+	}
+
+	P_PlayJingleMusic(player, musname, musflags, looping, jingletype);
+	return 0;
+}
+
 static int lib_pRestoreMusic(lua_State *L)
 {
 	player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
-	NOHUD
-	INLEVEL
+	//NOHUD
+	//INLEVEL
 	if (!player)
 		return LUA_ErrInvalid(L, "player_t");
 	if (P_IsLocalPlayer(player))
@@ -3071,6 +3120,8 @@ static luaL_Reg lib[] = {
 	{"P_InSpaceSector",lib_pInSpaceSector},
 	{"P_InQuicksand",lib_pInQuicksand},
 	{"P_SetObjectMomZ",lib_pSetObjectMomZ},
+	{"P_PlayJingle",lib_pPlayJingle},
+	{"P_PlayJingleMusic",lib_pPlayJingleMusic},
 	{"P_RestoreMusic",lib_pRestoreMusic},
 	{"P_SpawnShieldOrb",lib_pSpawnShieldOrb},
 	{"P_SpawnGhostMobj",lib_pSpawnGhostMobj},

From f2c968dea84ee76db8e8e38327427675c07fd8e9 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Sun, 23 Feb 2020 17:20:44 -0600
Subject: [PATCH 069/251] Add JingleStatus hook for carrying custom jingle
 tunes

The extra argument is the music name, as passed into
P_PlayJingleMusic(player, musname), to run the hook for, optional.
Arguments are (player, musname) - the latter to allow global hooks
that still differentiate between different tracks.
---
 src/lua_hook.h    |  2 ++
 src/lua_hooklib.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++-
 src/p_local.h     |  2 +-
 src/p_user.c      |  7 +++++--
 src/s_sound.c     |  2 +-
 5 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/src/lua_hook.h b/src/lua_hook.h
index 265700e4f..ea11d0236 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -58,6 +58,7 @@ enum hook {
 	hook_ViewpointSwitch,
 	hook_SeenPlayer,
 	hook_PlayerThink,
+	hook_JingleStatus,
 
 	hook_MAX // last hook
 };
@@ -110,5 +111,6 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean
 boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK
 #endif
 #define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
+boolean LUAh_JingleStatus(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing
 
 #endif
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index efed9adb7..c56336fca 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -69,6 +69,7 @@ const char *const hookNames[hook_MAX+1] = {
 	"ViewpointSwitch",
 	"SeenPlayer",
 	"PlayerThink",
+	"JingleStatus",
 	NULL
 };
 
@@ -80,7 +81,7 @@ struct hook_s
 	UINT16 id;
 	union {
 		mobjtype_t mt;
-		char *skinname;
+		char *skinname; // also used as musname for JingleStatus... I'm lazy
 		char *funcname;
 	} s;
 	boolean error;
@@ -148,6 +149,7 @@ static int lib_addHook(lua_State *L)
 		luaL_argcheck(L, hook.s.mt < NUMMOBJTYPES, 2, "invalid mobjtype_t");
 		break;
 	case hook_BotAI:
+	case hook_JingleStatus:
 		hook.s.skinname = NULL;
 		if (lua_isstring(L, 2))
 		{ // lowercase copy
@@ -1632,4 +1634,49 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend)
 }
 #endif // SEENAMES
 
+boolean LUAh_JingleStatus(player_t *player, const char *musname)
+{
+	hook_p hookp;
+	boolean keepplaying = false;
+	if (!gL || !(hooksAvailable[hook_JingleStatus/8] & (1<<(hook_JingleStatus%8))))
+		return true;
+
+	lua_settop(gL, 0);
+	hud_running = true; // local hook
+
+	for (hookp = roothook; hookp; hookp = hookp->next)
+	{
+		if (hookp->type == hook_JingleStatus) CONS_Printf("jingle status hook for %s vs %s\n", hookp->s.skinname, musname);
+
+		if (hookp->type != hook_JingleStatus
+			|| (hookp->s.skinname && strcmp(hookp->s.skinname, musname)))
+			continue;
+
+		if (lua_gettop(gL) == 0)
+		{
+			LUA_PushUserdata(gL, player, META_PLAYER);
+			lua_pushstring(gL, musname);
+		}
+		lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+		lua_gettable(gL, LUA_REGISTRYINDEX);
+		lua_pushvalue(gL, -3);
+		lua_pushvalue(gL, -3);
+		if (lua_pcall(gL, 2, 1, 0)) {
+			if (!hookp->error || cv_debug & DBG_LUA)
+				CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+			lua_pop(gL, 1);
+			hookp->error = true;
+			continue;
+		}
+		if (!lua_isnil(gL, -1) && lua_toboolean(gL, -1))
+			keepplaying = true; // Keep playing this boolean
+		lua_pop(gL, 1);
+	}
+
+	lua_settop(gL, 0);
+	hud_running = false;
+
+	return keepplaying;
+}
+
 #endif
diff --git a/src/p_local.h b/src/p_local.h
index 5e27379a7..99c465f9b 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -250,7 +250,7 @@ extern jingle_t jingleinfo[NUMJINGLES];
 #define JINGLEPOSTFADE 1000
 
 void P_PlayJingle(player_t *player, jingletype_t jingletype);
-boolean P_EvaluateMusicStatus(UINT16 status);
+boolean P_EvaluateMusicStatus(UINT16 status, const char *musname);
 void P_PlayJingleMusic(player_t *player, const char *musname, UINT16 musflags, boolean looping, UINT16 status);
 
 //
diff --git a/src/p_user.c b/src/p_user.c
index 2dcfd872c..ab85897a5 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -1541,7 +1541,7 @@ void P_PlayJingleMusic(player_t *player, const char *musname, UINT16 musflags, b
 	S_ChangeMusicInternal(musname, looping);
 }
 
-boolean P_EvaluateMusicStatus(UINT16 status)
+boolean P_EvaluateMusicStatus(UINT16 status, const char *musname)
 {
 	// \todo lua hook
 	int i;
@@ -1598,8 +1598,11 @@ boolean P_EvaluateMusicStatus(UINT16 status)
 				result = (players[i].nightstime && players[i].nightstime <= 10*TICRATE);
 				break;
 
-			case JT_NONE:   // Null state
 			case JT_OTHER:  // Other state
+				result = LUAh_JingleStatus(&players[i], musname);
+				break;
+
+			case JT_NONE:   // Null state
 			case JT_MASTER: // Main level music
 			default:
 				result = true;
diff --git a/src/s_sound.c b/src/s_sound.c
index 8193fdb9b..6507ffc02 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -2045,7 +2045,7 @@ static musicstack_t *S_GetMusicStackEntry(UINT16 status, boolean fromfirst, INT1
 
 		if (!status || mst->status == status)
 		{
-			if (P_EvaluateMusicStatus(mst->status))
+			if (P_EvaluateMusicStatus(mst->status, mst->musname))
 			{
 				if (!S_MusicExists(mst->musname, !midi_disabled, !digital_disabled)) // paranoia
 					S_RemoveMusicStackEntry(mst); // then continue

From 352029fd76805029e9f8bea5d92fc307cc5e6d68 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Sun, 23 Feb 2020 17:58:32 -0600
Subject: [PATCH 070/251] Add music position functions to Lua

---
 src/lua_baselib.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index c360007de..b6fa1b7aa 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -2656,6 +2656,25 @@ static int lib_sFadeOutStopMusic(lua_State *L)
 	return 1;
 }
 
+static int lib_sGetMusicLength(lua_State *L)
+{
+	lua_pushinteger(L, S_GetMusicLength());
+	return 1;
+}
+
+static int lib_sGetMusicPosition(lua_State *L)
+{
+	lua_pushinteger(L, S_GetMusicPosition());
+	return 1;
+}
+
+static int lib_sSetMusicPosition(lua_State *L)
+{
+	UINT32 pos = (UINT32)luaL_checkinteger(L, 1);
+	lua_pushboolean(L, S_SetMusicPosition(pos));
+	return 1;
+}
+
 static int lib_sOriginPlaying(lua_State *L)
 {
 	void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@@ -3242,6 +3261,9 @@ static luaL_Reg lib[] = {
 	{"S_StopFadingMusic",lib_sStopFadingMusic},
 	{"S_FadeMusic",lib_sFadeMusic},
 	{"S_FadeOutStopMusic",lib_sFadeOutStopMusic},
+	{"S_GetMusicLength",lib_sGetMusicLength},
+	{"S_GetMusicPosition",lib_sGetMusicPosition},
+	{"S_SetMusicPosition",lib_sSetMusicPosition},
 	{"S_OriginPlaying",lib_sOriginPlaying},
 	{"S_IdPlaying",lib_sIdPlaying},
 	{"S_SoundPlaying",lib_sSoundPlaying},

From d1dcdf88c7ad407f43f0132e986ba5f2844903ca Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Sun, 23 Feb 2020 18:44:22 -0600
Subject: [PATCH 071/251] Fix MD2 rollangle in reverse gravity

---
 src/hardware/hw_md2.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 5c3cd40a6..c9b78bc79 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -1478,7 +1478,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
 
 			// rotation pivot
 			p.centerx = FIXED_TO_FLOAT(spr->mobj->radius/2);
-			p.centery = FIXED_TO_FLOAT(spr->mobj->height/2);
+			p.centery = FIXED_TO_FLOAT(spr->mobj->height/(flip ? -2 : 2));
 
 			// rotation axis
 			if (sprinfo->available)
@@ -1490,6 +1490,9 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
 				p.rollflip = 1;
 			else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left
 				p.rollflip = -1;
+
+			if (flip)
+				p.rollflip *= -1;
 		}
 
 		p.anglex = 0.0f;

From 1848ce4b9785ba044496c92fb8f1f8594804c369 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Mon, 24 Feb 2020 10:02:36 -0600
Subject: [PATCH 072/251] Skip empty gametypes in level select menu

---
 src/m_menu.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index 945ce3de0..b39fcc2bf 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -5045,6 +5045,17 @@ static boolean M_SetNextMapOnPlatter(void)
 }
 #endif
 
+static boolean M_GametypeHasLevels(INT32 gt)
+{
+	INT32 mapnum;
+
+	for (mapnum = 0; mapnum < NUMMAPS; mapnum++)
+		if (M_CanShowLevelOnPlatter(mapnum, gt))
+			return true;
+
+	return false;
+}
+
 static INT32 M_CountRowsToShowOnPlatter(INT32 gt)
 {
 	INT32 mapnum = 0, prevmapnum = 0, col = 0, rows = 0;
@@ -5362,7 +5373,9 @@ static void M_HandleLevelPlatter(INT32 choice)
 		case KEY_RIGHTARROW:
 			if (levellistmode == LLM_CREATESERVER && !lsrow)
 			{
-				CV_AddValue(&cv_newgametype, 1);
+				do
+					CV_AddValue(&cv_newgametype, 1);
+				while (!M_GametypeHasLevels(cv_newgametype.value));
 				S_StartSound(NULL,sfx_menu1);
 				lscol = 0;
 
@@ -5391,7 +5404,9 @@ static void M_HandleLevelPlatter(INT32 choice)
 		case KEY_LEFTARROW:
 			if (levellistmode == LLM_CREATESERVER && !lsrow)
 			{
-				CV_AddValue(&cv_newgametype, -1);
+				do
+					CV_AddValue(&cv_newgametype, -1);
+				while (!M_GametypeHasLevels(cv_newgametype.value));
 				S_StartSound(NULL,sfx_menu1);
 				lscol = 0;
 

From 0df094021e35e4304e0e7b544cab1c2f5870e416 Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Mon, 24 Feb 2020 17:31:30 +0100
Subject: [PATCH 073/251] Allow emblem hints (and radar) in record attack.

---
 src/m_menu.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index 403d3a036..622d740e2 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -521,6 +521,8 @@ static menuitem_t MISC_AddonsMenu[] =
 // ---------------------------------
 static menuitem_t MAPauseMenu[] =
 {
+	{IT_CALL | IT_STRING,    NULL, "Emblem Hints...",      M_EmblemHints,         32},
+
 	{IT_CALL | IT_STRING,    NULL, "Continue",             M_SelectableClearMenus,48},
 	{IT_CALL | IT_STRING,    NULL, "Retry",                M_ModeAttackRetry,     56},
 	{IT_CALL | IT_STRING,    NULL, "Abort",                M_ModeAttackEndGame,   64},
@@ -528,6 +530,7 @@ static menuitem_t MAPauseMenu[] =
 
 typedef enum
 {
+	mapause_hints,
 	mapause_continue,
 	mapause_retry,
 	mapause_abort
@@ -729,9 +732,9 @@ static menuitem_t SR_SoundTestMenu[] =
 
 static menuitem_t SR_EmblemHintMenu[] =
 {
-	{IT_STRING | IT_ARROWS,       NULL, "Page", M_HandleEmblemHints, 10},
-	{IT_STRING|IT_CVAR,         NULL, "Emblem Radar", &cv_itemfinder, 20},
-	{IT_WHITESTRING|IT_SUBMENU, NULL, "Back",         &SPauseDef,     30}
+	{IT_STRING | IT_ARROWS,  NULL, "Page",    M_HandleEmblemHints, 10},
+	{IT_STRING|IT_CVAR,      NULL, "Emblem Radar", &cv_itemfinder, 20},
+	{IT_WHITESTRING|IT_CALL, NULL, "Back",         M_GoBack,       30}
 };
 
 // --------------------------------
@@ -7266,6 +7269,7 @@ static void M_EmblemHints(INT32 choice)
 	SR_EmblemHintMenu[0].status = (local > NUMHINTS*2) ? (IT_STRING | IT_ARROWS) : (IT_DISABLED);
 	SR_EmblemHintMenu[1].status = (M_SecretUnlocked(SECRET_ITEMFINDER)) ? (IT_CVAR|IT_STRING) : (IT_SECRET);
 	hintpage = 1;
+	SR_EmblemHintDef.prevMenu = currentMenu;
 	M_SetupNextMenu(&SR_EmblemHintDef);
 	itemOn = 2; // always start on back.
 }

From 1f8dbd1b8c64dd51736679c195c2b258e69a78e8 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Mon, 24 Feb 2020 11:44:27 -0600
Subject: [PATCH 074/251] Allow using lump names in ExecCfg

---
 src/dehacked.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index dea0289b9..38330606a 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -3889,7 +3889,26 @@ static void readmaincfg(MYFILE *f)
 			value = atoi(word2); // used for numerical settings
 
 			if (fastcmp(word, "EXECCFG"))
-				COM_BufAddText(va("exec %s\n", word2));
+			{
+				if (strchr(word2, '.'))
+					COM_BufAddText(va("exec %s\n", word2));
+				else
+				{
+					lumpnum_t lumpnum;
+					char newname[9];
+
+					strncpy(newname, word2, 8);
+
+					newname[8] = '\0';
+
+					lumpnum = W_CheckNumForName(newname);
+
+					if (lumpnum == LUMPERROR || W_LumpLength(lumpnum) == 0)
+						CONS_Debug(DBG_SETUP, "SOC Error: script lump %s not found/not valid.\n", newname);
+					else
+						COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE));
+				}
+			}
 
 			else if (fastcmp(word, "SPSTAGE_START"))
 			{
@@ -7477,7 +7496,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 
 	// Got Flag Sign
 	"S_GOTFLAG",
-	
+
 	// Finish flag
 	"S_FINISHFLAG",
 

From f8408f3c99c515efac228d33f689aa77bd3b2946 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Mon, 24 Feb 2020 11:44:45 -0600
Subject: [PATCH 075/251] Fix ExecCfg not working on files added via command
 line

---
 src/d_main.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/d_main.c b/src/d_main.c
index 904ab3bf1..1af7857ee 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -1152,6 +1152,12 @@ void D_SRB2Main(void)
 	if (M_CheckParm("-password") && M_IsNextParm())
 		D_SetPassword(M_GetNextParm());
 
+	CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n");
+	Z_Init();
+
+	// Do this up here so that WADs loaded through the command line can use ExecCfg
+	COM_Init();
+
 	// add any files specified on the command line with -file wadfile
 	// to the wad list
 	if (!(M_CheckParm("-connect") && !M_CheckParm("-server")))
@@ -1179,9 +1185,6 @@ void D_SRB2Main(void)
 	if (M_CheckParm("-server") || dedicated)
 		netgame = server = true;
 
-	CONS_Printf("Z_Init(): Init zone memory allocation daemon. \n");
-	Z_Init();
-
 	// adapt tables to SRB2's needs, including extra slots for dehacked file support
 	P_PatchInfoTables();
 
@@ -1253,7 +1256,6 @@ void D_SRB2Main(void)
 	CONS_Printf("HU_Init(): Setting up heads up display.\n");
 	HU_Init();
 
-	COM_Init();
 	CON_Init();
 
 	D_RegisterServerCommands();

From b66be478d991bb3038bb28b892ce7b059b235595 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Mon, 24 Feb 2020 11:45:22 -0600
Subject: [PATCH 076/251] Increase COM_BUF_SIZE

The config file is starting to get close to the old max,
so this should be enough headroom for a while...
---
 src/command.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/command.c b/src/command.c
index d1eea6052..abe6bcedf 100644
--- a/src/command.c
+++ b/src/command.c
@@ -80,7 +80,7 @@ static boolean joyaxis2_default = false;
 static INT32 joyaxis_count = 0;
 static INT32 joyaxis2_count = 0;
 
-#define COM_BUF_SIZE 8192 // command buffer size
+#define COM_BUF_SIZE (32<<10) // command buffer size
 #define MAX_ALIAS_RECURSION 100 // max recursion allowed for aliases
 
 static INT32 com_wait; // one command per frame (for cmd sequences)

From ce801e1076484ba85e9c8e5ae9c02a9c2b1df8b0 Mon Sep 17 00:00:00 2001
From: Steel Titanium <steeltitanium1@gmail.com>
Date: Mon, 24 Feb 2020 16:57:56 -0500
Subject: [PATCH 077/251] Fix new skin colors using default chat color

---
 src/hu_stuff.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 74b68ce69..98f3ca5a9 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -787,10 +787,12 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
 				case SKINCOLOR_RED:
 				case SKINCOLOR_CRIMSON:
 				case SKINCOLOR_FLAME:
+				case SKINCOLOR_KETCHUP:
 					cstart = "\x85"; // V_REDMAP
 					break;
 				case SKINCOLOR_YOGURT:
 				case SKINCOLOR_BROWN:
+				case SKINCOLOR_BRONZE:
 				case SKINCOLOR_TAN:
 				case SKINCOLOR_BEIGE:
 				case SKINCOLOR_QUAIL:
@@ -818,6 +820,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
 					cstart = "\x8e"; // V_ROSYMAP
 					break;
 				case SKINCOLOR_SUNSET:
+				case SKINCOLOR_COPPER:
 				case SKINCOLOR_APRICOT:
 				case SKINCOLOR_ORANGE:
 				case SKINCOLOR_RUST:
@@ -831,6 +834,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
 					break;
 				case SKINCOLOR_LIME:
 				case SKINCOLOR_PERIDOT:
+				case SKINCOLOR_APPLE:
 					cstart = "\x8b"; // V_PERIDOTMAP
 					break;
 				case SKINCOLOR_SEAFOAM:
@@ -851,12 +855,14 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
 				case SKINCOLOR_BLUE:
 				case SKINCOLOR_COBALT:
 				case SKINCOLOR_DUSK:
+				case SKINCOLOR_BLUEBELL:
 					cstart = "\x84"; // V_BLUEMAP
 					break;
 				case SKINCOLOR_BUBBLEGUM:
 				case SKINCOLOR_MAGENTA:
 				case SKINCOLOR_NEON:
 				case SKINCOLOR_VIOLET:
+				case SKINCOLOR_RASPBERRY:
 					cstart = "\x81"; // V_MAGENTAMAP
 					break;
 			}

From fe931555783c4a1d552a041faf0ae34ad0d7d532 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Mon, 24 Feb 2020 20:03:08 -0300
Subject: [PATCH 078/251] Fix Amy cameo's love hearts crashing the Software
 renderer due to invalid translucency tables

---
 src/p_mobj.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/p_mobj.c b/src/p_mobj.c
index 2bb2cc028..faee245d3 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -8001,8 +8001,9 @@ static void P_MobjSceneryThink(mobj_t *mobj)
 		}
 		if (mobj->fuse < 0)
 			return;
-		if ((--mobj->fuse) < 6)
+		if (mobj->fuse < 6)
 			mobj->frame = (mobj->frame & ~FF_TRANSMASK) | ((10 - (mobj->fuse*2)) << (FF_TRANSSHIFT));
+		mobj->fuse--;
 	}
 	break;
 	case MT_FINISHFLAG:
@@ -11594,7 +11595,7 @@ void P_AfterPlayerSpawn(INT32 playernum)
 
 	if (CheckForReverseGravity)
 		P_CheckGravity(mobj, false);
-	
+
 	if (p->pflags & PF_FINISHED)
 		P_GiveFinishFlags(p);
 }

From 3d7cd29edaf34d7abf7a5d19f14d327fdd5c69bf Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Tue, 25 Feb 2020 22:30:34 -0300
Subject: [PATCH 079/251] Fix TYPEOFLEVEL options not having enough bits for
 TOL_ flags

---
 src/dehacked.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index dea0289b9..329cf8788 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1249,7 +1249,7 @@ static void readgametype(MYFILE *f, char *gtname)
 					newgttol = (UINT32)i;
 				else
 				{
-					UINT16 tol = 0;
+					UINT32 tol = 0;
 					tmp = strtok(word2,",");
 					do {
 						for (i = 0; TYPEOFLEVEL[i].name; i++)
@@ -1591,7 +1591,7 @@ static void readlevelheader(MYFILE *f, INT32 num)
 					mapheaderinfo[num-1]->typeoflevel = (UINT32)i;
 				else
 				{
-					UINT16 tol = 0;
+					UINT32 tol = 0;
 					tmp = strtok(word2,",");
 					do {
 						for (i = 0; TYPEOFLEVEL[i].name; i++)
@@ -7477,7 +7477,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 
 	// Got Flag Sign
 	"S_GOTFLAG",
-	
+
 	// Finish flag
 	"S_FINISHFLAG",
 

From 25cf369f2261fc9b337524653332c45dfbb59b2d Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Tue, 25 Feb 2020 22:34:19 -0300
Subject: [PATCH 080/251] Fix (technically functional) string comparison
 counting an extra character in the comparison length

---
 src/dehacked.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index 329cf8788..5d29ca280 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -10236,7 +10236,7 @@ static fixed_t find_const(const char **rword)
 		free(word);
 		return r;
 	}
-	else if (fastncmp("GT_",word,4)) {
+	else if (fastncmp("GT_",word,3)) {
 		r = get_gametype(word);
 		free(word);
 		return r;

From 7f32a532332097f82ad348130b75bd8532d78c6a Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Fri, 28 Feb 2020 17:31:41 -0300
Subject: [PATCH 081/251] Fix HWR_DrawFlippedColumnInCache ignoring chroma key
 TF

---
 src/hardware/hw_cache.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c
index ccffc8a49..059556f15 100644
--- a/src/hardware/hw_cache.c
+++ b/src/hardware/hw_cache.c
@@ -234,11 +234,11 @@ static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block,
 			if (mipmap->colormap)
 				texel = mipmap->colormap[texel];
 
-			// transparent pixel
-			if (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)
+			// If the mipmap is chromakeyed, check if the texel's color
+			// is equivalent to the chroma key's color index.
+			alpha = 0xff;
+			if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX))
 				alpha = 0x00;
-			else
-				alpha = 0xff;
 
 			// hope compiler will get this switch out of the loops (dreams...)
 			// gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?)

From 4446b0d5630a9e06813e5895e1d26137e6173e12 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 1 Feb 2020 22:25:48 -0300
Subject: [PATCH 082/251] Fix ACZ fence texture

---
 src/r_data.c | 36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/src/r_data.c b/src/r_data.c
index 87212c175..553e83bbc 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -230,25 +230,31 @@ static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, tex
 UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha)
 {
 	RGBA_t output;
+	INT16 fullalpha = (alpha - (0xFF - foreground.s.alpha));
 	if (style == AST_TRANSLUCENT)
 	{
-		if (alpha == 0)
+		if (fullalpha <= 0)
 			output.rgba = background.rgba;
-		else if (alpha == 0xFF)
-			output.rgba = foreground.rgba;
-		else if (alpha < 0xFF)
-		{
-			UINT8 beta = (0xFF - alpha);
-			output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF;
-			output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF;
-			output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF;
-		}
-		// write foreground pixel alpha
-		// if there's no pixel in here
-		if (!background.rgba)
-			output.s.alpha = foreground.s.alpha;
 		else
-			output.s.alpha = 0xFF;
+		{
+			// don't go too high
+			if (fullalpha >= 0xFF)
+				fullalpha = 0xFF;
+			alpha = (UINT8)fullalpha;
+
+			// if the background pixel is empty,
+			// match software and don't blend anything
+			if (!background.s.alpha)
+				output.s.alpha = 0;
+			else
+			{
+				UINT8 beta = (0xFF - alpha);
+				output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF;
+				output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF;
+				output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF;
+				output.s.alpha = 0xFF;
+			}
+		}
 		return output.rgba;
 	}
 #define clamp(c) max(min(c, 0xFF), 0x00);

From 48b352049fcf29ca7db94ff08aa0cb14c6971f8b Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 25 Jan 2020 21:37:33 -0300
Subject: [PATCH 083/251] Stop using NextTexAvail

---
 src/hardware/r_opengl/r_opengl.c | 45 +++++++++++---------------------
 1 file changed, 15 insertions(+), 30 deletions(-)

diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index 03af059ad..97c887910 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -63,7 +63,6 @@ static float NEAR_CLIPPING_PLANE =   NZCLIP_PLANE;
 // **************************************************************************
 
 
-static  GLuint      NextTexAvail    = FIRST_TEX_AVAIL;
 static  GLuint      tex_downloaded  = 0;
 static  GLfloat     fov             = 90.0f;
 #if 0
@@ -72,8 +71,8 @@ static  FRGBAFloat  const_pal_col;
 #endif
 static  FBITFIELD   CurrentPolyFlags;
 
-static  FTextureInfo*  gr_cachetail = NULL;
-static  FTextureInfo*  gr_cachehead = NULL;
+static  FTextureInfo *gr_cachetail = NULL;
+static  FTextureInfo *gr_cachehead = NULL;
 
 RGBA_t  myPaletteData[256];
 GLint   screen_width    = 0;               // used by Draw2DLine()
@@ -243,6 +242,7 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...)
 
 /* 1.1 functions */
 /* texture objects */ //GL_EXT_texture_object
+#define pglGenTextures glGenTextures
 #define pglDeleteTextures glDeleteTextures
 #define pglBindTexture glBindTexture
 /* texture mapping */ //GL_EXT_copy_texture
@@ -359,6 +359,8 @@ static PFNglFogfv pglFogfv;
 
 /* 1.1 functions */
 /* texture objects */ //GL_EXT_texture_object
+typedef void (APIENTRY * PFNglGenTextures) (GLsizei n, const GLuint *textures);
+static PFNglGenTextures pglGenTextures;
 typedef void (APIENTRY * PFNglDeleteTextures) (GLsizei n, const GLuint *textures);
 static PFNglDeleteTextures pglDeleteTextures;
 typedef void (APIENTRY * PFNglBindTexture) (GLenum target, GLuint texture);
@@ -487,6 +489,7 @@ boolean SetupGLfunc(void)
 	GETOPENGLFUNC(pglFogf , glFogf)
 	GETOPENGLFUNC(pglFogfv , glFogfv)
 
+	GETOPENGLFUNC(pglGenTextures , glGenTextures)
 	GETOPENGLFUNC(pglDeleteTextures , glDeleteTextures)
 	GETOPENGLFUNC(pglBindTexture , glBindTexture)
 
@@ -723,33 +726,12 @@ void Flush(void)
 
 	while (gr_cachehead)
 	{
-		// this is not necessary at all, because you have loaded them normally,
-		// and so they already are in your list!
-#if 0
-		//Hurdler: 25/04/2000: now support colormap in hardware mode
-		FTextureInfo    *tmp = gr_cachehead->nextskin;
-
-		// The memory should be freed in the main code
-		while (tmp)
-		{
-			pglDeleteTextures(1, &tmp->downloaded);
-			tmp->downloaded = 0;
-			tmp = tmp->nextcolormap;
-		}
-#endif
-		pglDeleteTextures(1, (GLuint *)&gr_cachehead->downloaded);
+		if (gr_cachehead->downloaded)
+			pglDeleteTextures(1, (GLuint *)&gr_cachehead->downloaded);
 		gr_cachehead->downloaded = 0;
 		gr_cachehead = gr_cachehead->nextmipmap;
 	}
 	gr_cachetail = gr_cachehead = NULL; //Hurdler: well, gr_cachehead is already NULL
-	NextTexAvail = FIRST_TEX_AVAIL;
-#if 0
-	if (screentexture != FIRST_TEX_AVAIL)
-	{
-		pglDeleteTextures(1, &screentexture);
-		screentexture = FIRST_TEX_AVAIL;
-	}
-#endif
 
 	tex_downloaded = 0;
 }
@@ -1128,8 +1110,10 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo)
 		static RGBA_t   tex[2048*2048];
 		const GLvoid   *ptex = tex;
 		INT32             w, h;
+		GLuint texnum = 0;
 
-		//DBG_Printf ("DownloadMipmap %d %x\n",NextTexAvail,pTexInfo->grInfo.data);
+		pglGenTextures(1, &texnum);
+		//DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->grInfo.data);
 
 		w = pTexInfo->width;
 		h = pTexInfo->height;
@@ -1217,9 +1201,10 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo)
 		else
 			DBG_Printf ("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format);
 
-		pTexInfo->downloaded = NextTexAvail++;
-		tex_downloaded = pTexInfo->downloaded;
-		pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded);
+		// the texture number was already generated by pglGenTextures
+		pglBindTexture(GL_TEXTURE_2D, texnum);
+		pTexInfo->downloaded = texnum;
+		tex_downloaded = texnum;
 
 		// disable texture filtering on any texture that has holes so there's no dumb borders or blending issues
 		if (pTexInfo->flags & TF_TRANSPARENT)

From 9b88edc458a5630a116b3b2bde02d20ba6c2efe6 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 25 Jan 2020 21:46:52 -0300
Subject: [PATCH 084/251] Same deal for screen textures

---
 src/hardware/r_opengl/r_opengl.c | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index 97c887910..9a3607e3a 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -93,16 +93,10 @@ static GLfloat    modelMatrix[16];
 static GLfloat    projMatrix[16];
 static GLint       viewport[4];
 
-// Yay for arbitrary  numbers! NextTexAvail is buggy for some reason.
 // Sryder:	NextTexAvail is broken for these because palette changes or changes to the texture filter or antialiasing
 //			flush all of the stored textures, leaving them unavailable at times such as between levels
 //			These need to start at 0 and be set to their number, and be reset to 0 when deleted so that intel GPUs
 //			can know when the textures aren't there, as textures are always considered resident in their virtual memory
-// TODO:	Store them in a more normal way
-#define SCRTEX_SCREENTEXTURE 4294967295U
-#define SCRTEX_STARTSCREENWIPE 4294967294U
-#define SCRTEX_ENDSCREENWIPE 4294967293U
-#define SCRTEX_FINALSCREENTEXTURE 4294967292U
 static GLuint screentexture = 0;
 static GLuint startScreenWipe = 0;
 static GLuint endScreenWipe = 0;
@@ -2404,7 +2398,7 @@ EXPORT void HWRAPI(StartScreenWipe) (void)
 
 	// Create screen texture
 	if (firstTime)
-		startScreenWipe = SCRTEX_STARTSCREENWIPE;
+		pglGenTextures(1, &startScreenWipe);
 	pglBindTexture(GL_TEXTURE_2D, startScreenWipe);
 
 	if (firstTime)
@@ -2435,7 +2429,7 @@ EXPORT void HWRAPI(EndScreenWipe)(void)
 
 	// Create screen texture
 	if (firstTime)
-		endScreenWipe = SCRTEX_ENDSCREENWIPE;
+		pglGenTextures(1, &endScreenWipe);
 	pglBindTexture(GL_TEXTURE_2D, endScreenWipe);
 
 	if (firstTime)
@@ -2606,7 +2600,7 @@ EXPORT void HWRAPI(MakeScreenTexture) (void)
 
 	// Create screen texture
 	if (firstTime)
-		screentexture = SCRTEX_SCREENTEXTURE;
+		pglGenTextures(1, &screentexture);
 	pglBindTexture(GL_TEXTURE_2D, screentexture);
 
 	if (firstTime)
@@ -2636,7 +2630,7 @@ EXPORT void HWRAPI(MakeScreenFinalTexture) (void)
 
 	// Create screen texture
 	if (firstTime)
-		finalScreenTexture = SCRTEX_FINALSCREENTEXTURE;
+		pglGenTextures(1, &finalScreenTexture);
 	pglBindTexture(GL_TEXTURE_2D, finalScreenTexture);
 
 	if (firstTime)

From 4a489c4d95d01ead0e192b05bdd48eeb4bc6b7d3 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 25 Jan 2020 22:20:27 -0300
Subject: [PATCH 085/251] Fix NOTEXTURE_NUM

---
 src/hardware/r_opengl/r_opengl.c | 20 ++++----------------
 1 file changed, 4 insertions(+), 16 deletions(-)

diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index 9a3607e3a..ed60f2175 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -49,8 +49,7 @@ static const GLubyte white[4] = { 255, 255, 255, 255 };
 // ==========================================================================
 
 // With OpenGL 1.1+, the first texture should be 1
-#define NOTEXTURE_NUM     1     // small white texture
-#define FIRST_TEX_AVAIL   (NOTEXTURE_NUM + 1)
+static GLuint NOTEXTURE_NUM = 0;
 
 #define      N_PI_DEMI               (M_PIl/2.0f) //(1.5707963268f)
 
@@ -524,6 +523,8 @@ static void SetNoTexture(void)
 	// Set small white texture.
 	if (tex_downloaded != NOTEXTURE_NUM)
 	{
+		if (NOTEXTURE_NUM == 0)
+			pglGenTextures(1, &NOTEXTURE_NUM);
 		pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM);
 		tex_downloaded = NOTEXTURE_NUM;
 	}
@@ -638,11 +639,6 @@ void SetModelView(GLint w, GLint h)
 // -----------------+
 void SetStates(void)
 {
-	// Bind little white RGBA texture to ID NOTEXTURE_NUM.
-	/*
-	FUINT Data[8*8];
-	INT32 i;
-	*/
 #ifdef GL_LIGHT_MODEL_AMBIENT
 	GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
 #endif
@@ -676,16 +672,8 @@ void SetStates(void)
 	CurrentPolyFlags = 0xffffffff;
 	SetBlend(0);
 
-	/*
-	for (i = 0; i < 64; i++)
-		Data[i] = 0xffFFffFF;       // white pixel
-	*/
-
-	tex_downloaded = (GLuint)-1;
+	tex_downloaded = 0;
 	SetNoTexture();
-	//pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM);
-	//tex_downloaded = NOTEXTURE_NUM;
-	//pglTexImage2D(GL_TEXTURE_2D, 0, 4, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, Data);
 
 	pglPolygonOffset(-1.0f, -1.0f);
 

From 94107a5320944784ab0717ce5e3dc5337e72fd10 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Sat, 29 Feb 2020 19:36:50 -0300
Subject: [PATCH 086/251] Set pixel RGBA to nothing instead of the alpha only

---
 src/r_data.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/r_data.c b/src/r_data.c
index 553e83bbc..3d80bbda3 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -242,10 +242,9 @@ UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alph
 				fullalpha = 0xFF;
 			alpha = (UINT8)fullalpha;
 
-			// if the background pixel is empty,
-			// match software and don't blend anything
+			// if the background pixel is empty, match software and don't blend anything
 			if (!background.s.alpha)
-				output.s.alpha = 0;
+				output.rgba = 0;
 			else
 			{
 				UINT8 beta = (0xFF - alpha);

From 70a103b9afb143141449d99fbce0a59a29e358c4 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Mon, 2 Mar 2020 00:20:53 -0300
Subject: [PATCH 087/251] Fix G_TOLFlag returning the wrong type

---
 src/g_game.c | 4 ++--
 src/g_game.h | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/g_game.c b/src/g_game.c
index 08192bfb8..6d8826f1c 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -3592,7 +3592,7 @@ boolean G_CompetitionGametype(void)
   * \return The typeoflevel flag to check for that gametype.
   * \author Graue <graue@oceanbase.org>
   */
-INT16 G_TOLFlag(INT32 pgametype)
+UINT32 G_TOLFlag(INT32 pgametype)
 {
 	if (!multiplayer)
 		return TOL_SP;
@@ -3723,7 +3723,7 @@ static void G_DoCompleted(void)
 		&& (nextmap >= 0 && nextmap < NUMMAPS))
 	{
 		register INT16 cm = nextmap;
-		INT16 tolflag = G_TOLFlag(gametype);
+		UINT32 tolflag = G_TOLFlag(gametype);
 		UINT8 visitedmap[(NUMMAPS+7)/8];
 
 		memset(visitedmap, 0, sizeof (visitedmap));
diff --git a/src/g_game.h b/src/g_game.h
index c4c40d84b..8a2c5b0ae 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -309,6 +309,6 @@ FUNCMATH INT32 G_TicsToCentiseconds(tic_t tics);
 FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics);
 
 // Don't split up TOL handling
-INT16 G_TOLFlag(INT32 pgametype);
+UINT32 G_TOLFlag(INT32 pgametype);
 
 #endif

From c671097c04e784d4a0e1009ea766cde8af492c51 Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Mon, 2 Mar 2020 13:23:54 +0100
Subject: [PATCH 088/251] Actually use the "SCREENSHOT OPTIONS" header for its
 menu.

---
 src/m_menu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index 403d3a036..fd710ff10 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -2179,7 +2179,7 @@ menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE(
 menu_t OP_ScreenshotOptionsDef =
 {
 	MN_OP_MAIN + (MN_OP_DATA << 6) + (MN_OP_SCREENSHOTS << 12),
-	"M_DATA",
+	"M_SCREEN",
 	sizeof (OP_ScreenshotOptionsMenu)/sizeof (menuitem_t),
 	&OP_DataOptionsDef,
 	OP_ScreenshotOptionsMenu,

From 7ba93c184f15ef1212dbc45c69354dbc278293a2 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Mon, 2 Mar 2020 13:33:12 +0100
Subject: [PATCH 089/251] Fix warning and formatting

---
 src/blua/liolib.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/src/blua/liolib.c b/src/blua/liolib.c
index 378b8c86d..b43052194 100644
--- a/src/blua/liolib.c
+++ b/src/blua/liolib.c
@@ -34,7 +34,8 @@
 #define FMT_FILECALLBACKID "file_callback_%d"
 
 
-static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder
+// Allow scripters to write files of these types to SRB2's folder
+static const char *whitelist[] = {
 	".bmp",
 	".cfg",
 	".csv",
@@ -508,7 +509,6 @@ static int io_readline (lua_State *L) {
 static int g_write (lua_State *L, FILE *f, int arg) {
   int nargs = lua_gettop(L) - 1;
   int status = 1;
-  size_t count;
   for (; nargs--; arg++) {
     if (lua_type(L, arg) == LUA_TNUMBER) {
       /* optimization: could be done exactly as for strings */
@@ -518,12 +518,10 @@ static int g_write (lua_State *L, FILE *f, int arg) {
     else {
       size_t l;
       const char *s = luaL_checklstring(L, arg, &l);
-	  count += l;
-	  if (ftell(f) + l > FILELIMIT)
-	  {
-		luaL_error(L,"write limit bypassed in file. Changes have been discarded.");
-		break;
-	  }
+      if (ftell(f) + l > FILELIMIT) {
+          luaL_error(L,"write limit bypassed in file. Changes have been discarded.");
+          break;
+      }
       status = status && (fwrite(s, sizeof(char), l, f) == l);
     }
   }

From 04a1f479be653e8def68ead20e489ab735bd0ac6 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Mon, 2 Mar 2020 15:36:28 +0100
Subject: [PATCH 090/251] Increase the length of the player input buffer

---
 src/d_clisrv.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index 42da89670..7cdff8ef0 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -36,7 +36,7 @@ basic fields of the packet, and change infrequently.
 //  be transmitted.
 
 // Networking and tick handling related.
-#define BACKUPTICS 32
+#define BACKUPTICS 96
 #define MAXTEXTCMD 256
 //
 // Packet structure

From 776951c6a897ac0a55e952aeb2963bea79504df3 Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Tue, 3 Mar 2020 11:40:35 -0300
Subject: [PATCH 091/251] Never forget who your enemy is

---
 src/p_mobj.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/p_mobj.c b/src/p_mobj.c
index faee245d3..31abeb780 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -9393,8 +9393,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
 			if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0
 				&& P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z - mobj->z) <= mobj->radius*16)
 			{
+				var1 = mobj->info->speed;
+				var2 = 1;
+
 				// Home in on the target.
-				P_HomingAttack(mobj, mobj->tracer);
+				A_HomingChase(mobj);
 
 				if (mobj->z < mobj->floorz)
 					mobj->z = mobj->floorz;

From 761ec3b6a4a2389d985ae8263fb65a3eb9a82fd7 Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Sun, 1 Mar 2020 21:31:44 -0300
Subject: [PATCH 092/251] Separate PvP damage from non-friendly gametypes

---
 src/p_inter.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_inter.c b/src/p_inter.c
index a24f9bf03..8b9f74973 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -3156,7 +3156,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
 			return false;
 
 		// In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on
-		if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && (G_PlatformGametype()))
+		if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) && (gametyperules & GTR_FRIENDLY))
 		{
 			if (gametype == GT_COOP && inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) // co-op only
 			{

From b8db3e2216df8379344300e5979945e5c6e4d37e Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Wed, 4 Mar 2020 09:42:34 -0300
Subject: [PATCH 093/251] Fix NiGHTS Attack crash after render mode change

---
 src/m_menu.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index 72e2d57e0..e0becdff1 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -5740,6 +5740,8 @@ static void M_DrawNightsAttackSuperSonic(void)
 	const UINT8 *colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_YELLOW, GTC_CACHE);
 	INT32 timer = (ntsatkdrawtimer/4) % 2;
 	angle_t fa = (FixedAngle(((ntsatkdrawtimer * 4) % 360)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK;
+	ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH);
+	ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH);
 	V_DrawFixedPatch(235<<FRACBITS, (120<<FRACBITS) - (8*FINESINE(fa)), FRACUNIT, 0, ntssupersonic[timer], colormap);
 }
 
@@ -9978,9 +9980,6 @@ static void M_NightsAttack(INT32 choice)
 	// This is really just to make sure Sonic is the played character, just in case
 	M_PatchSkinNameTable();
 
-	ntssupersonic[0] = W_CachePatchName("NTSSONC1", PU_PATCH);
-	ntssupersonic[1] = W_CachePatchName("NTSSONC2", PU_PATCH);
-
 	G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching
 	titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
 	M_SetupNextMenu(&SP_NightsAttackDef);

From 27e084a827f9b8a1d3f5e913694db2268acf0079 Mon Sep 17 00:00:00 2001
From: Zwip-Zwap Zapony <ZwipZwapZapony@gmail.com>
Date: Wed, 4 Mar 2020 17:31:52 +0100
Subject: [PATCH 094/251] Fix division-by-0 crash with gamepad deadzones

Fix division-by-0 crash with gamepad deadzones
The problem was that it checked if A was more than B,
then lowered A to a max value, then subtracted B from A,
then divided something by that, without checking if A minus B was 0,
allowing division by 0 if B was the same as that max value

This fixes that by making sure that A is less than the max value
---
 src/g_game.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/src/g_game.c b/src/g_game.c
index 08192bfb8..4db55329e 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -1045,17 +1045,14 @@ static INT32 G_BasicDeadZoneCalculation(INT32 magnitude, fixed_t deadZone)
 	const INT32 jdeadzone = (JOYAXISRANGE * deadZone) / FRACUNIT;
 	INT32 deadzoneAppliedValue = 0;
 
-	if (jdeadzone > 0)
+	if (jdeadzone > 0 && magnitude > jdeadzone && deadZone < FRACUNIT)
 	{
-		if (magnitude > jdeadzone)
-		{
-			INT32 adjustedMagnitude = abs(magnitude);
-			adjustedMagnitude = min(adjustedMagnitude, JOYAXISRANGE);
+		INT32 adjustedMagnitude = abs(magnitude);
+		adjustedMagnitude = min(adjustedMagnitude, JOYAXISRANGE);
 
-			adjustedMagnitude -= jdeadzone;
+		adjustedMagnitude -= jdeadzone;
 
-			deadzoneAppliedValue = (adjustedMagnitude * JOYAXISRANGE) / (JOYAXISRANGE - jdeadzone);
-		}
+		deadzoneAppliedValue = (adjustedMagnitude * JOYAXISRANGE) / (JOYAXISRANGE - jdeadzone);
 	}
 
 	return deadzoneAppliedValue;

From df220aa2c2d209f7b253e958abc2cf0d63a8bca9 Mon Sep 17 00:00:00 2001
From: Zwip-Zwap Zapony <ZwipZwapZapony@gmail.com>
Date: Wed, 4 Mar 2020 21:11:55 +0100
Subject: [PATCH 095/251] Hotfix for 100% deadzone returning 0 input

It makes more sense for 100% deadzone to just make it so that
you have to push the axis all the way to trigger it,
rather than 100% deadzone resulting in no axis input
ever happening... So, let's make it be the former way instead
---
 src/g_game.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/g_game.c b/src/g_game.c
index 4db55329e..2cddaf8b8 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -1045,14 +1045,19 @@ static INT32 G_BasicDeadZoneCalculation(INT32 magnitude, fixed_t deadZone)
 	const INT32 jdeadzone = (JOYAXISRANGE * deadZone) / FRACUNIT;
 	INT32 deadzoneAppliedValue = 0;
 
-	if (jdeadzone > 0 && magnitude > jdeadzone && deadZone < FRACUNIT)
+	if (jdeadzone > 0 && magnitude > jdeadzone)
 	{
-		INT32 adjustedMagnitude = abs(magnitude);
-		adjustedMagnitude = min(adjustedMagnitude, JOYAXISRANGE);
+		if (deadZone >= FRACUNIT) // If the deadzone value is at 100%...
+			return JOYAXISRANGE; // ...return 100% input directly, to avoid dividing by 0
+		else
+		{
+			INT32 adjustedMagnitude = abs(magnitude);
+			adjustedMagnitude = min(adjustedMagnitude, JOYAXISRANGE);
 
-		adjustedMagnitude -= jdeadzone;
+			adjustedMagnitude -= jdeadzone;
 
-		deadzoneAppliedValue = (adjustedMagnitude * JOYAXISRANGE) / (JOYAXISRANGE - jdeadzone);
+			deadzoneAppliedValue = (adjustedMagnitude * JOYAXISRANGE) / (JOYAXISRANGE - jdeadzone);
+		}
 	}
 
 	return deadzoneAppliedValue;

From bce6349b1d09e24fd6a4deada395bc628452d38f Mon Sep 17 00:00:00 2001
From: Zwip-Zwap Zapony <ZwipZwapZapony@gmail.com>
Date: Wed, 4 Mar 2020 21:44:57 +0100
Subject: [PATCH 096/251] More gamepad deadzone tweakage

---
 src/g_game.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/src/g_game.c b/src/g_game.c
index 2cddaf8b8..818cb38c2 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -1044,20 +1044,17 @@ static INT32 G_BasicDeadZoneCalculation(INT32 magnitude, fixed_t deadZone)
 {
 	const INT32 jdeadzone = (JOYAXISRANGE * deadZone) / FRACUNIT;
 	INT32 deadzoneAppliedValue = 0;
+	INT32 adjustedMagnitude = abs(magnitude);
 
-	if (jdeadzone > 0 && magnitude > jdeadzone)
+	if (jdeadzone >= JOYAXISRANGE && adjustedMagnitude >= JOYAXISRANGE) // If the deadzone and magnitude are both 100%...
+		return JOYAXISRANGE; // ...return 100% input directly, to avoid dividing by 0
+	else if (adjustedMagnitude > jdeadzone) // Otherwise, calculate how much the magnitude exceeds the deadzone
 	{
-		if (deadZone >= FRACUNIT) // If the deadzone value is at 100%...
-			return JOYAXISRANGE; // ...return 100% input directly, to avoid dividing by 0
-		else
-		{
-			INT32 adjustedMagnitude = abs(magnitude);
-			adjustedMagnitude = min(adjustedMagnitude, JOYAXISRANGE);
+		adjustedMagnitude = min(adjustedMagnitude, JOYAXISRANGE);
 
-			adjustedMagnitude -= jdeadzone;
+		adjustedMagnitude -= jdeadzone;
 
-			deadzoneAppliedValue = (adjustedMagnitude * JOYAXISRANGE) / (JOYAXISRANGE - jdeadzone);
-		}
+		deadzoneAppliedValue = (adjustedMagnitude * JOYAXISRANGE) / (JOYAXISRANGE - jdeadzone);
 	}
 
 	return deadzoneAppliedValue;

From da9bf34175f6eb9bc0affaf5ad1a314f58f23abd Mon Sep 17 00:00:00 2001
From: ZipperQR <bartuince97@gmail.com>
Date: Thu, 5 Mar 2020 12:24:45 +0300
Subject: [PATCH 097/251] fix source player being nil

---
 src/p_inter.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_inter.c b/src/p_inter.c
index a24f9bf03..c2d4c695e 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -3441,7 +3441,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source)
 	if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super])
 		return;
 
-	if (!cv_friendlyfire.value)
+	if (!cv_friendlyfire.value && source->player)
 	{
 		if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
 		{

From 4d8a523da92654f80d40898efa6e81c34e2f2110 Mon Sep 17 00:00:00 2001
From: Zipper <sonic22mario@hotmail.com>
Date: Thu, 5 Mar 2020 18:30:27 -0500
Subject: [PATCH 098/251] Update p_inter.c

---
 src/p_inter.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_inter.c b/src/p_inter.c
index c2d4c695e..858718f84 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -3441,7 +3441,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source)
 	if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super])
 		return;
 
-	if (!cv_friendlyfire.value && source->player)
+	if (!cv_friendlyfire.value && source && source->player)
 	{
 		if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
 		{

From 4b28e19d16db1ece7bdeffef981513ef0b30d360 Mon Sep 17 00:00:00 2001
From: Zipper <sonic22mario@hotmail.com>
Date: Thu, 5 Mar 2020 18:48:20 -0500
Subject: [PATCH 099/251] Update p_inter.c

---
 src/p_inter.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_inter.c b/src/p_inter.c
index 858718f84..95f8fba41 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -3456,7 +3456,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source)
 			return;
 	}
 
-	if (inflictor->type == MT_LHRT)
+	if (inflictor && inflictor->type == MT_LHRT)
 		return;
 
 	if (player->powers[pw_shield] || player->bot)  //If One-Hit Shield

From 0d92bf3dd09cd4712a63fc79cc7520ed18556bf6 Mon Sep 17 00:00:00 2001
From: GoldenTails <milestailsprower101n2@gmail.com>
Date: Sat, 7 Mar 2020 21:41:52 -0600
Subject: [PATCH 100/251] Florida man fixes sectors with light level 256
 blacking out OpenGL objects; mappers riot.

Disclaimer: I'm not actually from Florida.
---
 src/hardware/hw_main.c | 17 ++++++++++-------
 src/hardware/hw_md2.c  |  4 ++--
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index efed9b602..5a5db90e8 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -4186,7 +4186,10 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale
 	{
 		light = R_GetPlaneLight(thing->subsector->sector, floorz, false); // Always use the light at the top instead of whatever I was doing before
 
-		lightlevel = *thing->subsector->sector->lightlist[light].lightlevel;
+        if (*thing->subsector->sector->lightlist[light].lightlevel > 255)
+            lightlevel = 255;
+        else
+            lightlevel = *thing->subsector->sector->lightlist[light].lightlevel;
 
 		if (*thing->subsector->sector->lightlist[light].extra_colormap)
 			colormap = *thing->subsector->sector->lightlist[light].extra_colormap;
@@ -4392,7 +4395,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 		if (h <= temp)
 		{
 			if (!(spr->mobj->frame & FF_FULLBRIGHT))
-				lightlevel = *list[i-1].lightlevel;
+				lightlevel = *list[i-1].lightlevel > 255 ? 255 : *list[i-1].lightlevel;
 			colormap = *list[i-1].extra_colormap;
 			break;
 		}
@@ -4400,7 +4403,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 #else
 	i = R_GetPlaneLight(sector, temp, false);
 	if (!(spr->mobj->frame & FF_FULLBRIGHT))
-		lightlevel = *list[i].lightlevel;
+		lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel;
 	colormap = *list[i].extra_colormap;
 #endif
 
@@ -4416,7 +4419,7 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 		if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES))
 		{
 			if (!(spr->mobj->frame & FF_FULLBRIGHT))
-				lightlevel = *list[i].lightlevel;
+				lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel;
 			colormap = *list[i].extra_colormap;
 		}
 
@@ -4693,7 +4696,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
 		extracolormap_t *colormap = sector->extra_colormap;
 
 		if (!(spr->mobj->frame & FF_FULLBRIGHT))
-			lightlevel = sector->lightlevel;
+			lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
 
 		if (colormap)
 			Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
@@ -4790,7 +4793,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
 			light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before
 
 			if (!(spr->mobj->frame & FF_FULLBRIGHT))
-				lightlevel = *sector->lightlist[light].lightlevel;
+				lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
 
 			if (*sector->lightlist[light].extra_colormap)
 				colormap = *sector->lightlist[light].extra_colormap;
@@ -4798,7 +4801,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr)
 		else
 		{
 			if (!(spr->mobj->frame & FF_FULLBRIGHT))
-				lightlevel = sector->lightlevel;
+				lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
 
 			if (sector->extra_colormap)
 				colormap = sector->extra_colormap;
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 5c3cd40a6..2e3af4a4c 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -1221,7 +1221,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
 			light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before
 
 			if (!(spr->mobj->frame & FF_FULLBRIGHT))
-				lightlevel = *sector->lightlist[light].lightlevel;
+				lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
 
 			if (*sector->lightlist[light].extra_colormap)
 				colormap = *sector->lightlist[light].extra_colormap;
@@ -1229,7 +1229,7 @@ boolean HWR_DrawModel(gr_vissprite_t *spr)
 		else
 		{
 			if (!(spr->mobj->frame & FF_FULLBRIGHT))
-				lightlevel = sector->lightlevel;
+				lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
 
 			if (sector->extra_colormap)
 				colormap = sector->extra_colormap;

From cdba9ba03371adf3609010aa8896200018570cc7 Mon Sep 17 00:00:00 2001
From: GoldenTails <milestailsprower101n2@gmail.com>
Date: Sat, 7 Mar 2020 21:48:40 -0600
Subject: [PATCH 101/251] Fix spaces before someone yells at me for it

---
 src/hardware/hw_main.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 5a5db90e8..bb3559696 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -4186,10 +4186,10 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale
 	{
 		light = R_GetPlaneLight(thing->subsector->sector, floorz, false); // Always use the light at the top instead of whatever I was doing before
 
-        if (*thing->subsector->sector->lightlist[light].lightlevel > 255)
-            lightlevel = 255;
-        else
-            lightlevel = *thing->subsector->sector->lightlist[light].lightlevel;
+		if (*thing->subsector->sector->lightlist[light].lightlevel > 255)
+			lightlevel = 255;
+		else
+			lightlevel = *thing->subsector->sector->lightlist[light].lightlevel;
 
 		if (*thing->subsector->sector->lightlist[light].extra_colormap)
 			colormap = *thing->subsector->sector->lightlist[light].extra_colormap;

From a3f3dd649f5a177d4e42bc4f443a3a127574dd45 Mon Sep 17 00:00:00 2001
From: Steel Titanium <steeltitanium1@gmail.com>
Date: Sun, 8 Mar 2020 00:02:43 -0500
Subject: [PATCH 102/251] Fix guest deletion confirmation returning to Record
 Attack menu from Nights Mode menu

---
 src/m_menu.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index 72e2d57e0..712fd2cd7 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -10103,10 +10103,7 @@ static void M_EraseGuest(INT32 choice)
 	(void)choice;
 	if (FIL_FileExists(rguest))
 		remove(rguest);
-	if (currentMenu == &SP_NightsGuestReplayDef)
-		M_SetupNextMenu(&SP_NightsAttackDef);
-	else
-		M_SetupNextMenu(&SP_TimeAttackDef);
+	M_SetupNextMenu(currentMenu->prevMenu->prevMenu);
 	Nextmap_OnChange();
 	M_StartMessage(M_GetText("Guest replay data erased.\n"),NULL,MM_NOTHING);
 }

From e5270ad9c71a79b0bc95561b2d8cd55306d3d5f7 Mon Sep 17 00:00:00 2001
From: Steel Titanium <steeltitanium1@gmail.com>
Date: Sun, 8 Mar 2020 00:34:15 -0500
Subject: [PATCH 103/251] Fix guest data being deleted regardless of choice

---
 src/m_menu.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index 712fd2cd7..75774c74c 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -10100,9 +10100,12 @@ static void M_ReplayTimeAttack(INT32 choice)
 static void M_EraseGuest(INT32 choice)
 {
 	const char *rguest = va("%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s-guest.lmp", srb2home, timeattackfolder, G_BuildMapName(cv_nextmap.value));
-	(void)choice;
-	if (FIL_FileExists(rguest))
-		remove(rguest);
+
+	if (choice == 'y' || choice == KEY_ENTER)
+	{
+		if (FIL_FileExists(rguest))
+			remove(rguest);
+	}
 	M_SetupNextMenu(currentMenu->prevMenu->prevMenu);
 	Nextmap_OnChange();
 	M_StartMessage(M_GetText("Guest replay data erased.\n"),NULL,MM_NOTHING);

From be338da3f695f94cce07a9aa4ae2e0e85701d8af Mon Sep 17 00:00:00 2001
From: Tatsuru <44866610+Ikkarin@users.noreply.github.com>
Date: Sun, 8 Mar 2020 14:06:18 -0300
Subject: [PATCH 104/251] I guess

---
 src/p_user.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_user.c b/src/p_user.c
index 9167d5345..1715224ae 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -9422,7 +9422,7 @@ boolean P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target
 	if (enemy->health <= 0) // dead
 		return false;
 
-	if (!((enemy->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (enemy->flags & MF_SHOOTABLE)) || (enemy->flags & MF_SPRING)) == !(enemy->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag
+	if (source->player && (!((enemy->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (enemy->flags & MF_SHOOTABLE)) || (enemy->flags & MF_SPRING)) == !(enemy->flags2 & MF2_INVERTAIMABLE))) // allows if it has the flags desired XOR it has the invert aimable flag
 		return false;
 
 	if (enemy->flags2 & MF2_FRET)

From ce29129f3a67eab7c88af8e2360be48333ce0d16 Mon Sep 17 00:00:00 2001
From: colette <red@lyrawearspants.com>
Date: Sun, 8 Mar 2020 13:09:39 -0400
Subject: [PATCH 105/251] Fix resyncs never recovering if node and player
 mismatch

---
 src/d_clisrv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index f5fea366f..71e32977a 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -3966,7 +3966,7 @@ static void HandlePacketFromPlayer(SINT8 node)
 		case PT_RESYNCHGET:
 			if (client)
 				break;
-			SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot);
+			SV_AcknowledgeResynchAck(node, netbuffer->u.resynchgot);
 			break;
 		case PT_CLIENTCMD:
 		case PT_CLIENT2CMD:

From a67dbfff549ec6d9e330d9c83b4df8cce2d327f9 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Sun, 8 Mar 2020 19:32:07 +0000
Subject: [PATCH 106/251] Create r_skins.c/.h, to contain skins code formerly
 in r_things.c/h

---
 src/r_skins.c  | 825 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/r_skins.h  | 102 ++++++
 src/r_things.c | 799 +----------------------------------------------
 src/r_things.h |  81 +----
 4 files changed, 936 insertions(+), 871 deletions(-)
 create mode 100644 src/r_skins.c
 create mode 100644 src/r_skins.h

diff --git a/src/r_skins.c b/src/r_skins.c
new file mode 100644
index 000000000..48764ff75
--- /dev/null
+++ b/src/r_skins.c
@@ -0,0 +1,825 @@
+// SONIC ROBO BLAST 2
+//-----------------------------------------------------------------------------
+// Copyright (C) 1993-1996 by id Software, Inc.
+// Copyright (C) 1998-2000 by DooM Legacy Team.
+// Copyright (C) 1999-2020 by Sonic Team Junior.
+//
+// This program is free software distributed under the
+// terms of the GNU General Public License, version 2.
+// See the 'LICENSE' file for more details.
+//-----------------------------------------------------------------------------
+/// \file  r_skins.c
+/// \brief Loading skins
+
+#include "doomdef.h"
+#include "console.h"
+#include "g_game.h"
+#include "r_local.h"
+#include "st_stuff.h"
+#include "w_wad.h"
+#include "z_zone.h"
+#include "m_misc.h"
+#include "info.h" // spr2names
+#include "i_video.h" // rendermode
+#include "i_system.h"
+#include "r_things.h"
+#include "r_skins.h"
+#include "p_local.h"
+#include "dehacked.h" // get_number (for thok)
+#include "m_cond.h"
+#ifdef HWRENDER
+#include "hardware/hw_md2.h"
+#endif
+
+#ifdef PC_DOS
+#include <stdio.h> // for snprintf
+int	snprintf(char *str, size_t n, const char *fmt, ...);
+//int	vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
+#endif
+
+INT32 numskins = 0;
+skin_t skins[MAXSKINS];
+
+// FIXTHIS: don't work because it must be inistilised before the config load
+//#define SKINVALUES
+#ifdef SKINVALUES
+CV_PossibleValue_t skin_cons_t[MAXSKINS+1];
+#endif
+
+//
+// P_GetSkinSprite2
+// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing.
+// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version.
+//
+
+UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
+{
+	UINT8 super = 0, i = 0;
+
+	if (!skin)
+		return 0;
+
+	if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2)
+		return 0;
+
+	while (!skin->sprites[spr2].numframes
+		&& spr2 != SPR2_STND
+		&& ++i < 32) // recursion limiter
+	{
+		if (spr2 & FF_SPR2SUPER)
+		{
+			super = FF_SPR2SUPER;
+			spr2 &= ~FF_SPR2SUPER;
+			continue;
+		}
+
+		switch(spr2)
+		{
+		// Normal special cases.
+		case SPR2_JUMP:
+			spr2 = ((player
+					? player->charflags
+					: skin->flags)
+					& SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL;
+			break;
+		case SPR2_TIRE:
+			spr2 = ((player
+					? player->charability
+					: skin->ability)
+					== CA_SWIM) ? SPR2_SWIM : SPR2_FLY;
+			break;
+		// Use the handy list, that's what it's there for!
+		default:
+			spr2 = spr2defaults[spr2];
+			break;
+		}
+
+		spr2 |= super;
+	}
+
+	if (i >= 32) // probably an infinite loop...
+		return 0;
+
+	return spr2;
+}
+
+static void Sk_SetDefaultValue(skin_t *skin)
+{
+	INT32 i;
+	//
+	// set default skin values
+	//
+	memset(skin, 0, sizeof (skin_t));
+	snprintf(skin->name,
+		sizeof skin->name, "skin %u", (UINT32)(skin-skins));
+	skin->name[sizeof skin->name - 1] = '\0';
+	skin->wadnum = INT16_MAX;
+
+	skin->flags = 0;
+
+	strcpy(skin->realname, "Someone");
+	strcpy(skin->hudname, "???");
+
+	skin->starttranscolor = 96;
+	skin->prefcolor = SKINCOLOR_GREEN;
+	skin->supercolor = SKINCOLOR_SUPERGOLD1;
+	skin->prefoppositecolor = 0; // use tables
+
+	skin->normalspeed = 36<<FRACBITS;
+	skin->runspeed = 28<<FRACBITS;
+	skin->thrustfactor = 5;
+	skin->accelstart = 96;
+	skin->acceleration = 40;
+
+	skin->ability = CA_NONE;
+	skin->ability2 = CA2_SPINDASH;
+	skin->jumpfactor = FRACUNIT;
+	skin->actionspd = 30<<FRACBITS;
+	skin->mindash = 15<<FRACBITS;
+	skin->maxdash = 70<<FRACBITS;
+
+	skin->radius = mobjinfo[MT_PLAYER].radius;
+	skin->height = mobjinfo[MT_PLAYER].height;
+	skin->spinheight = FixedMul(skin->height, 2*FRACUNIT/3);
+
+	skin->shieldscale = FRACUNIT;
+	skin->camerascale = FRACUNIT;
+
+	skin->thokitem = -1;
+	skin->spinitem = -1;
+	skin->revitem = -1;
+	skin->followitem = 0;
+
+	skin->highresscale = FRACUNIT;
+	skin->contspeed = 17;
+	skin->contangle = 0;
+
+	skin->availability = 0;
+
+	for (i = 0; i < sfx_skinsoundslot0; i++)
+		if (S_sfx[i].skinsound != -1)
+			skin->soundsid[S_sfx[i].skinsound] = i;
+}
+
+//
+// Initialize the basic skins
+//
+void R_InitSkins(void)
+{
+#ifdef SKINVALUES
+	INT32 i;
+
+	for (i = 0; i <= MAXSKINS; i++)
+	{
+		skin_cons_t[i].value = 0;
+		skin_cons_t[i].strvalue = NULL;
+	}
+#endif
+
+	// no default skin!
+	numskins = 0;
+}
+
+UINT32 R_GetSkinAvailabilities(void)
+{
+	INT32 s;
+	UINT32 response = 0;
+
+	for (s = 0; s < MAXSKINS; s++)
+	{
+		if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked)
+			response |= (1 << s);
+	}
+	return response;
+}
+
+// returns true if available in circumstances, otherwise nope
+// warning don't use with an invalid skinnum other than -1 which always returns true
+boolean R_SkinUsable(INT32 playernum, INT32 skinnum)
+{
+	return ((skinnum == -1) // Simplifies things elsewhere, since there's already plenty of checks for less-than-0...
+		|| (!skins[skinnum].availability)
+		|| (((netgame || multiplayer) && playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked))
+		|| (modeattacking) // If you have someone else's run you might as well take a look
+		|| (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1.
+		|| (netgame && (cv_forceskin.value == skinnum)) // Force 2.
+		|| (metalrecording && skinnum == 5) // Force 3.
+		);
+}
+
+// returns true if the skin name is found (loaded from pwad)
+// warning return -1 if not found
+INT32 R_SkinAvailable(const char *name)
+{
+	INT32 i;
+
+	for (i = 0; i < numskins; i++)
+	{
+		// search in the skin list
+		if (stricmp(skins[i].name,name)==0)
+			return i;
+	}
+	return -1;
+}
+
+// network code calls this when a 'skin change' is received
+void SetPlayerSkin(INT32 playernum, const char *skinname)
+{
+	INT32 i = R_SkinAvailable(skinname);
+	player_t *player = &players[playernum];
+
+	if ((i != -1) && R_SkinUsable(playernum, i))
+	{
+		SetPlayerSkinByNum(playernum, i);
+		return;
+	}
+
+	if (P_IsLocalPlayer(player))
+		CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname);
+	else if(server || IsPlayerAdmin(consoleplayer))
+		CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname);
+
+	SetPlayerSkinByNum(playernum, 0);
+}
+
+// Same as SetPlayerSkin, but uses the skin #.
+// network code calls this when a 'skin change' is received
+void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
+{
+	player_t *player = &players[playernum];
+	skin_t *skin = &skins[skinnum];
+	UINT8 newcolor = 0;
+
+	if (skinnum >= 0 && skinnum < numskins && R_SkinUsable(playernum, skinnum)) // Make sure it exists!
+	{
+		player->skin = skinnum;
+
+		player->camerascale = skin->camerascale;
+		player->shieldscale = skin->shieldscale;
+
+		player->charability = (UINT8)skin->ability;
+		player->charability2 = (UINT8)skin->ability2;
+
+		player->charflags = (UINT32)skin->flags;
+
+		player->thokitem = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem;
+		player->spinitem = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem;
+		player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem;
+		player->followitem = skin->followitem;
+
+		if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->revitem == MT_LHRT || player->spinitem == MT_LHRT || player->thokitem == MT_LHRT)) // Healers can't keep their buff.
+			player->powers[pw_shield] &= SH_STACK;
+
+		player->actionspd = skin->actionspd;
+		player->mindash = skin->mindash;
+		player->maxdash = skin->maxdash;
+
+		player->normalspeed = skin->normalspeed;
+		player->runspeed = skin->runspeed;
+		player->thrustfactor = skin->thrustfactor;
+		player->accelstart = skin->accelstart;
+		player->acceleration = skin->acceleration;
+
+		player->jumpfactor = skin->jumpfactor;
+
+		player->height = skin->height;
+		player->spinheight = skin->spinheight;
+
+		if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback))
+		{
+			if (playernum == consoleplayer)
+				CV_StealthSetValue(&cv_playercolor, skin->prefcolor);
+			else if (playernum == secondarydisplayplayer)
+				CV_StealthSetValue(&cv_playercolor2, skin->prefcolor);
+			player->skincolor = newcolor = skin->prefcolor;
+		}
+
+		if (player->followmobj)
+		{
+			P_RemoveMobj(player->followmobj);
+			P_SetTarget(&player->followmobj, NULL);
+		}
+
+		if (player->mo)
+		{
+			fixed_t radius = FixedMul(skin->radius, player->mo->scale);
+			if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (skin->sprites[SPR2_NFLY].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin.
+			{
+				skin = &skins[DEFAULTNIGHTSSKIN];
+				player->followitem = skin->followitem;
+				if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback))
+					newcolor = skin->prefcolor; // will be updated in thinker to flashing
+			}
+			player->mo->skin = skin;
+			if (newcolor)
+				player->mo->color = newcolor;
+			P_SetScale(player->mo, player->mo->scale);
+			player->mo->radius = radius;
+
+			P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames
+		}
+		return;
+	}
+
+	if (P_IsLocalPlayer(player))
+		CONS_Alert(CONS_WARNING, M_GetText("Requested skin %d not found\n"), skinnum);
+	else if(server || IsPlayerAdmin(consoleplayer))
+		CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum);
+	SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin
+}
+
+//
+// Add skins from a pwad, each skin preceded by 'S_SKIN' marker
+//
+
+// Does the same is in w_wad, but check only for
+// the first 6 characters (this is so we can have S_SKIN1, S_SKIN2..
+// for wad editors that don't like multiple resources of the same name)
+//
+static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
+{
+	UINT16 i;
+	const char *S_SKIN = "S_SKIN";
+	lumpinfo_t *lump_p;
+
+	// scan forward, start at <startlump>
+	if (startlump < wadfiles[wadid]->numlumps)
+	{
+		lump_p = wadfiles[wadid]->lumpinfo + startlump;
+		for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++)
+			if (memcmp(lump_p->name,S_SKIN,6)==0)
+				return i;
+	}
+	return INT16_MAX; // not found
+}
+
+#define HUDNAMEWRITE(value) STRBUFCPY(skin->hudname, value)
+
+// turn _ into spaces and . into katana dot
+#define SYMBOLCONVERT(name) for (value = name; *value; value++)\
+					{\
+						if (*value == '_') *value = ' ';\
+						else if (*value == '.') *value = '\x1E';\
+					}
+
+//
+// Patch skins from a pwad, each skin preceded by 'P_SKIN' marker
+//
+
+// Does the same is in w_wad, but check only for
+// the first 6 characters (this is so we can have P_SKIN1, P_SKIN2..
+// for wad editors that don't like multiple resources of the same name)
+//
+static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
+{
+	UINT16 i;
+	const char *P_SKIN = "P_SKIN";
+	lumpinfo_t *lump_p;
+
+	// scan forward, start at <startlump>
+	if (startlump < wadfiles[wadid]->numlumps)
+	{
+		lump_p = wadfiles[wadid]->lumpinfo + startlump;
+		for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++)
+			if (memcmp(lump_p->name,P_SKIN,6)==0)
+				return i;
+	}
+	return INT16_MAX; // not found
+}
+
+static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin)
+{
+	UINT16 newlastlump;
+	UINT8 sprite2;
+
+	*lump += 1; // start after S_SKIN
+	*lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END
+
+	// old wadding practices die hard -- stop at S_SKIN (or P_SKIN) or S_START if they come before S_END.
+	newlastlump = W_CheckForSkinMarkerInPwad(wadnum,*lump);
+	if (newlastlump < *lastlump) *lastlump = newlastlump;
+	newlastlump = W_CheckForPatchSkinMarkerInPwad(wadnum,*lump);
+	if (newlastlump < *lastlump) *lastlump = newlastlump;
+	newlastlump = W_CheckNumForNamePwad("S_START",wadnum,*lump);
+	if (newlastlump < *lastlump) *lastlump = newlastlump;
+
+	// ...and let's handle super, too
+	newlastlump = W_CheckNumForNamePwad("S_SUPER",wadnum,*lump);
+	if (newlastlump < *lastlump)
+	{
+		newlastlump++;
+		// load all sprite sets we are aware of... for super!
+		for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
+			R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump);
+
+		newlastlump--;
+		*lastlump = newlastlump; // okay, make the normal sprite set loading end there
+	}
+
+	// load all sprite sets we are aware of... for normal stuff.
+	for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
+		R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[sprite2], wadnum, *lump, *lastlump);
+
+	if (skin->sprites[0].numframes == 0)
+		I_Error("R_LoadSkinSprites: no frames found for sprite SPR2_%s\n", spr2names[0]);
+}
+
+// returns whether found appropriate property
+static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
+{
+	// custom translation table
+	if (!stricmp(stoken, "startcolor"))
+		skin->starttranscolor = atoi(value);
+
+#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value);
+	// character type identification
+	FULLPROCESS(flags)
+	FULLPROCESS(ability)
+	FULLPROCESS(ability2)
+
+	FULLPROCESS(thokitem)
+	FULLPROCESS(spinitem)
+	FULLPROCESS(revitem)
+	FULLPROCESS(followitem)
+#undef FULLPROCESS
+
+#define GETFRACBITS(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value)<<FRACBITS;
+	GETFRACBITS(normalspeed)
+	GETFRACBITS(runspeed)
+
+	GETFRACBITS(mindash)
+	GETFRACBITS(maxdash)
+	GETFRACBITS(actionspd)
+
+	GETFRACBITS(radius)
+	GETFRACBITS(height)
+	GETFRACBITS(spinheight)
+#undef GETFRACBITS
+
+#define GETINT(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value);
+	GETINT(thrustfactor)
+	GETINT(accelstart)
+	GETINT(acceleration)
+	GETINT(contspeed)
+	GETINT(contangle)
+#undef GETINT
+
+#define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) skin->field = R_GetColorByName(value);
+	GETSKINCOLOR(prefcolor)
+	GETSKINCOLOR(prefoppositecolor)
+#undef GETSKINCOLOR
+	else if (!stricmp(stoken, "supercolor"))
+		skin->supercolor = R_GetSuperColorByName(value);
+
+#define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value));
+	GETFLOAT(jumpfactor)
+	GETFLOAT(highresscale)
+	GETFLOAT(shieldscale)
+	GETFLOAT(camerascale)
+#undef GETFLOAT
+
+#define GETFLAG(field) else if (!stricmp(stoken, #field)) { \
+	strupr(value); \
+	if (atoi(value) || value[0] == 'T' || value[0] == 'Y') \
+		skin->flags |= (SF_##field); \
+	else \
+		skin->flags &= ~(SF_##field); \
+}
+	// parameters for individual character flags
+	// these are uppercase so they can be concatenated with SF_
+	// 1, true, yes are all valid values
+	GETFLAG(SUPER)
+	GETFLAG(NOSUPERSPIN)
+	GETFLAG(NOSPINDASHDUST)
+	GETFLAG(HIRES)
+	GETFLAG(NOSKID)
+	GETFLAG(NOSPEEDADJUST)
+	GETFLAG(RUNONWATER)
+	GETFLAG(NOJUMPSPIN)
+	GETFLAG(NOJUMPDAMAGE)
+	GETFLAG(STOMPDAMAGE)
+	GETFLAG(MARIODAMAGE)
+	GETFLAG(MACHINE)
+	GETFLAG(DASHMODE)
+	GETFLAG(FASTEDGE)
+	GETFLAG(MULTIABILITY)
+	GETFLAG(NONIGHTSROTATION)
+#undef GETFLAG
+
+	else // let's check if it's a sound, otherwise error out
+	{
+		boolean found = false;
+		sfxenum_t i;
+		size_t stokenadjust;
+
+		// Remove the prefix. (We need to affect an adjusting variable so that we can print error messages if it's not actually a sound.)
+		if ((stoken[0] == 'D' || stoken[0] == 'd') && (stoken[1] == 'S' || stoken[1] == 's')) // DS*
+			stokenadjust = 2;
+		else // sfx_*
+			stokenadjust = 4;
+
+		// Remove the prefix. (We can affect this directly since we're not going to use it again.)
+		if ((value[0] == 'D' || value[0] == 'd') && (value[1] == 'S' || value[1] == 's')) // DS*
+			value += 2;
+		else // sfx_*
+			value += 4;
+
+		// copy name of sounds that are remapped
+		// for this skin
+		for (i = 0; i < sfx_skinsoundslot0; i++)
+		{
+			if (!S_sfx[i].name)
+				continue;
+			if (S_sfx[i].skinsound != -1
+				&& !stricmp(S_sfx[i].name,
+					stoken + stokenadjust))
+			{
+				skin->soundsid[S_sfx[i].skinsound] =
+					S_AddSoundFx(value, S_sfx[i].singularity, S_sfx[i].pitch, true);
+				found = true;
+			}
+		}
+		return found;
+	}
+	return true;
+}
+
+//
+// Find skin sprites, sounds & optional status bar face, & add them
+//
+void R_AddSkins(UINT16 wadnum)
+{
+	UINT16 lump, lastlump = 0;
+	char *buf;
+	char *buf2;
+	char *stoken;
+	char *value;
+	size_t size;
+	skin_t *skin;
+	boolean hudname, realname;
+
+	//
+	// search for all skin markers in pwad
+	//
+
+	while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX)
+	{
+		// advance by default
+		lastlump = lump + 1;
+
+		if (numskins >= MAXSKINS)
+		{
+			CONS_Debug(DBG_RENDER, "ignored skin (%d skins maximum)\n", MAXSKINS);
+			continue; // so we know how many skins couldn't be added
+		}
+		buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
+		size = W_LumpLengthPwad(wadnum, lump);
+
+		// for strtok
+		buf2 = malloc(size+1);
+		if (!buf2)
+			I_Error("R_AddSkins: No more free memory\n");
+		M_Memcpy(buf2,buf,size);
+		buf2[size] = '\0';
+
+		// set defaults
+		skin = &skins[numskins];
+		Sk_SetDefaultValue(skin);
+		skin->wadnum = wadnum;
+		hudname = realname = false;
+		// parse
+		stoken = strtok (buf2, "\r\n= ");
+		while (stoken)
+		{
+			if ((stoken[0] == '/' && stoken[1] == '/')
+				|| (stoken[0] == '#'))// skip comments
+			{
+				stoken = strtok(NULL, "\r\n"); // skip end of line
+				goto next_token;              // find the real next token
+			}
+
+			value = strtok(NULL, "\r\n= ");
+
+			if (!value)
+				I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename);
+
+			// Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines.
+			// Others can't go in there because we don't want them to be patchable.
+			if (!stricmp(stoken, "name"))
+			{
+				INT32 skinnum = R_SkinAvailable(value);
+				strlwr(value);
+				if (skinnum == -1)
+					STRBUFCPY(skin->name, value);
+				// the skin name must uniquely identify a single skin
+				// if the name is already used I make the name 'namex'
+				// using the default skin name's number set above
+				else
+				{
+					const size_t stringspace =
+						strlen(value) + sizeof (numskins) + 1;
+					char *value2 = Z_Malloc(stringspace, PU_STATIC, NULL);
+					snprintf(value2, stringspace,
+						"%s%d", value, numskins);
+					value2[stringspace - 1] = '\0';
+					if (R_SkinAvailable(value2) == -1)
+						// I'm lazy so if NEW name is already used I leave the 'skin x'
+						// default skin name set in Sk_SetDefaultValue
+						STRBUFCPY(skin->name, value2);
+					Z_Free(value2);
+				}
+
+				// copy to hudname and fullname as a default.
+				if (!realname)
+				{
+					STRBUFCPY(skin->realname, skin->name);
+					for (value = skin->realname; *value; value++)
+					{
+						if (*value == '_') *value = ' '; // turn _ into spaces.
+						else if (*value == '.') *value = '\x1E'; // turn . into katana dot.
+					}
+				}
+				if (!hudname)
+				{
+					HUDNAMEWRITE(skin->name);
+					strupr(skin->hudname);
+					SYMBOLCONVERT(skin->hudname)
+				}
+			}
+			else if (!stricmp(stoken, "realname"))
+			{ // Display name (eg. "Knuckles")
+				realname = true;
+				STRBUFCPY(skin->realname, value);
+				SYMBOLCONVERT(skin->realname)
+				if (!hudname)
+					HUDNAMEWRITE(skin->realname);
+			}
+			else if (!stricmp(stoken, "hudname"))
+			{ // Life icon name (eg. "K.T.E")
+				hudname = true;
+				HUDNAMEWRITE(value);
+				SYMBOLCONVERT(skin->hudname)
+				if (!realname)
+					STRBUFCPY(skin->realname, skin->hudname);
+			}
+			else if (!stricmp(stoken, "availability"))
+			{
+				skin->availability = atoi(value);
+				if (skin->availability >= MAXUNLOCKABLES)
+					skin->availability = 0;
+			}
+			else if (!R_ProcessPatchableFields(skin, stoken, value))
+				CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename);
+
+next_token:
+			stoken = strtok(NULL, "\r\n= ");
+		}
+		free(buf2);
+
+		// Add sprites
+		R_LoadSkinSprites(wadnum, &lump, &lastlump, skin);
+		//ST_LoadFaceGraphics(numskins); -- nah let's do this elsewhere
+
+		R_FlushTranslationColormapCache();
+
+		if (!skin->availability) // Safe to print...
+			CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name);
+#ifdef SKINVALUES
+		skin_cons_t[numskins].value = numskins;
+		skin_cons_t[numskins].strvalue = skin->name;
+#endif
+
+#ifdef HWRENDER
+		if (rendermode == render_opengl)
+			HWR_AddPlayerModel(numskins);
+#endif
+
+		numskins++;
+	}
+	return;
+}
+
+//
+// Patch skin sprites
+//
+void R_PatchSkins(UINT16 wadnum)
+{
+	UINT16 lump, lastlump = 0;
+	char *buf;
+	char *buf2;
+	char *stoken;
+	char *value;
+	size_t size;
+	skin_t *skin;
+	boolean noskincomplain, realname, hudname;
+
+	//
+	// search for all skin patch markers in pwad
+	//
+
+	while ((lump = W_CheckForPatchSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX)
+	{
+		INT32 skinnum = 0;
+
+		// advance by default
+		lastlump = lump + 1;
+
+		buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
+		size = W_LumpLengthPwad(wadnum, lump);
+
+		// for strtok
+		buf2 = malloc(size+1);
+		if (!buf2)
+			I_Error("R_PatchSkins: No more free memory\n");
+		M_Memcpy(buf2,buf,size);
+		buf2[size] = '\0';
+
+		skin = NULL;
+		noskincomplain = realname = hudname = false;
+
+		/*
+		Parse. Has more phases than the parser in R_AddSkins because it needs to have the patching name first (no default skin name is acceptible for patching, unlike skin creation)
+		*/
+
+		stoken = strtok(buf2, "\r\n= ");
+		while (stoken)
+		{
+			if ((stoken[0] == '/' && stoken[1] == '/')
+				|| (stoken[0] == '#'))// skip comments
+			{
+				stoken = strtok(NULL, "\r\n"); // skip end of line
+				goto next_token;              // find the real next token
+			}
+
+			value = strtok(NULL, "\r\n= ");
+
+			if (!value)
+				I_Error("R_PatchSkins: syntax error in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename);
+
+			if (!skin) // Get the name!
+			{
+				if (!stricmp(stoken, "name"))
+				{
+					strlwr(value);
+					skinnum = R_SkinAvailable(value);
+					if (skinnum != -1)
+						skin = &skins[skinnum];
+					else
+					{
+						CONS_Debug(DBG_SETUP, "R_PatchSkins: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename);
+						noskincomplain = true;
+					}
+				}
+			}
+			else // Get the properties!
+			{
+				// Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines.
+				if (!stricmp(stoken, "realname"))
+				{ // Display name (eg. "Knuckles")
+					realname = true;
+					STRBUFCPY(skin->realname, value);
+					SYMBOLCONVERT(skin->realname)
+					if (!hudname)
+						HUDNAMEWRITE(skin->realname);
+				}
+				else if (!stricmp(stoken, "hudname"))
+				{ // Life icon name (eg. "K.T.E")
+					hudname = true;
+					HUDNAMEWRITE(value);
+					SYMBOLCONVERT(skin->hudname)
+					if (!realname)
+						STRBUFCPY(skin->realname, skin->hudname);
+				}
+				else if (!R_ProcessPatchableFields(skin, stoken, value))
+					CONS_Debug(DBG_SETUP, "R_PatchSkins: Unknown keyword '%s' in P_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename);
+			}
+
+			if (!skin)
+				break;
+
+next_token:
+			stoken = strtok(NULL, "\r\n= ");
+		}
+		free(buf2);
+
+		if (!skin) // Didn't include a name parameter? What a waste.
+		{
+			if (!noskincomplain)
+				CONS_Debug(DBG_SETUP, "R_PatchSkins: no skin name given in P_SKIN lump #%d (WAD %s)\n", lump, wadfiles[wadnum]->filename);
+			continue;
+		}
+
+		// Patch sprites
+		R_LoadSkinSprites(wadnum, &lump, &lastlump, skin);
+		//ST_LoadFaceGraphics(skinnum); -- nah let's do this elsewhere
+
+		R_FlushTranslationColormapCache();
+
+		if (!skin->availability) // Safe to print...
+			CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name);
+	}
+	return;
+}
+
+#undef HUDNAMEWRITE
+#undef SYMBOLCONVERT
diff --git a/src/r_skins.h b/src/r_skins.h
new file mode 100644
index 000000000..4b83966ac
--- /dev/null
+++ b/src/r_skins.h
@@ -0,0 +1,102 @@
+// SONIC ROBO BLAST 2
+//-----------------------------------------------------------------------------
+// Copyright (C) 1993-1996 by id Software, Inc.
+// Copyright (C) 1998-2000 by DooM Legacy Team.
+// Copyright (C) 1999-2020 by Sonic Team Junior.
+//
+// This program is free software distributed under the
+// terms of the GNU General Public License, version 2.
+// See the 'LICENSE' file for more details.
+//-----------------------------------------------------------------------------
+/// \file  r_skins.h
+/// \brief Skins stuff
+
+#ifndef __R_SKINS__
+#define __R_SKINS__
+
+#include "info.h"
+#include "sounds.h"
+#include "r_patch.h" // spriteinfo_t
+#include "r_defs.h" // spritedef_t
+
+/// Defaults
+#define SKINNAMESIZE 16
+// should be all lowercase!! S_SKIN processing does a strlwr
+#define DEFAULTSKIN "sonic"
+#define DEFAULTSKIN2 "tails" // secondary player
+#define DEFAULTNIGHTSSKIN 0
+
+/// The skin_t struct
+typedef struct
+{
+	char name[SKINNAMESIZE+1]; // INT16 descriptive name of the skin
+	UINT16 wadnum;
+	skinflags_t flags;
+
+	char realname[SKINNAMESIZE+1]; // Display name for level completion.
+	char hudname[SKINNAMESIZE+1]; // HUD name to display (officially exactly 5 characters long)
+
+	UINT8 ability; // ability definition
+	UINT8 ability2; // secondary ability definition
+	INT32 thokitem;
+	INT32 spinitem;
+	INT32 revitem;
+	INT32 followitem;
+	fixed_t actionspd;
+	fixed_t mindash;
+	fixed_t maxdash;
+
+	fixed_t normalspeed; // Normal ground
+	fixed_t runspeed; // Speed that you break into your run animation
+
+	UINT8 thrustfactor; // Thrust = thrustfactor * acceleration
+	UINT8 accelstart; // Acceleration if speed = 0
+	UINT8 acceleration; // Acceleration
+
+	fixed_t jumpfactor; // multiple of standard jump height
+
+	fixed_t radius; // Bounding box changes.
+	fixed_t height;
+	fixed_t spinheight;
+
+	fixed_t shieldscale; // no change to bounding box, but helps set the shield's sprite size
+	fixed_t camerascale;
+
+	// Definable color translation table
+	UINT8 starttranscolor;
+	UINT8 prefcolor;
+	UINT8 supercolor;
+	UINT8 prefoppositecolor; // if 0 use tables instead
+
+	fixed_t highresscale; // scale of highres, default is 0.5
+	UINT8 contspeed; // continue screen animation speed
+	UINT8 contangle; // initial angle on continue screen
+
+	// specific sounds per skin
+	sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
+
+	// contains super versions too
+	spritedef_t sprites[NUMPLAYERSPRITES*2];
+	spriteinfo_t sprinfo[NUMPLAYERSPRITES*2];
+
+	UINT8 availability; // lock?
+} skin_t;
+
+/// Externs
+extern INT32 numskins;
+extern skin_t skins[MAXSKINS];
+
+/// Function prototypes
+void R_InitSkins(void);
+
+void SetPlayerSkin(INT32 playernum,const char *skinname);
+void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002
+boolean R_SkinUsable(INT32 playernum, INT32 skinnum);
+UINT32 R_GetSkinAvailabilities(void);
+INT32 R_SkinAvailable(const char *name);
+void R_PatchSkins(UINT16 wadnum);
+void R_AddSkins(UINT16 wadnum);
+
+UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player);
+
+#endif //__R_SKINS__
diff --git a/src/r_things.c b/src/r_things.c
index 953825d0f..17a5f0809 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -30,11 +30,8 @@
 #include "p_tick.h"
 #include "p_local.h"
 #include "p_slopes.h"
-#include "dehacked.h" // get_number (for thok)
 #include "d_netfil.h" // blargh. for nameonly().
 #include "m_cheat.h" // objectplace
-#include "m_cond.h"
-#include "fastcmp.h"
 #ifdef HWRENDER
 #include "hardware/hw_md2.h"
 #include "hardware/hw_glob.h"
@@ -42,14 +39,6 @@
 #include "hardware/hw_drv.h"
 #endif
 
-#ifdef PC_DOS
-#include <stdio.h> // for snprintf
-int	snprintf(char *str, size_t n, const char *fmt, ...);
-//int	vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
-#endif
-
-static void R_InitSkins(void);
-
 #define MINZ (FRACUNIT*4)
 #define BASEYCENTER (BASEVIDHEIGHT/2)
 
@@ -233,7 +222,7 @@ static void R_InstallSpriteLump(UINT16 wad,            // graphics patch
 //
 // Returns true if the sprite was succesfully added
 //
-static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump)
+boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump)
 {
 	UINT16 l;
 	UINT8 frame;
@@ -2971,788 +2960,4 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks)
 //
 // ==========================================================================
 
-INT32 numskins = 0;
-skin_t skins[MAXSKINS];
-// FIXTHIS: don't work because it must be inistilised before the config load
-//#define SKINVALUES
-#ifdef SKINVALUES
-CV_PossibleValue_t skin_cons_t[MAXSKINS+1];
-#endif
-
-//
-// P_GetSkinSprite2
-// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing.
-// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version.
-//
-
-UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player)
-{
-	UINT8 super = 0, i = 0;
-
-	if (!skin)
-		return 0;
-
-	if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2)
-		return 0;
-
-	while (!skin->sprites[spr2].numframes
-		&& spr2 != SPR2_STND
-		&& ++i < 32) // recursion limiter
-	{
-		if (spr2 & FF_SPR2SUPER)
-		{
-			super = FF_SPR2SUPER;
-			spr2 &= ~FF_SPR2SUPER;
-			continue;
-		}
-
-		switch(spr2)
-		{
-		// Normal special cases.
-		case SPR2_JUMP:
-			spr2 = ((player
-					? player->charflags
-					: skin->flags)
-					& SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL;
-			break;
-		case SPR2_TIRE:
-			spr2 = ((player
-					? player->charability
-					: skin->ability)
-					== CA_SWIM) ? SPR2_SWIM : SPR2_FLY;
-			break;
-		// Use the handy list, that's what it's there for!
-		default:
-			spr2 = spr2defaults[spr2];
-			break;
-		}
-
-		spr2 |= super;
-	}
-
-	if (i >= 32) // probably an infinite loop...
-		return 0;
-
-	return spr2;
-}
-
-static void Sk_SetDefaultValue(skin_t *skin)
-{
-	INT32 i;
-	//
-	// set default skin values
-	//
-	memset(skin, 0, sizeof (skin_t));
-	snprintf(skin->name,
-		sizeof skin->name, "skin %u", (UINT32)(skin-skins));
-	skin->name[sizeof skin->name - 1] = '\0';
-	skin->wadnum = INT16_MAX;
-
-	skin->flags = 0;
-
-	strcpy(skin->realname, "Someone");
-	strcpy(skin->hudname, "???");
-
-	skin->starttranscolor = 96;
-	skin->prefcolor = SKINCOLOR_GREEN;
-	skin->supercolor = SKINCOLOR_SUPERGOLD1;
-	skin->prefoppositecolor = 0; // use tables
-
-	skin->normalspeed = 36<<FRACBITS;
-	skin->runspeed = 28<<FRACBITS;
-	skin->thrustfactor = 5;
-	skin->accelstart = 96;
-	skin->acceleration = 40;
-
-	skin->ability = CA_NONE;
-	skin->ability2 = CA2_SPINDASH;
-	skin->jumpfactor = FRACUNIT;
-	skin->actionspd = 30<<FRACBITS;
-	skin->mindash = 15<<FRACBITS;
-	skin->maxdash = 70<<FRACBITS;
-
-	skin->radius = mobjinfo[MT_PLAYER].radius;
-	skin->height = mobjinfo[MT_PLAYER].height;
-	skin->spinheight = FixedMul(skin->height, 2*FRACUNIT/3);
-
-	skin->shieldscale = FRACUNIT;
-	skin->camerascale = FRACUNIT;
-
-	skin->thokitem = -1;
-	skin->spinitem = -1;
-	skin->revitem = -1;
-	skin->followitem = 0;
-
-	skin->highresscale = FRACUNIT;
-	skin->contspeed = 17;
-	skin->contangle = 0;
-
-	skin->availability = 0;
-
-	for (i = 0; i < sfx_skinsoundslot0; i++)
-		if (S_sfx[i].skinsound != -1)
-			skin->soundsid[S_sfx[i].skinsound] = i;
-}
-
-//
-// Initialize the basic skins
-//
-void R_InitSkins(void)
-{
-#ifdef SKINVALUES
-	INT32 i;
-
-	for (i = 0; i <= MAXSKINS; i++)
-	{
-		skin_cons_t[i].value = 0;
-		skin_cons_t[i].strvalue = NULL;
-	}
-#endif
-
-	// no default skin!
-	numskins = 0;
-}
-
-UINT32 R_GetSkinAvailabilities(void)
-{
-	INT32 s;
-	UINT32 response = 0;
-
-	for (s = 0; s < MAXSKINS; s++)
-	{
-		if (skins[s].availability && unlockables[skins[s].availability - 1].unlocked)
-			response |= (1 << s);
-	}
-	return response;
-}
-
-// returns true if available in circumstances, otherwise nope
-// warning don't use with an invalid skinnum other than -1 which always returns true
-boolean R_SkinUsable(INT32 playernum, INT32 skinnum)
-{
-	return ((skinnum == -1) // Simplifies things elsewhere, since there's already plenty of checks for less-than-0...
-		|| (!skins[skinnum].availability)
-		|| (((netgame || multiplayer) && playernum != -1) ? (players[playernum].availabilities & (1 << skinnum)) : (unlockables[skins[skinnum].availability - 1].unlocked))
-		|| (modeattacking) // If you have someone else's run you might as well take a look
-		|| (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) // Force 1.
-		|| (netgame && (cv_forceskin.value == skinnum)) // Force 2.
-		|| (metalrecording && skinnum == 5) // Force 3.
-		);
-}
-
-// returns true if the skin name is found (loaded from pwad)
-// warning return -1 if not found
-INT32 R_SkinAvailable(const char *name)
-{
-	INT32 i;
-
-	for (i = 0; i < numskins; i++)
-	{
-		// search in the skin list
-		if (stricmp(skins[i].name,name)==0)
-			return i;
-	}
-	return -1;
-}
-
-// network code calls this when a 'skin change' is received
-void SetPlayerSkin(INT32 playernum, const char *skinname)
-{
-	INT32 i = R_SkinAvailable(skinname);
-	player_t *player = &players[playernum];
-
-	if ((i != -1) && R_SkinUsable(playernum, i))
-	{
-		SetPlayerSkinByNum(playernum, i);
-		return;
-	}
-
-	if (P_IsLocalPlayer(player))
-		CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname);
-	else if(server || IsPlayerAdmin(consoleplayer))
-		CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname);
-
-	SetPlayerSkinByNum(playernum, 0);
-}
-
-// Same as SetPlayerSkin, but uses the skin #.
-// network code calls this when a 'skin change' is received
-void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
-{
-	player_t *player = &players[playernum];
-	skin_t *skin = &skins[skinnum];
-	UINT8 newcolor = 0;
-
-	if (skinnum >= 0 && skinnum < numskins && R_SkinUsable(playernum, skinnum)) // Make sure it exists!
-	{
-		player->skin = skinnum;
-
-		player->camerascale = skin->camerascale;
-		player->shieldscale = skin->shieldscale;
-
-		player->charability = (UINT8)skin->ability;
-		player->charability2 = (UINT8)skin->ability2;
-
-		player->charflags = (UINT32)skin->flags;
-
-		player->thokitem = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem;
-		player->spinitem = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem;
-		player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem;
-		player->followitem = skin->followitem;
-
-		if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->revitem == MT_LHRT || player->spinitem == MT_LHRT || player->thokitem == MT_LHRT)) // Healers can't keep their buff.
-			player->powers[pw_shield] &= SH_STACK;
-
-		player->actionspd = skin->actionspd;
-		player->mindash = skin->mindash;
-		player->maxdash = skin->maxdash;
-
-		player->normalspeed = skin->normalspeed;
-		player->runspeed = skin->runspeed;
-		player->thrustfactor = skin->thrustfactor;
-		player->accelstart = skin->accelstart;
-		player->acceleration = skin->acceleration;
-
-		player->jumpfactor = skin->jumpfactor;
-
-		player->height = skin->height;
-		player->spinheight = skin->spinheight;
-
-		if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback))
-		{
-			if (playernum == consoleplayer)
-				CV_StealthSetValue(&cv_playercolor, skin->prefcolor);
-			else if (playernum == secondarydisplayplayer)
-				CV_StealthSetValue(&cv_playercolor2, skin->prefcolor);
-			player->skincolor = newcolor = skin->prefcolor;
-		}
-
-		if (player->followmobj)
-		{
-			P_RemoveMobj(player->followmobj);
-			P_SetTarget(&player->followmobj, NULL);
-		}
-
-		if (player->mo)
-		{
-			fixed_t radius = FixedMul(skin->radius, player->mo->scale);
-			if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (skin->sprites[SPR2_NFLY].numframes == 0)) // If you don't have a sprite for flying horizontally, use the default NiGHTS skin.
-			{
-				skin = &skins[DEFAULTNIGHTSSKIN];
-				player->followitem = skin->followitem;
-				if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback))
-					newcolor = skin->prefcolor; // will be updated in thinker to flashing
-			}
-			player->mo->skin = skin;
-			if (newcolor)
-				player->mo->color = newcolor;
-			P_SetScale(player->mo, player->mo->scale);
-			player->mo->radius = radius;
-
-			P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames
-		}
-		return;
-	}
-
-	if (P_IsLocalPlayer(player))
-		CONS_Alert(CONS_WARNING, M_GetText("Requested skin %d not found\n"), skinnum);
-	else if(server || IsPlayerAdmin(consoleplayer))
-		CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum);
-	SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin
-}
-
-//
-// Add skins from a pwad, each skin preceded by 'S_SKIN' marker
-//
-
-// Does the same is in w_wad, but check only for
-// the first 6 characters (this is so we can have S_SKIN1, S_SKIN2..
-// for wad editors that don't like multiple resources of the same name)
-//
-static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
-{
-	UINT16 i;
-	const char *S_SKIN = "S_SKIN";
-	lumpinfo_t *lump_p;
-
-	// scan forward, start at <startlump>
-	if (startlump < wadfiles[wadid]->numlumps)
-	{
-		lump_p = wadfiles[wadid]->lumpinfo + startlump;
-		for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++)
-			if (memcmp(lump_p->name,S_SKIN,6)==0)
-				return i;
-	}
-	return INT16_MAX; // not found
-}
-
-#define HUDNAMEWRITE(value) STRBUFCPY(skin->hudname, value)
-
-// turn _ into spaces and . into katana dot
-#define SYMBOLCONVERT(name) for (value = name; *value; value++)\
-					{\
-						if (*value == '_') *value = ' ';\
-						else if (*value == '.') *value = '\x1E';\
-					}
-
-//
-// Patch skins from a pwad, each skin preceded by 'P_SKIN' marker
-//
-
-// Does the same is in w_wad, but check only for
-// the first 6 characters (this is so we can have P_SKIN1, P_SKIN2..
-// for wad editors that don't like multiple resources of the same name)
-//
-static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump)
-{
-	UINT16 i;
-	const char *P_SKIN = "P_SKIN";
-	lumpinfo_t *lump_p;
-
-	// scan forward, start at <startlump>
-	if (startlump < wadfiles[wadid]->numlumps)
-	{
-		lump_p = wadfiles[wadid]->lumpinfo + startlump;
-		for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++)
-			if (memcmp(lump_p->name,P_SKIN,6)==0)
-				return i;
-	}
-	return INT16_MAX; // not found
-}
-
-static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin)
-{
-	UINT16 newlastlump;
-	UINT8 sprite2;
-
-	*lump += 1; // start after S_SKIN
-	*lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END
-
-	// old wadding practices die hard -- stop at S_SKIN (or P_SKIN) or S_START if they come before S_END.
-	newlastlump = W_CheckForSkinMarkerInPwad(wadnum,*lump);
-	if (newlastlump < *lastlump) *lastlump = newlastlump;
-	newlastlump = W_CheckForPatchSkinMarkerInPwad(wadnum,*lump);
-	if (newlastlump < *lastlump) *lastlump = newlastlump;
-	newlastlump = W_CheckNumForNamePwad("S_START",wadnum,*lump);
-	if (newlastlump < *lastlump) *lastlump = newlastlump;
-
-	// ...and let's handle super, too
-	newlastlump = W_CheckNumForNamePwad("S_SUPER",wadnum,*lump);
-	if (newlastlump < *lastlump)
-	{
-		newlastlump++;
-		// load all sprite sets we are aware of... for super!
-		for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
-			R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump);
-
-		newlastlump--;
-		*lastlump = newlastlump; // okay, make the normal sprite set loading end there
-	}
-
-	// load all sprite sets we are aware of... for normal stuff.
-	for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
-		R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[sprite2], wadnum, *lump, *lastlump);
-
-	if (skin->sprites[0].numframes == 0)
-		I_Error("R_LoadSkinSprites: no frames found for sprite SPR2_%s\n", spr2names[0]);
-}
-
-// returns whether found appropriate property
-static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value)
-{
-	// custom translation table
-	if (!stricmp(stoken, "startcolor"))
-		skin->starttranscolor = atoi(value);
-
-#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value);
-	// character type identification
-	FULLPROCESS(flags)
-	FULLPROCESS(ability)
-	FULLPROCESS(ability2)
-
-	FULLPROCESS(thokitem)
-	FULLPROCESS(spinitem)
-	FULLPROCESS(revitem)
-	FULLPROCESS(followitem)
-#undef FULLPROCESS
-
-#define GETFRACBITS(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value)<<FRACBITS;
-	GETFRACBITS(normalspeed)
-	GETFRACBITS(runspeed)
-
-	GETFRACBITS(mindash)
-	GETFRACBITS(maxdash)
-	GETFRACBITS(actionspd)
-
-	GETFRACBITS(radius)
-	GETFRACBITS(height)
-	GETFRACBITS(spinheight)
-#undef GETFRACBITS
-
-#define GETINT(field) else if (!stricmp(stoken, #field)) skin->field = atoi(value);
-	GETINT(thrustfactor)
-	GETINT(accelstart)
-	GETINT(acceleration)
-	GETINT(contspeed)
-	GETINT(contangle)
-#undef GETINT
-
-#define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) skin->field = R_GetColorByName(value);
-	GETSKINCOLOR(prefcolor)
-	GETSKINCOLOR(prefoppositecolor)
-#undef GETSKINCOLOR
-	else if (!stricmp(stoken, "supercolor"))
-		skin->supercolor = R_GetSuperColorByName(value);
-
-#define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value));
-	GETFLOAT(jumpfactor)
-	GETFLOAT(highresscale)
-	GETFLOAT(shieldscale)
-	GETFLOAT(camerascale)
-#undef GETFLOAT
-
-#define GETFLAG(field) else if (!stricmp(stoken, #field)) { \
-	strupr(value); \
-	if (atoi(value) || value[0] == 'T' || value[0] == 'Y') \
-		skin->flags |= (SF_##field); \
-	else \
-		skin->flags &= ~(SF_##field); \
-}
-	// parameters for individual character flags
-	// these are uppercase so they can be concatenated with SF_
-	// 1, true, yes are all valid values
-	GETFLAG(SUPER)
-	GETFLAG(NOSUPERSPIN)
-	GETFLAG(NOSPINDASHDUST)
-	GETFLAG(HIRES)
-	GETFLAG(NOSKID)
-	GETFLAG(NOSPEEDADJUST)
-	GETFLAG(RUNONWATER)
-	GETFLAG(NOJUMPSPIN)
-	GETFLAG(NOJUMPDAMAGE)
-	GETFLAG(STOMPDAMAGE)
-	GETFLAG(MARIODAMAGE)
-	GETFLAG(MACHINE)
-	GETFLAG(DASHMODE)
-	GETFLAG(FASTEDGE)
-	GETFLAG(MULTIABILITY)
-	GETFLAG(NONIGHTSROTATION)
-#undef GETFLAG
-
-	else // let's check if it's a sound, otherwise error out
-	{
-		boolean found = false;
-		sfxenum_t i;
-		size_t stokenadjust;
-
-		// Remove the prefix. (We need to affect an adjusting variable so that we can print error messages if it's not actually a sound.)
-		if ((stoken[0] == 'D' || stoken[0] == 'd') && (stoken[1] == 'S' || stoken[1] == 's')) // DS*
-			stokenadjust = 2;
-		else // sfx_*
-			stokenadjust = 4;
-
-		// Remove the prefix. (We can affect this directly since we're not going to use it again.)
-		if ((value[0] == 'D' || value[0] == 'd') && (value[1] == 'S' || value[1] == 's')) // DS*
-			value += 2;
-		else // sfx_*
-			value += 4;
-
-		// copy name of sounds that are remapped
-		// for this skin
-		for (i = 0; i < sfx_skinsoundslot0; i++)
-		{
-			if (!S_sfx[i].name)
-				continue;
-			if (S_sfx[i].skinsound != -1
-				&& !stricmp(S_sfx[i].name,
-					stoken + stokenadjust))
-			{
-				skin->soundsid[S_sfx[i].skinsound] =
-					S_AddSoundFx(value, S_sfx[i].singularity, S_sfx[i].pitch, true);
-				found = true;
-			}
-		}
-		return found;
-	}
-	return true;
-}
-
-//
-// Find skin sprites, sounds & optional status bar face, & add them
-//
-void R_AddSkins(UINT16 wadnum)
-{
-	UINT16 lump, lastlump = 0;
-	char *buf;
-	char *buf2;
-	char *stoken;
-	char *value;
-	size_t size;
-	skin_t *skin;
-	boolean hudname, realname;
-
-	//
-	// search for all skin markers in pwad
-	//
-
-	while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX)
-	{
-		// advance by default
-		lastlump = lump + 1;
-
-		if (numskins >= MAXSKINS)
-		{
-			CONS_Debug(DBG_RENDER, "ignored skin (%d skins maximum)\n", MAXSKINS);
-			continue; // so we know how many skins couldn't be added
-		}
-		buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
-		size = W_LumpLengthPwad(wadnum, lump);
-
-		// for strtok
-		buf2 = malloc(size+1);
-		if (!buf2)
-			I_Error("R_AddSkins: No more free memory\n");
-		M_Memcpy(buf2,buf,size);
-		buf2[size] = '\0';
-
-		// set defaults
-		skin = &skins[numskins];
-		Sk_SetDefaultValue(skin);
-		skin->wadnum = wadnum;
-		hudname = realname = false;
-		// parse
-		stoken = strtok (buf2, "\r\n= ");
-		while (stoken)
-		{
-			if ((stoken[0] == '/' && stoken[1] == '/')
-				|| (stoken[0] == '#'))// skip comments
-			{
-				stoken = strtok(NULL, "\r\n"); // skip end of line
-				goto next_token;              // find the real next token
-			}
-
-			value = strtok(NULL, "\r\n= ");
-
-			if (!value)
-				I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename);
-
-			// Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines.
-			// Others can't go in there because we don't want them to be patchable.
-			if (!stricmp(stoken, "name"))
-			{
-				INT32 skinnum = R_SkinAvailable(value);
-				strlwr(value);
-				if (skinnum == -1)
-					STRBUFCPY(skin->name, value);
-				// the skin name must uniquely identify a single skin
-				// if the name is already used I make the name 'namex'
-				// using the default skin name's number set above
-				else
-				{
-					const size_t stringspace =
-						strlen(value) + sizeof (numskins) + 1;
-					char *value2 = Z_Malloc(stringspace, PU_STATIC, NULL);
-					snprintf(value2, stringspace,
-						"%s%d", value, numskins);
-					value2[stringspace - 1] = '\0';
-					if (R_SkinAvailable(value2) == -1)
-						// I'm lazy so if NEW name is already used I leave the 'skin x'
-						// default skin name set in Sk_SetDefaultValue
-						STRBUFCPY(skin->name, value2);
-					Z_Free(value2);
-				}
-
-				// copy to hudname and fullname as a default.
-				if (!realname)
-				{
-					STRBUFCPY(skin->realname, skin->name);
-					for (value = skin->realname; *value; value++)
-					{
-						if (*value == '_') *value = ' '; // turn _ into spaces.
-						else if (*value == '.') *value = '\x1E'; // turn . into katana dot.
-					}
-				}
-				if (!hudname)
-				{
-					HUDNAMEWRITE(skin->name);
-					strupr(skin->hudname);
-					SYMBOLCONVERT(skin->hudname)
-				}
-			}
-			else if (!stricmp(stoken, "realname"))
-			{ // Display name (eg. "Knuckles")
-				realname = true;
-				STRBUFCPY(skin->realname, value);
-				SYMBOLCONVERT(skin->realname)
-				if (!hudname)
-					HUDNAMEWRITE(skin->realname);
-			}
-			else if (!stricmp(stoken, "hudname"))
-			{ // Life icon name (eg. "K.T.E")
-				hudname = true;
-				HUDNAMEWRITE(value);
-				SYMBOLCONVERT(skin->hudname)
-				if (!realname)
-					STRBUFCPY(skin->realname, skin->hudname);
-			}
-			else if (!stricmp(stoken, "availability"))
-			{
-				skin->availability = atoi(value);
-				if (skin->availability >= MAXUNLOCKABLES)
-					skin->availability = 0;
-			}
-			else if (!R_ProcessPatchableFields(skin, stoken, value))
-				CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename);
-
-next_token:
-			stoken = strtok(NULL, "\r\n= ");
-		}
-		free(buf2);
-
-		// Add sprites
-		R_LoadSkinSprites(wadnum, &lump, &lastlump, skin);
-		//ST_LoadFaceGraphics(numskins); -- nah let's do this elsewhere
-
-		R_FlushTranslationColormapCache();
-
-		if (!skin->availability) // Safe to print...
-			CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name);
-#ifdef SKINVALUES
-		skin_cons_t[numskins].value = numskins;
-		skin_cons_t[numskins].strvalue = skin->name;
-#endif
-
-#ifdef HWRENDER
-		if (rendermode == render_opengl)
-			HWR_AddPlayerModel(numskins);
-#endif
-
-		numskins++;
-	}
-	return;
-}
-
-//
-// Patch skin sprites
-//
-void R_PatchSkins(UINT16 wadnum)
-{
-	UINT16 lump, lastlump = 0;
-	char *buf;
-	char *buf2;
-	char *stoken;
-	char *value;
-	size_t size;
-	skin_t *skin;
-	boolean noskincomplain, realname, hudname;
-
-	//
-	// search for all skin patch markers in pwad
-	//
-
-	while ((lump = W_CheckForPatchSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX)
-	{
-		INT32 skinnum = 0;
-
-		// advance by default
-		lastlump = lump + 1;
-
-		buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE);
-		size = W_LumpLengthPwad(wadnum, lump);
-
-		// for strtok
-		buf2 = malloc(size+1);
-		if (!buf2)
-			I_Error("R_PatchSkins: No more free memory\n");
-		M_Memcpy(buf2,buf,size);
-		buf2[size] = '\0';
-
-		skin = NULL;
-		noskincomplain = realname = hudname = false;
-
-		/*
-		Parse. Has more phases than the parser in R_AddSkins because it needs to have the patching name first (no default skin name is acceptible for patching, unlike skin creation)
-		*/
-
-		stoken = strtok(buf2, "\r\n= ");
-		while (stoken)
-		{
-			if ((stoken[0] == '/' && stoken[1] == '/')
-				|| (stoken[0] == '#'))// skip comments
-			{
-				stoken = strtok(NULL, "\r\n"); // skip end of line
-				goto next_token;              // find the real next token
-			}
-
-			value = strtok(NULL, "\r\n= ");
-
-			if (!value)
-				I_Error("R_PatchSkins: syntax error in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename);
-
-			if (!skin) // Get the name!
-			{
-				if (!stricmp(stoken, "name"))
-				{
-					strlwr(value);
-					skinnum = R_SkinAvailable(value);
-					if (skinnum != -1)
-						skin = &skins[skinnum];
-					else
-					{
-						CONS_Debug(DBG_SETUP, "R_PatchSkins: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename);
-						noskincomplain = true;
-					}
-				}
-			}
-			else // Get the properties!
-			{
-				// Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines.
-				if (!stricmp(stoken, "realname"))
-				{ // Display name (eg. "Knuckles")
-					realname = true;
-					STRBUFCPY(skin->realname, value);
-					SYMBOLCONVERT(skin->realname)
-					if (!hudname)
-						HUDNAMEWRITE(skin->realname);
-				}
-				else if (!stricmp(stoken, "hudname"))
-				{ // Life icon name (eg. "K.T.E")
-					hudname = true;
-					HUDNAMEWRITE(value);
-					SYMBOLCONVERT(skin->hudname)
-					if (!realname)
-						STRBUFCPY(skin->realname, skin->hudname);
-				}
-				else if (!R_ProcessPatchableFields(skin, stoken, value))
-					CONS_Debug(DBG_SETUP, "R_PatchSkins: Unknown keyword '%s' in P_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename);
-			}
-
-			if (!skin)
-				break;
-
-next_token:
-			stoken = strtok(NULL, "\r\n= ");
-		}
-		free(buf2);
-
-		if (!skin) // Didn't include a name parameter? What a waste.
-		{
-			if (!noskincomplain)
-				CONS_Debug(DBG_SETUP, "R_PatchSkins: no skin name given in P_SKIN lump #%d (WAD %s)\n", lump, wadfiles[wadnum]->filename);
-			continue;
-		}
-
-		// Patch sprites
-		R_LoadSkinSprites(wadnum, &lump, &lastlump, skin);
-		//ST_LoadFaceGraphics(skinnum); -- nah let's do this elsewhere
-
-		R_FlushTranslationColormapCache();
-
-		if (!skin->availability) // Safe to print...
-			CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name);
-	}
-	return;
-}
-
-#undef HUDNAMEWRITE
-#undef SYMBOLCONVERT
+#include "r_skins.c"
diff --git a/src/r_things.h b/src/r_things.h
index bd6271b60..dd9b227f8 100644
--- a/src/r_things.h
+++ b/src/r_things.h
@@ -14,7 +14,6 @@
 #ifndef __R_THINGS__
 #define __R_THINGS__
 
-#include "sounds.h"
 #include "r_plane.h"
 #include "r_patch.h"
 #include "r_portal.h"
@@ -82,69 +81,17 @@ typedef struct
 
 void R_DrawMasked(maskcount_t* masks, UINT8 nummasks);
 
+// --------------
+// SPRITE LOADING
+// --------------
+
+boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump);
+
 // -----------
 // SKINS STUFF
 // -----------
-#define SKINNAMESIZE 16
-// should be all lowercase!! S_SKIN processing does a strlwr
-#define DEFAULTSKIN "sonic"
-#define DEFAULTSKIN2 "tails" // secondary player
-#define DEFAULTNIGHTSSKIN 0
 
-typedef struct
-{
-	char name[SKINNAMESIZE+1]; // INT16 descriptive name of the skin
-	UINT16 wadnum;
-	skinflags_t flags;
-
-	char realname[SKINNAMESIZE+1]; // Display name for level completion.
-	char hudname[SKINNAMESIZE+1]; // HUD name to display (officially exactly 5 characters long)
-
-	UINT8 ability; // ability definition
-	UINT8 ability2; // secondary ability definition
-	INT32 thokitem;
-	INT32 spinitem;
-	INT32 revitem;
-	INT32 followitem;
-	fixed_t actionspd;
-	fixed_t mindash;
-	fixed_t maxdash;
-
-	fixed_t normalspeed; // Normal ground
-	fixed_t runspeed; // Speed that you break into your run animation
-
-	UINT8 thrustfactor; // Thrust = thrustfactor * acceleration
-	UINT8 accelstart; // Acceleration if speed = 0
-	UINT8 acceleration; // Acceleration
-
-	fixed_t jumpfactor; // multiple of standard jump height
-
-	fixed_t radius; // Bounding box changes.
-	fixed_t height;
-	fixed_t spinheight;
-
-	fixed_t shieldscale; // no change to bounding box, but helps set the shield's sprite size
-	fixed_t camerascale;
-
-	// Definable color translation table
-	UINT8 starttranscolor;
-	UINT8 prefcolor;
-	UINT8 supercolor;
-	UINT8 prefoppositecolor; // if 0 use tables instead
-
-	fixed_t highresscale; // scale of highres, default is 0.5
-	UINT8 contspeed; // continue screen animation speed
-	UINT8 contangle; // initial angle on continue screen
-
-	// specific sounds per skin
-	sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table
-
-	// contains super versions too
-	spritedef_t sprites[NUMPLAYERSPRITES*2];
-	spriteinfo_t sprinfo[NUMPLAYERSPRITES*2];
-
-	UINT8 availability; // lock?
-} skin_t;
+#include "r_skins.h"
 
 // -----------
 // NOT SKINS STUFF !
@@ -241,24 +188,10 @@ typedef struct drawnode_s
 	struct drawnode_s *prev;
 } drawnode_t;
 
-extern INT32 numskins;
-extern skin_t skins[MAXSKINS];
 extern UINT32 visspritecount;
 
-void SetPlayerSkin(INT32 playernum,const char *skinname);
-void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002
-boolean R_SkinUsable(INT32 playernum, INT32 skinnum);
-UINT32 R_GetSkinAvailabilities(void);
-INT32 R_SkinAvailable(const char *name);
-void R_PatchSkins(UINT16 wadnum);
-void R_AddSkins(UINT16 wadnum);
-
-UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player);
-
 void R_InitDrawNodes(void);
 
-char *GetPlayerFacePic(INT32 skinnum);
-
 // Functions to go from sprite character ID to frame number
 // for 2.1 compatibility this still uses the old 'A' + frame code
 // The use of symbols tends to be painful for wad editors though

From b2d9697e070c8d7742fcb9b4a49592517141d256 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Sun, 8 Mar 2020 19:36:56 +0000
Subject: [PATCH 107/251] remove r_skins.c include in r_things.c, on second
 thoughts

---
 src/r_things.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/src/r_things.c b/src/r_things.c
index 17a5f0809..77418e066 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -2953,11 +2953,3 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks)
 
 	free(heads);
 }
-
-// ==========================================================================
-//
-//                              SKINS CODE
-//
-// ==========================================================================
-
-#include "r_skins.c"

From 37ecb47436854ece31d049da326bd8e622cd4586 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Sun, 8 Mar 2020 19:48:23 +0000
Subject: [PATCH 108/251] update Makefile, CMakeLists.txt and MSVC project
 files

---
 src/CMakeLists.txt                   | 2 ++
 src/Makefile                         | 1 +
 src/sdl/Srb2SDL-vc10.vcxproj         | 2 ++
 src/sdl/Srb2SDL-vc10.vcxproj.filters | 6 ++++++
 4 files changed, 11 insertions(+)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e8c9c3182..bc4a6114e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -120,6 +120,7 @@ set(SRB2_CORE_RENDER_SOURCES
 	r_main.c
 	r_plane.c
 	r_segs.c
+	r_skins.c
 	r_sky.c
 	r_splats.c
 	r_things.c
@@ -134,6 +135,7 @@ set(SRB2_CORE_RENDER_SOURCES
 	r_main.h
 	r_plane.h
 	r_segs.h
+	r_skins.h
 	r_sky.h
 	r_splats.h
 	r_state.h
diff --git a/src/Makefile b/src/Makefile
index 9f368217c..701f2cfda 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -468,6 +468,7 @@ OBJS:=$(i_main_o) \
 		$(OBJDIR)/r_main.o   \
 		$(OBJDIR)/r_plane.o  \
 		$(OBJDIR)/r_segs.o   \
+		$(OBJDIR)/r_skins.o  \
 		$(OBJDIR)/r_sky.o    \
 		$(OBJDIR)/r_splats.o \
 		$(OBJDIR)/r_things.o \
diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj
index b334f6313..7e260f4c0 100644
--- a/src/sdl/Srb2SDL-vc10.vcxproj
+++ b/src/sdl/Srb2SDL-vc10.vcxproj
@@ -284,6 +284,7 @@
     <ClInclude Include="..\r_patch.h" />
     <ClInclude Include="..\r_portal.h" />
     <ClInclude Include="..\r_segs.h" />
+    <ClInclude Include="..\r_skins.h" />
     <ClInclude Include="..\r_sky.h" />
     <ClInclude Include="..\r_splats.h" />
     <ClInclude Include="..\r_state.h" />
@@ -446,6 +447,7 @@
 	<ClCompile Include="..\r_patch.c" />
     <ClCompile Include="..\r_portal.c" />
     <ClCompile Include="..\r_segs.c" />
+    <ClCompile Include="..\r_skins.c" />
     <ClCompile Include="..\r_sky.c" />
     <ClCompile Include="..\r_splats.c" />
     <ClCompile Include="..\r_things.c" />
diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters
index 3f61e8709..21820551a 100644
--- a/src/sdl/Srb2SDL-vc10.vcxproj.filters
+++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters
@@ -417,6 +417,9 @@
     <ClInclude Include="..\r_segs.h">
       <Filter>R_Rend</Filter>
     </ClInclude>
+    <ClInclude Include="..\r_skins.h">
+      <Filter>R_Rend</Filter>
+    </ClInclude>
     <ClInclude Include="..\r_sky.h">
       <Filter>R_Rend</Filter>
     </ClInclude>
@@ -849,6 +852,9 @@
     <ClCompile Include="..\r_segs.c">
       <Filter>R_Rend</Filter>
     </ClCompile>
+    <ClCompile Include="..\r_skins.c">
+      <Filter>R_Rend</Filter>
+    </ClCompile>
     <ClCompile Include="..\r_sky.c">
       <Filter>R_Rend</Filter>
     </ClCompile>

From e81ef824d6db33e06a83cd2deedd2ed6547f441a Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Sun, 8 Mar 2020 19:51:18 +0000
Subject: [PATCH 109/251] Set the "spritename" variable within
 R_AddSingleSpriteDef rather than externally to it, since R_InstallSpriteLump
 is the only place it gets used anyway

This way we don't have to make it some extern in order for r_skins.c to use it
---
 src/r_skins.c  | 4 ++--
 src/r_things.c | 9 +++++----
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/r_skins.c b/src/r_skins.c
index 48764ff75..2e9548bd7 100644
--- a/src/r_skins.c
+++ b/src/r_skins.c
@@ -410,7 +410,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
 		newlastlump++;
 		// load all sprite sets we are aware of... for super!
 		for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
-			R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump);
+			R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump);
 
 		newlastlump--;
 		*lastlump = newlastlump; // okay, make the normal sprite set loading end there
@@ -418,7 +418,7 @@ static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, ski
 
 	// load all sprite sets we are aware of... for normal stuff.
 	for (sprite2 = 0; sprite2 < free_spr2; sprite2++)
-		R_AddSingleSpriteDef((spritename = spr2names[sprite2]), &skin->sprites[sprite2], wadnum, *lump, *lastlump);
+		R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump);
 
 	if (skin->sprites[0].numframes == 0)
 		I_Error("R_LoadSkinSprites: no frames found for sprite SPR2_%s\n", spr2names[0]);
diff --git a/src/r_things.c b/src/r_things.c
index 77418e066..2fc44faf8 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -234,6 +234,8 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
 	memset(sprtemp,0xFF, sizeof (sprtemp));
 	maxframe = (size_t)-1;
 
+	spritename = sprname;
+
 	// are we 'patching' a sprite already loaded ?
 	// if so, it might patch only certain frames, not all
 	if (spritedef->numframes) // (then spriteframes is not null)
@@ -465,11 +467,10 @@ void R_AddSpriteDefs(UINT16 wadnum)
 	//
 	for (i = 0; i < numsprites; i++)
 	{
-		spritename = sprnames[i];
-		if (spritename[4] && wadnum >= (UINT16)spritename[4])
+		if (sprnames[i][4] && wadnum >= (UINT16)sprnames[i][4])
 			continue;
 
-		if (R_AddSingleSpriteDef(spritename, &sprites[i], wadnum, start, end))
+		if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end))
 		{
 #ifdef HWRENDER
 			if (rendermode == render_opengl)
@@ -478,7 +479,7 @@ void R_AddSpriteDefs(UINT16 wadnum)
 			// if a new sprite was added (not just replaced)
 			addsprites++;
 #ifndef ZDEBUG
-			CONS_Debug(DBG_SETUP, "sprite %s set in pwad %d\n", spritename, wadnum);
+			CONS_Debug(DBG_SETUP, "sprite %s set in pwad %d\n", sprnames[i], wadnum);
 #endif
 		}
 	}

From 1dd4ed4afaa71401fad875e7e702ee8c7535eaa8 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Sun, 8 Mar 2020 21:17:30 +0000
Subject: [PATCH 110/251] Reorganise r_things.h

---
 src/r_things.h | 71 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 28 deletions(-)

diff --git a/src/r_things.h b/src/r_things.h
index dd9b227f8..05d6fb27b 100644
--- a/src/r_things.h
+++ b/src/r_things.h
@@ -18,21 +18,23 @@
 #include "r_patch.h"
 #include "r_portal.h"
 #include "r_defs.h"
+#include "r_skins.h"
 
-// number of sprite lumps for spritewidth,offset,topoffset lookup tables
-// Fab: this is a hack : should allocate the lookup tables per sprite
-#define MAXVISSPRITES 2048 // added 2-2-98 was 128
-
-#define VISSPRITECHUNKBITS 6	// 2^6 = 64 sprites per chunk
-#define VISSPRITESPERCHUNK (1 << VISSPRITECHUNKBITS)
-#define VISSPRITEINDEXMASK (VISSPRITESPERCHUNK - 1)
+// --------------
+// SPRITE LOADING
+// --------------
 
 #define FEETADJUST (4<<FRACBITS) // R_AddSingleSpriteDef
 
-// Constant arrays used for psprite clipping
-//  and initializing clipping.
-extern INT16 negonearray[MAXVIDWIDTH];
-extern INT16 screenheightarray[MAXVIDWIDTH];
+boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump);
+
+//faB: find sprites in wadfile, replace existing, add new ones
+//     (only sprites from namelist are added or replaced)
+void R_AddSpriteDefs(UINT16 wadnum);
+
+// ---------------------
+// MASKED COLUMN DRAWING
+// ---------------------
 
 // vars for R_DrawMaskedColumn
 extern INT16 *mfloorclip;
@@ -46,9 +48,14 @@ extern fixed_t windowbottom;
 void R_DrawMaskedColumn(column_t *column);
 void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight);
 
-//faB: find sprites in wadfile, replace existing, add new ones
-//     (only sprites from namelist are added or replaced)
-void R_AddSpriteDefs(UINT16 wadnum);
+// ----------------
+// SPRITE RENDERING
+// ----------------
+
+// Constant arrays used for psprite clipping
+//  and initializing clipping.
+extern INT16 negonearray[MAXVIDWIDTH];
+extern INT16 screenheightarray[MAXVIDWIDTH];
 
 fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
 
@@ -67,6 +74,9 @@ boolean R_ThingVisibleWithinDist (mobj_t *thing,
 boolean R_PrecipThingVisible (precipmobj_t *precipthing,
 		fixed_t precip_draw_dist);
 
+// --------------
+// MASKED DRAWING
+// --------------
 /** Used to count the amount of masked elements
  * per portal to later group them in separate
  * drawnode lists.
@@ -81,21 +91,18 @@ typedef struct
 
 void R_DrawMasked(maskcount_t* masks, UINT8 nummasks);
 
-// --------------
-// SPRITE LOADING
-// --------------
+// ----------
+// VISSPRITES
+// ----------
 
-boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump);
+// number of sprite lumps for spritewidth,offset,topoffset lookup tables
+// Fab: this is a hack : should allocate the lookup tables per sprite
+#define MAXVISSPRITES 2048 // added 2-2-98 was 128
 
-// -----------
-// SKINS STUFF
-// -----------
+#define VISSPRITECHUNKBITS 6	// 2^6 = 64 sprites per chunk
+#define VISSPRITESPERCHUNK (1 << VISSPRITECHUNKBITS)
+#define VISSPRITEINDEXMASK (VISSPRITESPERCHUNK - 1)
 
-#include "r_skins.h"
-
-// -----------
-// NOT SKINS STUFF !
-// -----------
 typedef enum
 {
 	// actual cuts
@@ -174,6 +181,12 @@ typedef struct vissprite_s
 	INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
 } vissprite_t;
 
+extern UINT32 visspritecount;
+
+// ----------
+// DRAW NODES
+// ----------
+
 // A drawnode is something that points to a 3D floor, 3D side, or masked
 // middle texture. This is used for sorting with sprites.
 typedef struct drawnode_s
@@ -188,10 +201,12 @@ typedef struct drawnode_s
 	struct drawnode_s *prev;
 } drawnode_t;
 
-extern UINT32 visspritecount;
-
 void R_InitDrawNodes(void);
 
+// -----------------------
+// SPRITE FRAME CHARACTERS
+// -----------------------
+
 // Functions to go from sprite character ID to frame number
 // for 2.1 compatibility this still uses the old 'A' + frame code
 // The use of symbols tends to be painful for wad editors though

From f4cb6e1f5ed149bd6484960d2329f24a50bd7e65 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Mon, 9 Mar 2020 13:54:56 +0000
Subject: [PATCH 111/251] Include r_skins.h instead of r_things.h in many files
 where all they wanted from it was skins stuff

(oddly enough, this actually revealed some secret file dependencies previously included via r_things.h! I also needed to include d_player.h in r_skins.h itself it seems)
---
 src/d_netcmd.c          | 2 +-
 src/dehacked.c          | 1 +
 src/f_wipe.c            | 1 +
 src/g_game.c            | 2 +-
 src/hardware/hw3sound.c | 2 +-
 src/lua_baselib.c       | 2 +-
 src/lua_hooklib.c       | 2 +-
 src/lua_mobjlib.c       | 2 +-
 src/lua_skinlib.c       | 2 +-
 src/m_cond.c            | 2 +-
 src/m_menu.h            | 3 ++-
 src/p_enemy.c           | 2 +-
 src/p_mobj.c            | 2 +-
 src/p_saveg.c           | 2 +-
 src/p_setup.c           | 2 +-
 src/p_spec.c            | 2 +-
 src/p_user.c            | 2 +-
 src/r_skins.h           | 1 +
 src/s_sound.c           | 2 +-
 src/sounds.c            | 2 +-
 src/y_inter.c           | 2 +-
 21 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index c25929929..a55e70287 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -22,7 +22,7 @@
 #include "g_input.h"
 #include "m_menu.h"
 #include "r_local.h"
-#include "r_things.h"
+#include "r_skins.h"
 #include "p_local.h"
 #include "p_setup.h"
 #include "s_sound.h"
diff --git a/src/dehacked.c b/src/dehacked.c
index dea0289b9..e6466f792 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -31,6 +31,7 @@
 #include "r_data.h"
 #include "r_draw.h"
 #include "r_patch.h"
+#include "r_things.h" // R_Char2Frame
 #include "r_sky.h"
 #include "fastcmp.h"
 #include "lua_script.h"
diff --git a/src/f_wipe.c b/src/f_wipe.c
index 8d12262ef..0fd6c1431 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -16,6 +16,7 @@
 #include "i_video.h"
 #include "v_video.h"
 
+#include "r_state.h" // fadecolormap
 #include "r_draw.h" // transtable
 #include "p_pspr.h" // tr_transxxx
 #include "p_local.h"
diff --git a/src/g_game.c b/src/g_game.c
index 08192bfb8..1bf76f33f 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -38,7 +38,7 @@
 #include "byteptr.h"
 #include "i_joy.h"
 #include "r_local.h"
-#include "r_things.h"
+#include "r_skins.h"
 #include "y_inter.h"
 #include "v_video.h"
 #include "dehacked.h" // get_number (for ghost thok)
diff --git a/src/hardware/hw3sound.c b/src/hardware/hw3sound.c
index f7c6e1da0..7858640c0 100644
--- a/src/hardware/hw3sound.c
+++ b/src/hardware/hw3sound.c
@@ -28,7 +28,7 @@
 #include "../tables.h"
 #include "../sounds.h"
 #include "../r_main.h"
-#include "../r_things.h"
+#include "../r_skins.h"
 #include "../m_random.h"
 #include "../p_local.h"
 #include "hw3dsdrv.h"
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 03f142446..d001408be 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -21,7 +21,7 @@
 #include "z_zone.h"
 #include "r_main.h"
 #include "r_draw.h"
-#include "r_things.h"
+#include "r_things.h" // R_Frame2Char etc
 #include "m_random.h"
 #include "s_sound.h"
 #include "g_game.h"
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index efed9adb7..92080e8ed 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -15,7 +15,7 @@
 #include "doomstat.h"
 #include "p_mobj.h"
 #include "g_game.h"
-#include "r_things.h"
+#include "r_skins.h"
 #include "b_bot.h"
 #include "z_zone.h"
 
diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c
index a7bd8da94..9e46344cf 100644
--- a/src/lua_mobjlib.c
+++ b/src/lua_mobjlib.c
@@ -13,7 +13,7 @@
 #include "doomdef.h"
 #ifdef HAVE_BLUA
 #include "fastcmp.h"
-#include "r_things.h"
+#include "r_skins.h"
 #include "p_local.h"
 #include "g_game.h"
 #include "p_setup.h"
diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c
index 3ade06042..f26aed2f0 100644
--- a/src/lua_skinlib.c
+++ b/src/lua_skinlib.c
@@ -13,7 +13,7 @@
 #include "doomdef.h"
 #ifdef HAVE_BLUA
 #include "fastcmp.h"
-#include "r_things.h"
+#include "r_skins.h"
 #include "sounds.h"
 
 #include "lua_script.h"
diff --git a/src/m_cond.c b/src/m_cond.c
index 89058a488..0abc7adf8 100644
--- a/src/m_cond.c
+++ b/src/m_cond.c
@@ -18,7 +18,7 @@
 #include "v_video.h" // video flags
 
 #include "g_game.h" // record info
-#include "r_things.h" // numskins
+#include "r_skins.h" // numskins
 #include "r_draw.h" // R_GetColorByName
 
 // Map triggers for linedef executors
diff --git a/src/m_menu.h b/src/m_menu.h
index 18b681ff0..e7270380d 100644
--- a/src/m_menu.h
+++ b/src/m_menu.h
@@ -15,9 +15,10 @@
 #ifndef __X_MENU__
 #define __X_MENU__
 
+#include "doomstat.h" // for NUMGAMETYPES
 #include "d_event.h"
 #include "command.h"
-#include "r_things.h" // for SKINNAMESIZE
+#include "r_skins.h" // for SKINNAMESIZE
 #include "f_finale.h" // for ttmode_enum
 
 //
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 5d067ebc3..14e5c4d3e 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -21,7 +21,7 @@
 #include "s_sound.h"
 #include "m_random.h"
 #include "m_misc.h"
-#include "r_things.h"
+#include "r_skins.h"
 #include "i_video.h"
 #include "z_zone.h"
 #include "lua_hook.h"
diff --git a/src/p_mobj.c b/src/p_mobj.c
index faee245d3..9194cf9f7 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -19,7 +19,7 @@
 #include "p_local.h"
 #include "p_setup.h"
 #include "r_main.h"
-#include "r_things.h"
+#include "r_skins.h"
 #include "r_sky.h"
 #include "r_splats.h"
 #include "s_sound.h"
diff --git a/src/p_saveg.c b/src/p_saveg.c
index e8c6c7a84..2cd4bbbef 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -22,7 +22,7 @@
 #include "p_setup.h"
 #include "p_saveg.h"
 #include "r_data.h"
-#include "r_things.h"
+#include "r_skins.h"
 #include "r_state.h"
 #include "w_wad.h"
 #include "y_inter.h"
diff --git a/src/p_setup.c b/src/p_setup.c
index 7b4c6773b..857bb1d43 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -27,7 +27,7 @@
 #include "i_system.h"
 
 #include "r_data.h"
-#include "r_things.h"
+#include "r_things.h" // for R_AddSpriteDefs
 #include "r_patch.h"
 #include "r_sky.h"
 #include "r_draw.h"
diff --git a/src/p_spec.c b/src/p_spec.c
index d9bbab246..aecdb3b98 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -36,7 +36,7 @@
 #include "m_cond.h" //unlock triggers
 #include "lua_hook.h" // LUAh_LinedefExecute
 #include "f_finale.h" // control text prompt
-#include "r_things.h" // skins
+#include "r_skins.h" // skins
 
 #ifdef HW3SOUND
 #include "hardware/hw3sound.h"
diff --git a/src/p_user.c b/src/p_user.c
index 9167d5345..c34d37264 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -22,7 +22,7 @@
 #include "p_local.h"
 #include "r_main.h"
 #include "s_sound.h"
-#include "r_things.h"
+#include "r_skins.h"
 #include "d_think.h"
 #include "r_sky.h"
 #include "p_setup.h"
diff --git a/src/r_skins.h b/src/r_skins.h
index 4b83966ac..96697b422 100644
--- a/src/r_skins.h
+++ b/src/r_skins.h
@@ -16,6 +16,7 @@
 
 #include "info.h"
 #include "sounds.h"
+#include "d_player.h" // skinflags
 #include "r_patch.h" // spriteinfo_t
 #include "r_defs.h" // spritedef_t
 
diff --git a/src/s_sound.c b/src/s_sound.c
index 8193fdb9b..8e9461d78 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -27,7 +27,7 @@ extern INT32 msg_id;
 #include "g_game.h"
 #include "m_argv.h"
 #include "r_main.h" // R_PointToAngle2() used to calc stereo sep.
-#include "r_things.h" // for skins
+#include "r_skins.h" // for skins
 #include "i_system.h"
 #include "i_sound.h"
 #include "s_sound.h"
diff --git a/src/sounds.c b/src/sounds.c
index a9d720d5c..ca943c2d0 100644
--- a/src/sounds.c
+++ b/src/sounds.c
@@ -15,7 +15,7 @@
 #include "i_sound.h"
 #include "sounds.h"
 #include "r_defs.h"
-#include "r_things.h"
+#include "r_skins.h"
 #include "z_zone.h"
 #include "w_wad.h"
 #include "lua_script.h"
diff --git a/src/y_inter.c b/src/y_inter.c
index 36cb64d06..6f23ef1b1 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -19,7 +19,7 @@
 #include "i_video.h"
 #include "p_tick.h"
 #include "r_defs.h"
-#include "r_things.h"
+#include "r_skins.h"
 #include "s_sound.h"
 #include "st_stuff.h"
 #include "v_video.h"

From 40e728fdb5d428532ecd5f9fa73a2ea0a4a83b73 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Mon, 9 Mar 2020 15:04:22 +0000
Subject: [PATCH 112/251] One line fix: don't assume 0 (aka SPR2_STND) is the
 default value for sprite2, but rather what the state sets for it

This fixes some issues with a custom character tested during netplay, which did not have SPR2_WAIT sprites and therefore fell back to SPR2_STND sprites. Unfortunately, the fact they used SPR2_STND instead meant the sprite2 was not synced at all!
---
 src/p_saveg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index e8c6c7a84..fc8d9d4ee 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1406,7 +1406,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 		diff |= MD_TICS;
 	if (mobj->sprite != mobj->state->sprite)
 		diff |= MD_SPRITE;
-	if (mobj->sprite == SPR_PLAY && mobj->sprite2 != 0)
+	if (mobj->sprite == SPR_PLAY && mobj->sprite2 != (mobj->state->frame&FF_FRAMEMASK))
 		diff |= MD_SPRITE;
 	if (mobj->frame != mobj->state->frame)
 		diff |= MD_FRAME;

From bdab78152cb5288cdce2303cb6f65b99b6c22129 Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Fri, 13 Mar 2020 10:46:57 -0400
Subject: [PATCH 113/251] Check if emblem hints are actually unlocked.

---
 src/m_menu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/m_menu.c b/src/m_menu.c
index 622d740e2..18f1f6c8e 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -3612,6 +3612,7 @@ void M_StartControlPanel(void)
 	else if (modeattacking)
 	{
 		currentMenu = &MAPauseDef;
+		MAPauseMenu[mapause_hints].status = (M_SecretUnlocked(SECRET_EMBLEMHINTS)) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
 		itemOn = mapause_continue;
 	}
 	else if (!(netgame || multiplayer)) // Single Player

From c2cd9a71fad89d9b57759e6567437be8958625c1 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Tue, 17 Mar 2020 13:05:54 -0300
Subject: [PATCH 114/251] Fix con_backpic

---
 src/console.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/src/console.c b/src/console.c
index f8fa1314a..e39c2f531 100644
--- a/src/console.c
+++ b/src/console.c
@@ -1553,13 +1553,28 @@ static void CON_DrawConsole(void)
 	if (cons_backpic.value || con_forcepic)
 	{
 		patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH);
-		int h;
+		int x, w, h;
 
+		w = (con_backpic->width * vid.dupx);
+		x = (vid.width / 2) - (w / 2);
 		h = con_curlines/vid.dupy;
 
-		// Jimita: CON_DrawBackpic just called V_DrawScaledPatch
-		//V_DrawScaledPatch(0, 0, 0, con_backpic);
-		V_DrawCroppedPatch(0, 0, FRACUNIT, 0, con_backpic,
+		// Lactozilla: If the patch doesn't fill the entire screen,
+		// then fill the sides with a solid color.
+		if (x > 0)
+		{
+			column_t *column = (column_t *)((UINT8 *)(con_backpic) + LONG(con_backpic->columnofs[0]));
+			if (!column->topdelta)
+			{
+				UINT8 *source = (UINT8 *)(column) + 3;
+				INT32 color = (source[0] | V_NOSCALESTART);
+				// left side
+				V_DrawFill(0, 0, x, con_curlines, color);
+				// right side
+				V_DrawFill((x + w), 0, (vid.width - w), con_curlines, color);
+			}
+		}
+		V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, V_NOSCALESTART, con_backpic,
 				0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h);
 
 		W_UnlockCachedPatch(con_backpic);

From 1904e3b5e9e1491d59cfac9df2aac9f9196c3a40 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Tue, 17 Mar 2020 15:23:13 -0300
Subject: [PATCH 115/251] Fix OpenGL

---
 src/console.c          | 75 +++++++++++++++++++++++--------------
 src/hardware/hw_draw.c |  4 +-
 src/w_wad.c            | 85 ++++++++++++++++++++++++++----------------
 src/w_wad.h            | 11 +++++-
 4 files changed, 110 insertions(+), 65 deletions(-)

diff --git a/src/console.c b/src/console.c
index e39c2f531..0f1ccbd33 100644
--- a/src/console.c
+++ b/src/console.c
@@ -97,6 +97,7 @@ static void CON_InputInit(void);
 static void CON_RecalcSize(void);
 static void CON_ChangeHeight(void);
 
+static void CON_DrawBackpic(void);
 static void CONS_hudlines_Change(void);
 static void CONS_backcolor_Change(void);
 
@@ -1530,6 +1531,51 @@ static void CON_DrawHudlines(void)
 	con_clearlines = y; // this is handled by HU_Erase();
 }
 
+// Lactozilla: Draws the console's background picture.
+static void CON_DrawBackpic(void)
+{
+	patch_t *con_backpic;
+	lumpnum_t piclump;
+	int x, w, h;
+
+	// Get the lumpnum for CONSBACK, or fallback into MISSING.
+	piclump = W_CheckNumForName("CONSBACK");
+	if (piclump == LUMPERROR)
+		piclump = W_GetNumForName("MISSING");
+
+	// Cache the Software patch.
+	con_backpic = W_CacheSoftwarePatchNum(piclump, PU_PATCH);
+
+	// Center the backpic, and draw a vertically cropped patch.
+	w = (con_backpic->width * vid.dupx);
+	x = (vid.width / 2) - (w / 2);
+	h = con_curlines/vid.dupy;
+
+	// If the patch doesn't fill the entire screen,
+	// then fill the sides with a solid color.
+	if (x > 0)
+	{
+		column_t *column = (column_t *)((UINT8 *)(con_backpic) + LONG(con_backpic->columnofs[0]));
+		if (!column->topdelta)
+		{
+			UINT8 *source = (UINT8 *)(column) + 3;
+			INT32 color = (source[0] | V_NOSCALESTART);
+			// left side
+			V_DrawFill(0, 0, x, con_curlines, color);
+			// right side
+			V_DrawFill((x + w), 0, (vid.width - w), con_curlines, color);
+		}
+	}
+
+	// Cache the patch normally.
+	con_backpic = W_CachePatchNum(piclump, PU_PATCH);
+	V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, V_NOSCALESTART, con_backpic,
+			0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h);
+
+	// Unlock the cached patch.
+	W_UnlockCachedPatch(con_backpic);
+}
+
 // draw the console background, text, and prompt if enough place
 //
 static void CON_DrawConsole(void)
@@ -1551,34 +1597,7 @@ static void CON_DrawConsole(void)
 
 	// draw console background
 	if (cons_backpic.value || con_forcepic)
-	{
-		patch_t *con_backpic = W_CachePatchName("CONSBACK", PU_PATCH);
-		int x, w, h;
-
-		w = (con_backpic->width * vid.dupx);
-		x = (vid.width / 2) - (w / 2);
-		h = con_curlines/vid.dupy;
-
-		// Lactozilla: If the patch doesn't fill the entire screen,
-		// then fill the sides with a solid color.
-		if (x > 0)
-		{
-			column_t *column = (column_t *)((UINT8 *)(con_backpic) + LONG(con_backpic->columnofs[0]));
-			if (!column->topdelta)
-			{
-				UINT8 *source = (UINT8 *)(column) + 3;
-				INT32 color = (source[0] | V_NOSCALESTART);
-				// left side
-				V_DrawFill(0, 0, x, con_curlines, color);
-				// right side
-				V_DrawFill((x + w), 0, (vid.width - w), con_curlines, color);
-			}
-		}
-		V_DrawCroppedPatch(x << FRACBITS, 0, FRACUNIT, V_NOSCALESTART, con_backpic,
-				0, ( BASEVIDHEIGHT - h ), BASEVIDWIDTH, h);
-
-		W_UnlockCachedPatch(con_backpic);
-	}
+		CON_DrawBackpic();
 	else
 	{
 		// inu: no more width (was always 0 and vid.width)
diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c
index 598a635aa..d01331765 100644
--- a/src/hardware/hw_draw.c
+++ b/src/hardware/hw_draw.c
@@ -291,7 +291,7 @@ void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t
 			if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT)
 			{
 				// Need to temporarily cache the real patch to get the colour of the top left pixel
-				patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
+				patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
 				const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
 				if (!column->topdelta)
 				{
@@ -450,7 +450,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal
 			if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT)
 			{
 				// Need to temporarily cache the real patch to get the colour of the top left pixel
-				patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
+				patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC);
 				const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0]));
 				if (!column->topdelta)
 				{
diff --git a/src/w_wad.c b/src/w_wad.c
index e96afd050..797f286d5 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -1511,6 +1511,57 @@ void *W_CacheLumpName(const char *name, INT32 tag)
 // Cache a patch into heap memory, convert the patch format as necessary
 //
 
+void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
+{
+	lumpcache_t *lumpcache = NULL;
+
+	if (needpatchflush)
+		W_FlushCachedPatches();
+
+	if (!TestValidLump(wad, lump))
+		return NULL;
+
+	lumpcache = wadfiles[wad]->patchcache;
+
+	if (!lumpcache[lump])
+	{
+		size_t len = W_LumpLengthPwad(wad, lump);
+		void *ptr, *lumpdata;
+#ifndef NO_PNG_LUMPS
+		void *srcdata = NULL;
+#endif
+
+		ptr = Z_Malloc(len, tag, &lumpcache[lump]);
+		lumpdata = Z_Malloc(len, tag, NULL);
+
+		// read the lump in full
+		W_ReadLumpHeaderPwad(wad, lump, lumpdata, 0, 0);
+
+#ifndef NO_PNG_LUMPS
+		// lump is a png so convert it
+		if (R_IsLumpPNG((UINT8 *)lumpdata, len))
+		{
+			size_t newlen;
+			srcdata = R_PNGToPatch((UINT8 *)lumpdata, len, &newlen);
+			ptr = Z_Realloc(ptr, newlen, tag, &lumpcache[lump]);
+			M_Memcpy(ptr, srcdata, newlen);
+			Z_Free(srcdata);
+		}
+		else // just copy it into the patch cache
+#endif
+			M_Memcpy(ptr, lumpdata, len);
+	}
+	else
+		Z_ChangeTag(lumpcache[lump], tag);
+
+	return lumpcache[lump];
+}
+
+void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag)
+{
+	return W_CacheSoftwarePatchNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag);
+}
+
 void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
 {
 #ifdef HWRENDER
@@ -1528,39 +1579,7 @@ void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag)
 	if (rendermode == render_soft || rendermode == render_none)
 #endif
 	{
-		lumpcache_t *lumpcache = wadfiles[wad]->patchcache;
-		if (!lumpcache[lump])
-		{
-			size_t len = W_LumpLengthPwad(wad, lump);
-			void *ptr, *lumpdata;
-#ifndef NO_PNG_LUMPS
-			void *srcdata = NULL;
-#endif
-
-			ptr = Z_Malloc(len, tag, &lumpcache[lump]);
-			lumpdata = Z_Malloc(len, tag, NULL);
-
-			// read the lump in full
-			W_ReadLumpHeaderPwad(wad, lump, lumpdata, 0, 0);
-
-#ifndef NO_PNG_LUMPS
-			// lump is a png so convert it
-			if (R_IsLumpPNG((UINT8 *)lumpdata, len))
-			{
-				size_t newlen;
-				srcdata = R_PNGToPatch((UINT8 *)lumpdata, len, &newlen);
-				ptr = Z_Realloc(ptr, newlen, tag, &lumpcache[lump]);
-				M_Memcpy(ptr, srcdata, newlen);
-				Z_Free(srcdata);
-			}
-			else // just copy it into the patch cache
-#endif
-				M_Memcpy(ptr, lumpdata, len);
-		}
-		else
-			Z_ChangeTag(lumpcache[lump], tag);
-
-		return lumpcache[lump];
+		return W_CacheSoftwarePatchNumPwad(wad, lump, tag);
 	}
 #ifdef HWRENDER
 
diff --git a/src/w_wad.h b/src/w_wad.h
index d598d9b39..3fb0cb77e 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -191,8 +191,15 @@ boolean W_IsPatchCached(lumpnum_t lump, void *ptr);
 void *W_CacheLumpName(const char *name, INT32 tag);
 void *W_CachePatchName(const char *name, INT32 tag);
 
-void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); // return a patch_t
-void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag); // return a patch_t
+// Returns either a Software patch, or an OpenGL patch.
+// Performs any necessary conversions from PNG images.
+void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag);
+void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag);
+
+// Returns a Software patch.
+// Performs any necessary conversions from PNG images.
+void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag);
+void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag);
 
 void W_UnlockCachedPatch(void *patch);
 void W_FlushCachedPatches(void);

From e0badd1e5b7dfb89d19a04be82a9543ceb60820e Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Wed, 18 Mar 2020 22:35:21 -0500
Subject: [PATCH 116/251] Rename hook to ShouldJingleContinue

---
 src/lua_hook.h    |  4 ++--
 src/lua_hooklib.c | 14 +++++++-------
 src/p_user.c      |  2 +-
 3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/lua_hook.h b/src/lua_hook.h
index ea11d0236..dde8d4c41 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -58,7 +58,7 @@ enum hook {
 	hook_ViewpointSwitch,
 	hook_SeenPlayer,
 	hook_PlayerThink,
-	hook_JingleStatus,
+	hook_ShouldJingleContinue,
 
 	hook_MAX // last hook
 };
@@ -111,6 +111,6 @@ UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean
 boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK
 #endif
 #define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
-boolean LUAh_JingleStatus(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing
+boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing
 
 #endif
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index c56336fca..3a4d67492 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -69,7 +69,7 @@ const char *const hookNames[hook_MAX+1] = {
 	"ViewpointSwitch",
 	"SeenPlayer",
 	"PlayerThink",
-	"JingleStatus",
+	"ShouldJingleContinue",
 	NULL
 };
 
@@ -81,7 +81,7 @@ struct hook_s
 	UINT16 id;
 	union {
 		mobjtype_t mt;
-		char *skinname; // also used as musname for JingleStatus... I'm lazy
+		char *skinname; // also used as musname for ShouldJingleContinue... I'm lazy
 		char *funcname;
 	} s;
 	boolean error;
@@ -149,7 +149,7 @@ static int lib_addHook(lua_State *L)
 		luaL_argcheck(L, hook.s.mt < NUMMOBJTYPES, 2, "invalid mobjtype_t");
 		break;
 	case hook_BotAI:
-	case hook_JingleStatus:
+	case hook_ShouldJingleContinue:
 		hook.s.skinname = NULL;
 		if (lua_isstring(L, 2))
 		{ // lowercase copy
@@ -1634,11 +1634,11 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend)
 }
 #endif // SEENAMES
 
-boolean LUAh_JingleStatus(player_t *player, const char *musname)
+boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname)
 {
 	hook_p hookp;
 	boolean keepplaying = false;
-	if (!gL || !(hooksAvailable[hook_JingleStatus/8] & (1<<(hook_JingleStatus%8))))
+	if (!gL || !(hooksAvailable[hook_ShouldJingleContinue/8] & (1<<(hook_ShouldJingleContinue%8))))
 		return true;
 
 	lua_settop(gL, 0);
@@ -1646,9 +1646,9 @@ boolean LUAh_JingleStatus(player_t *player, const char *musname)
 
 	for (hookp = roothook; hookp; hookp = hookp->next)
 	{
-		if (hookp->type == hook_JingleStatus) CONS_Printf("jingle status hook for %s vs %s\n", hookp->s.skinname, musname);
+		if (hookp->type == hook_ShouldJingleContinue) CONS_Printf("jingle status hook for %s vs %s\n", hookp->s.skinname, musname);
 
-		if (hookp->type != hook_JingleStatus
+		if (hookp->type != hook_ShouldJingleContinue
 			|| (hookp->s.skinname && strcmp(hookp->s.skinname, musname)))
 			continue;
 
diff --git a/src/p_user.c b/src/p_user.c
index ab85897a5..b7b95f9f0 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -1599,7 +1599,7 @@ boolean P_EvaluateMusicStatus(UINT16 status, const char *musname)
 				break;
 
 			case JT_OTHER:  // Other state
-				result = LUAh_JingleStatus(&players[i], musname);
+				result = LUAh_ShouldJingleContinue(&players[i], musname);
 				break;
 
 			case JT_NONE:   // Null state

From dd0d86120b09c2a2f7d2a06c34f9abbf82d5111c Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Wed, 18 Mar 2020 22:38:18 -0500
Subject: [PATCH 117/251] > building SRB2 without Lua in 2020

---
 src/p_user.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/p_user.c b/src/p_user.c
index b7b95f9f0..3694a1a3b 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -1599,8 +1599,10 @@ boolean P_EvaluateMusicStatus(UINT16 status, const char *musname)
 				break;
 
 			case JT_OTHER:  // Other state
+#ifdef HAVE_BLUA
 				result = LUAh_ShouldJingleContinue(&players[i], musname);
 				break;
+#endif
 
 			case JT_NONE:   // Null state
 			case JT_MASTER: // Main level music

From 647f73c8f26d66370de86723b80428efbfb1f7f3 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Wed, 18 Mar 2020 22:38:51 -0500
Subject: [PATCH 118/251] Clean up after myself

---
 src/lua_hooklib.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 3a4d67492..4f873dd99 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -1646,8 +1646,6 @@ boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname)
 
 	for (hookp = roothook; hookp; hookp = hookp->next)
 	{
-		if (hookp->type == hook_ShouldJingleContinue) CONS_Printf("jingle status hook for %s vs %s\n", hookp->s.skinname, musname);
-
 		if (hookp->type != hook_ShouldJingleContinue
 			|| (hookp->s.skinname && strcmp(hookp->s.skinname, musname)))
 			continue;

From 520e3c5dc32e1970c339be3b2fc9eee80ab168bb Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Wed, 18 Mar 2020 22:40:11 -0500
Subject: [PATCH 119/251] Are these casts unnecessary...??

---
 src/lua_baselib.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index b6fa1b7aa..4694b56ba 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -1043,7 +1043,7 @@ static int lib_pSetObjectMomZ(lua_State *L)
 static int lib_pPlayJingle(lua_State *L)
 {
 	player_t *player = NULL;
-	jingletype_t jingletype = (jingletype_t)luaL_checkinteger(L, 2);
+	jingletype_t jingletype = luaL_checkinteger(L, 2);
 	//NOHUD
 	//INLEVEL
 	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
@@ -1065,7 +1065,7 @@ static int lib_pPlayJingleMusic(lua_State *L)
 	char musname[7], *p = musname;
 	UINT16 musflags = luaL_optinteger(L, 3, 0);
 	boolean looping = lua_opttrueboolean(L, 4);
-	jingletype_t jingletype = (jingletype_t)luaL_optinteger(L, 5, JT_OTHER);
+	jingletype_t jingletype = luaL_optinteger(L, 5, JT_OTHER);
 	//NOHUD
 	//INLEVEL
 	if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))

From 9c86cd0bc2e7895d9c46b79cb5e368e74dece2b0 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Wed, 18 Mar 2020 22:42:31 -0500
Subject: [PATCH 120/251] More union types for the union type god

---
 src/lua_hooklib.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 4f873dd99..2843b0228 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -81,7 +81,8 @@ struct hook_s
 	UINT16 id;
 	union {
 		mobjtype_t mt;
-		char *skinname; // also used as musname for ShouldJingleContinue... I'm lazy
+		char *skinname;
+		char *musname;
 		char *funcname;
 	} s;
 	boolean error;
@@ -1647,7 +1648,7 @@ boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname)
 	for (hookp = roothook; hookp; hookp = hookp->next)
 	{
 		if (hookp->type != hook_ShouldJingleContinue
-			|| (hookp->s.skinname && strcmp(hookp->s.skinname, musname)))
+			|| (hookp->s.musname && strcmp(hookp->s.musname, musname)))
 			continue;
 
 		if (lua_gettop(gL) == 0)

From 725826a64b6d56a04b7fd17e1e1ef4c20243047d Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Wed, 18 Mar 2020 22:56:20 -0500
Subject: [PATCH 121/251] Avoid infinite loops if no maps are selectable (y
 tho)

---
 src/m_menu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index b39fcc2bf..3ebaedca2 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -5373,9 +5373,10 @@ static void M_HandleLevelPlatter(INT32 choice)
 		case KEY_RIGHTARROW:
 			if (levellistmode == LLM_CREATESERVER && !lsrow)
 			{
+				INT32 startinggametype = cv_newgametype.value;
 				do
 					CV_AddValue(&cv_newgametype, 1);
-				while (!M_GametypeHasLevels(cv_newgametype.value));
+				while (cv_newgametype.value != startinggametype && !M_GametypeHasLevels(cv_newgametype.value));
 				S_StartSound(NULL,sfx_menu1);
 				lscol = 0;
 

From 58c42eec292d6a38748d9a720ddb5e682344f628 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Thu, 19 Mar 2020 14:38:42 +0100
Subject: [PATCH 122/251] Simplify hook code

---
 src/lua_hooklib.c | 20 ++++----------------
 1 file changed, 4 insertions(+), 16 deletions(-)

diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 20a7738e7..078732541 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -155,25 +155,13 @@ static int lib_addHook(lua_State *L)
 		hook.s.skinname = NULL;
 		if (lua_isstring(L, 2))
 		{ // lowercase copy
-			const char *s = lua_tostring(L, 2);
-			char *p = hook.s.skinname = ZZ_Alloc(strlen(s)+1);
-			do {
-				*p = tolower(*s);
-				++p;
-			} while(*(++s));
-			*p = 0;
+			hook.s.skinname = Z_StrDup(lua_tostring(L, 2));
+			strlwr(hook.s.skinname);
 		}
 		break;
 	case hook_LinedefExecute: // Linedef executor functions
-		{ // uppercase copy
-			const char *s = luaL_checkstring(L, 2);
-			char *p = hook.s.funcname = ZZ_Alloc(strlen(s)+1);
-			do {
-				*p = toupper(*s);
-				++p;
-			} while(*(++s));
-			*p = 0;
-		}
+		hook.s.skinname = Z_StrDup(luaL_checkstring(L, 2));
+		strupr(hook.s.skinname);
 		break;
 	default:
 		break;

From 1d5d6ead651174a10f554e5a27ae0caa6511e2c6 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Thu, 19 Mar 2020 14:40:12 +0100
Subject: [PATCH 123/251] Fix misleading naming

---
 src/lua_hooklib.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 078732541..549d1a3ef 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -81,9 +81,7 @@ struct hook_s
 	UINT16 id;
 	union {
 		mobjtype_t mt;
-		char *skinname;
-		char *musname;
-		char *funcname;
+		char *str;
 	} s;
 	boolean error;
 };
@@ -152,16 +150,16 @@ static int lib_addHook(lua_State *L)
 		break;
 	case hook_BotAI:
 	case hook_ShouldJingleContinue:
-		hook.s.skinname = NULL;
+		hook.s.str = NULL;
 		if (lua_isstring(L, 2))
 		{ // lowercase copy
-			hook.s.skinname = Z_StrDup(lua_tostring(L, 2));
-			strlwr(hook.s.skinname);
+			hook.s.str = Z_StrDup(lua_tostring(L, 2));
+			strlwr(hook.s.str);
 		}
 		break;
 	case hook_LinedefExecute: // Linedef executor functions
-		hook.s.skinname = Z_StrDup(luaL_checkstring(L, 2));
-		strupr(hook.s.skinname);
+		hook.s.str = Z_StrDup(luaL_checkstring(L, 2));
+		strupr(hook.s.str);
 		break;
 	default:
 		break;
@@ -1064,7 +1062,7 @@ boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
 	for (hookp = roothook; hookp; hookp = hookp->next)
 	{
 		if (hookp->type != hook_BotAI
-		|| (hookp->s.skinname && strcmp(hookp->s.skinname, ((skin_t*)tails->skin)->name)))
+		|| (hookp->s.str && strcmp(hookp->s.str, ((skin_t*)tails->skin)->name)))
 			continue;
 
 		if (lua_gettop(gL) == 0)
@@ -1126,7 +1124,7 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
 
 	for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next)
 	{
-		if (strcmp(hookp->s.funcname, line->text))
+		if (strcmp(hookp->s.str, line->text))
 			continue;
 
 		if (lua_gettop(gL) == 0)
@@ -1664,7 +1662,7 @@ boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname)
 	for (hookp = roothook; hookp; hookp = hookp->next)
 	{
 		if (hookp->type != hook_ShouldJingleContinue
-			|| (hookp->s.musname && strcmp(hookp->s.musname, musname)))
+			|| (hookp->s.str && strcmp(hookp->s.str, musname)))
 			continue;
 
 		if (lua_gettop(gL) == 0)

From c1b50397ce665bd082fb45e1f8b24e85963d2ead Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Thu, 19 Mar 2020 14:40:35 +0100
Subject: [PATCH 124/251] Fix compiler warning

---
 src/p_user.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/p_user.c b/src/p_user.c
index 345da85ef..15a75b3a5 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -1550,6 +1550,10 @@ boolean P_EvaluateMusicStatus(UINT16 status, const char *musname)
 	int i;
 	boolean result = false;
 
+#ifndef HAVE_BLUA
+	(void)musname;
+#endif
+
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
 		if (!P_IsLocalPlayer(&players[i]))

From e3cbdf8fabd34ff8c5cf7fc98fde2d377c6eedff Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Thu, 19 Mar 2020 18:36:14 +0100
Subject: [PATCH 125/251] Use HAVE_BLUA as fuel for my fireplace

---
 src/CMakeLists.txt                            | 163 ++--
 src/Makefile                                  |   6 +-
 src/b_bot.c                                   |   4 -
 src/blua/Makefile.cfg                         |   2 -
 src/command.c                                 |   6 -
 src/d_clisrv.c                                |  20 -
 src/d_clisrv.h                                |   2 -
 src/d_main.c                                  |   8 -
 src/d_net.c                                   |   4 -
 src/d_netcmd.c                                |  20 +-
 src/d_netcmd.h                                |   2 -
 src/d_netfil.c                                |   8 -
 src/d_netfil.h                                |   2 -
 src/dehacked.c                                |  65 +-
 src/dehacked.h                                |   2 -
 src/doomstat.h                                |   1 -
 src/f_finale.c                                |   8 -
 src/f_wipe.c                                  |   2 -
 src/filesrch.h                                |   2 +-
 src/g_game.c                                  |  16 +-
 src/hu_stuff.c                                |  31 +-
 src/lua_baselib.c                             |   3 -
 src/lua_blockmaplib.c                         |   3 -
 src/lua_consolelib.c                          |   3 -
 src/lua_hook.h                                |   4 -
 src/lua_hooklib.c                             |   3 -
 src/lua_hudlib.c                              |   3 -
 src/lua_infolib.c                             |   3 -
 src/lua_libs.h                                |   4 -
 src/lua_maplib.c                              |   3 -
 src/lua_mathlib.c                             |   3 -
 src/lua_mobjlib.c                             |   3 -
 src/lua_playerlib.c                           |   3 -
 src/lua_script.c                              |   3 -
 src/lua_script.h                              |   4 -
 src/lua_skinlib.c                             |   3 -
 src/lua_thinkerlib.c                          |   3 -
 src/m_cheat.c                                 |   4 +-
 src/m_cheat.h                                 |   2 +-
 src/m_menu.c                                  |   6 -
 src/p_enemy.c                                 | 765 +++++-------------
 src/p_inter.c                                 |  20 -
 src/p_map.c                                   |  11 +-
 src/p_mobj.c                                  | 225 +++---
 src/p_saveg.c                                 |   6 -
 src/p_setup.c                                 |   8 -
 src/p_spec.c                                  |   4 -
 src/p_tick.c                                  |  15 +-
 src/p_user.c                                  | 171 ++--
 src/s_sound.c                                 |   4 +-
 src/sdl/Srb2SDL-vc9.vcproj                    |   8 +-
 .../macosx/Srb2mac.xcodeproj/project.pbxproj  |   2 -
 src/st_stuff.c                                | 126 +--
 src/w_wad.c                                   |  15 +-
 src/win32/Srb2win-vc9.vcproj                  |   8 +-
 src/y_inter.c                                 |  10 -
 src/z_zone.c                                  |   2 -
 57 files changed, 513 insertions(+), 1324 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b95fdd9e7..372341291 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -216,8 +216,6 @@ source_group("Assembly" FILES ${SRB2_ASM_SOURCES} ${SRB2_NASM_SOURCES})
 
 
 ### Configuration
-set(SRB2_CONFIG_HAVE_BLUA ON CACHE BOOL
-	"Enable Lua interpreter support")
 set(SRB2_CONFIG_HAVE_PNG ON CACHE BOOL
 	"Enable PNG support. Depends on zlib, so will be disabled if you don't enable that too.")
 set(SRB2_CONFIG_HAVE_ZLIB ON CACHE BOOL
@@ -241,93 +239,90 @@ if(${CMAKE_SYSTEM} MATCHES "Windows") ###set on Windows only
 	"Use SRB2's internal copies of required dependencies (SDL2, PNG, zlib, GME, OpenMPT).")
 endif()
 
-if(${SRB2_CONFIG_HAVE_BLUA})
-	add_definitions(-DHAVE_BLUA)
-	set(SRB2_LUA_SOURCES
-		lua_baselib.c
-		lua_blockmaplib.c
-		lua_consolelib.c
-		lua_hooklib.c
-		lua_hudlib.c
-		lua_infolib.c
-		lua_maplib.c
-		lua_mathlib.c
-		lua_mobjlib.c
-		lua_playerlib.c
-		lua_script.c
-		lua_skinlib.c
-		lua_thinkerlib.c
-	)
-	set(SRB2_LUA_HEADERS
-		lua_hook.h
-		lua_hud.h
-		lua_libs.h
-		lua_script.h
-	)
+set(SRB2_LUA_SOURCES
+	lua_baselib.c
+	lua_blockmaplib.c
+	lua_consolelib.c
+	lua_hooklib.c
+	lua_hudlib.c
+	lua_infolib.c
+	lua_maplib.c
+	lua_mathlib.c
+	lua_mobjlib.c
+	lua_playerlib.c
+	lua_script.c
+	lua_skinlib.c
+	lua_thinkerlib.c
+)
+set(SRB2_LUA_HEADERS
+	lua_hook.h
+	lua_hud.h
+	lua_libs.h
+	lua_script.h
+)
 
-	prepend_sources(SRB2_LUA_SOURCES)
-	prepend_sources(SRB2_LUA_HEADERS)
+prepend_sources(SRB2_LUA_SOURCES)
+prepend_sources(SRB2_LUA_HEADERS)
 
-	source_group("LUA" FILES ${SRB2_LUA_SOURCES} ${SRB2_LUA_HEADERS})
+source_group("LUA" FILES ${SRB2_LUA_SOURCES} ${SRB2_LUA_HEADERS})
 
-	set(SRB2_BLUA_SOURCES
-		blua/lapi.c
-		blua/lauxlib.c
-		blua/lbaselib.c
-		blua/lcode.c
-		blua/ldebug.c
-		blua/ldo.c
-		blua/ldump.c
-		blua/lfunc.c
-		blua/lgc.c
-		blua/linit.c
-		blua/liolib.c
-		blua/llex.c
-		blua/lmem.c
-		blua/lobject.c
-		blua/lopcodes.c
-		blua/lparser.c
-		blua/lstate.c
-		blua/lstring.c
-		blua/lstrlib.c
-		blua/ltable.c
-		blua/ltablib.c
-		blua/ltm.c
-		blua/lundump.c
-		blua/lvm.c
-		blua/lzio.c
-	)
-	set(SRB2_BLUA_HEADERS
-		blua/lapi.h
-		blua/lauxlib.h
-		blua/lcode.h
-		blua/ldebug.h
-		blua/ldo.h
-		blua/lfunc.h
-		blua/lgc.h
-		blua/llex.h
-		blua/llimits.h
-		blua/lmem.h
-		blua/lobject.h
-		blua/lopcodes.h
-		blua/lparser.h
-		blua/lstate.h
-		blua/lstring.h
-		blua/ltable.h
-		blua/ltm.h
-		blua/lua.h
-		blua/luaconf.h
-		blua/lualib.h
-		blua/lundump.h
-		blua/lvm.h
-		blua/lzio.h
-	)
+set(SRB2_BLUA_SOURCES
+	blua/lapi.c
+	blua/lauxlib.c
+	blua/lbaselib.c
+	blua/lcode.c
+	blua/ldebug.c
+	blua/ldo.c
+	blua/ldump.c
+	blua/lfunc.c
+	blua/lgc.c
+	blua/linit.c
+	blua/liolib.c
+	blua/llex.c
+	blua/lmem.c
+	blua/lobject.c
+	blua/lopcodes.c
+	blua/lparser.c
+	blua/lstate.c
+	blua/lstring.c
+	blua/lstrlib.c
+	blua/ltable.c
+	blua/ltablib.c
+	blua/ltm.c
+	blua/lundump.c
+	blua/lvm.c
+	blua/lzio.c
+)
+set(SRB2_BLUA_HEADERS
+	blua/lapi.h
+	blua/lauxlib.h
+	blua/lcode.h
+	blua/ldebug.h
+	blua/ldo.h
+	blua/lfunc.h
+	blua/lgc.h
+	blua/llex.h
+	blua/llimits.h
+	blua/lmem.h
+	blua/lobject.h
+	blua/lopcodes.h
+	blua/lparser.h
+	blua/lstate.h
+	blua/lstring.h
+	blua/ltable.h
+	blua/ltm.h
+	blua/lua.h
+	blua/luaconf.h
+	blua/lualib.h
+	blua/lundump.h
+	blua/lvm.h
+	blua/lzio.h
+)
 
-	prepend_sources(SRB2_BLUA_SOURCES)
-	prepend_sources(SRB2_BLUA_HEADERS)
+prepend_sources(SRB2_BLUA_SOURCES)
+prepend_sources(SRB2_BLUA_HEADERS)
 
-	source_group("LUA\\Interpreter" FILES ${SRB2_BLUA_SOURCES} ${SRB2_BLUA_HEADERS})
-endif()
+source_group("LUA\\Interpreter" FILES ${SRB2_BLUA_SOURCES} ${SRB2_BLUA_HEADERS})
 
 if(${SRB2_CONFIG_HAVE_GME})
 	if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES})
diff --git a/src/Makefile b/src/Makefile
index 701f2cfda..1ebd39ac4 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -340,9 +340,7 @@ CFLAGS+=-DHAVE_MINIUPNPC
 endif
 endif
 
-ifndef NO_LUA
-	include blua/Makefile.cfg
-endif
+include blua/Makefile.cfg
 
 ifdef NOMD5
 	OPTS+=-DNOMD5
@@ -683,9 +681,7 @@ $(OBJDIR)/depend.dep:
 ifndef NOHW
 	$(CC) $(CFLAGS) -MM hardware/*.c >> $(OBJDIR)/depend.ped
 endif
-ifndef NO_LUA
 	$(CC) $(CFLAGS) -MM blua/*.c >> $(OBJDIR)/depend.ped
-endif
 	@sed -e 's,\(.*\)\.o: ,$(subst /,\/,$(OBJDIR))\/&,g' < $(OBJDIR)/depend.ped > $(OBJDIR)/depend.dep
 	$(REMOVE) $(OBJDIR)/depend.ped
 	@echo "Created dependency file, depend.dep"
diff --git a/src/b_bot.c b/src/b_bot.c
index 4f904b672..4fefbdcb6 100644
--- a/src/b_bot.c
+++ b/src/b_bot.c
@@ -74,11 +74,9 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
 	if (!sonic || sonic->health <= 0)
 		return;
 
-#ifdef HAVE_BLUA
 	// Lua can handle it!
 	if (LUAh_BotAI(sonic, tails, cmd))
 		return;
-#endif
 
 	if (tails->player->powers[pw_carry] == CR_MACESPIN || tails->player->powers[pw_carry] == CR_GENERIC)
 	{
@@ -364,11 +362,9 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
 	// Bot AI isn't programmed in analog.
 	CV_SetValue(&cv_analog[1], false);
 
-#ifdef HAVE_BLUA
 	// Let Lua scripts build ticcmds
 	if (LUAh_BotTiccmd(player, cmd))
 		return;
-#endif
 
 	// We don't have any main character AI, sorry. D:
 	if (player-players == consoleplayer)
diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg
index 659faf3c8..12ea064b4 100644
--- a/src/blua/Makefile.cfg
+++ b/src/blua/Makefile.cfg
@@ -10,8 +10,6 @@ WFLAGS+=-Wno-logical-op
 endif
 endif
 
-OPTS+=-DHAVE_BLUA
-
 OBJS:=$(OBJS) \
 	$(OBJDIR)/lapi.o \
 	$(OBJDIR)/lbaselib.o \
diff --git a/src/command.c b/src/command.c
index d1eea6052..72dc9f769 100644
--- a/src/command.c
+++ b/src/command.c
@@ -481,13 +481,11 @@ void COM_AddCommand(const char *name, com_func_t func)
 	{
 		if (!stricmp(name, cmd->name)) //case insensitive now that we have lower and uppercase!
 		{
-#ifdef HAVE_BLUA
 			// don't I_Error for Lua commands
 			// Lua commands can replace game commands, and they have priority.
 			// BUT, if for some reason we screwed up and made two console commands with the same name,
 			// it's good to have this here so we find out.
 			if (cmd->function != COM_Lua_f)
-#endif
 				I_Error("Command %s already exists\n", name);
 
 			return;
@@ -501,7 +499,6 @@ void COM_AddCommand(const char *name, com_func_t func)
 	com_commands = cmd;
 }
 
-#ifdef HAVE_BLUA
 /** Adds a console command for Lua.
   * No I_Errors allowed; return a negative code instead.
   *
@@ -534,7 +531,6 @@ int COM_AddLuaCommand(const char *name)
 	com_commands = cmd;
 	return 0;
 }
-#endif
 
 /** Tests if a command exists.
   *
@@ -1427,9 +1423,7 @@ finish:
 	}
 	var->flags |= CV_MODIFIED;
 	// raise 'on change' code
-#ifdef HAVE_BLUA
 	LUA_CVarChanged(var->name); // let consolelib know what cvar this is.
-#endif
 	if (var->flags & CV_CALL && !stealth)
 		var->func();
 
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index b706b5467..aa5d4cb9a 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -2547,20 +2547,14 @@ static void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
 		}
 	}
 
-#ifdef HAVE_BLUA
 	LUAh_PlayerQuit(&players[playernum], reason); // Lua hook for player quitting
-#else
-	(void)reason;
-#endif
 
 	// don't look through someone's view who isn't there
 	if (playernum == displayplayer)
 	{
-#ifdef HAVE_BLUA
 		// Call ViewpointSwitch hooks here.
 		// The viewpoint was forcibly changed.
 		LUAh_ViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true);
-#endif
 		displayplayer = consoleplayer;
 	}
 
@@ -2581,9 +2575,7 @@ static void CL_RemovePlayer(INT32 playernum, kickreason_t reason)
 		RemoveAdminPlayer(playernum); // don't stay admin after you're gone
 	}
 
-#ifdef HAVE_BLUA
 	LUA_InvalidatePlayer(&players[playernum]);
-#endif
 
 	if (G_TagGametype()) //Check if you still have a game. Location flexible. =P
 		P_CheckSurvivors();
@@ -3177,9 +3169,7 @@ void SV_ResetServer(void)
 
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
-#ifdef HAVE_BLUA
 		LUA_InvalidatePlayer(&players[i]);
-#endif
 		playeringame[i] = false;
 		playernode[i] = UINT8_MAX;
 		memset(playeraddress[i], 0, sizeof(*playeraddress));
@@ -3240,10 +3230,8 @@ void D_QuitNetGame(void)
 
 	// abort send/receive of files
 	CloseNetFile();
-#ifdef HAVE_BLUA
 	RemoveAllLuaFileTransfers();
 	waitingforluafiletransfer = false;
-#endif
 
 	if (server)
 	{
@@ -3414,10 +3402,8 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
 	if (server && multiplayer && motd[0] != '\0')
 		COM_BufAddText(va("sayto %d %s\n", newplayernum, motd));
 
-#ifdef HAVE_BLUA
 	if (!rejoined)
 		LUAh_PlayerJoin(newplayernum);
-#endif
 }
 
 static boolean SV_AddWaitingPlayers(const char *name, const char *name2)
@@ -3625,10 +3611,8 @@ static void HandleConnect(SINT8 node)
 		SV_SendRefuse(node, M_GetText("Too many players from\nthis node."));
 	else if (netgame && !netbuffer->u.clientcfg.localplayers) // Stealth join?
 		SV_SendRefuse(node, M_GetText("No players from\nthis node."));
-#ifdef HAVE_BLUA
 	else if (luafiletransfers)
 		SV_SendRefuse(node, M_GetText("The server is broadcasting a file\nrequested by a Lua script.\nPlease wait a bit and then\ntry rejoining."));
-#endif
 	else
 	{
 #ifndef NONET
@@ -4215,7 +4199,6 @@ static void HandlePacketFromPlayer(SINT8 node)
 			Net_CloseConnection(node);
 			nodeingame[node] = false;
 			break;
-#ifdef HAVE_BLUA
 		case PT_ASKLUAFILE:
 			if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_ASKED)
 			{
@@ -4228,7 +4211,6 @@ static void HandlePacketFromPlayer(SINT8 node)
 			if (server && luafiletransfers && luafiletransfers->nodestatus[node] == LFTNS_SENDING)
 				SV_HandleLuaFileSent(node);
 			break;
-#endif
 // -------------------------------------------- CLIENT RECEIVE ----------
 		case PT_RESYNCHEND:
 			// Only accept PT_RESYNCHEND from the server.
@@ -4356,12 +4338,10 @@ static void HandlePacketFromPlayer(SINT8 node)
 			if (client)
 				Got_Filetxpak();
 			break;
-#ifdef HAVE_BLUA
 		case PT_SENDINGLUAFILE:
 			if (client)
 				CL_PrepareDownloadLuaFile();
 			break;
-#endif
 		default:
 			DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n",
 				netbuffer->packettype, node));
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index b5cc00152..30d562bed 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -67,11 +67,9 @@ typedef enum
 	PT_RESYNCHEND,    // Player is now resynched and is being requested to remake the gametic
 	PT_RESYNCHGET,    // Player got resynch packet
 
-#ifdef HAVE_BLUA
 	PT_SENDINGLUAFILE, // Server telling a client Lua needs to open a file
 	PT_ASKLUAFILE,     // Client telling the server they don't have the file
 	PT_HASLUAFILE,     // Client telling the server they have the file
-#endif
 
 	// Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility.
 
diff --git a/src/d_main.c b/src/d_main.c
index 9cbcdc0c6..40e7af22a 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -91,9 +91,7 @@ int	snprintf(char *str, size_t n, const char *fmt, ...);
 #include "hardware/hw3sound.h"
 #endif
 
-#ifdef HAVE_BLUA
 #include "lua_script.h"
-#endif
 
 // platform independant focus loss
 UINT8 window_notinfocus = false;
@@ -746,9 +744,7 @@ void D_SRB2Loop(void)
 		HW3S_EndFrameUpdate();
 #endif
 
-#ifdef HAVE_BLUA
 		LUA_Step();
-#endif
 	}
 }
 
@@ -1124,9 +1120,7 @@ void D_SRB2Main(void)
 			// can't use sprintf since there is %u in savegamename
 			strcatbf(savegamename, srb2home, PATHSEP);
 
-#ifdef HAVE_BLUA
 			snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", srb2home);
-#endif
 #else // DEFAULTDIR
 			snprintf(srb2home, sizeof srb2home, "%s", userhome);
 			snprintf(downloaddir, sizeof downloaddir, "%s", userhome);
@@ -1138,9 +1132,7 @@ void D_SRB2Main(void)
 			// can't use sprintf since there is %u in savegamename
 			strcatbf(savegamename, userhome, PATHSEP);
 
-#ifdef HAVE_BLUA
 			snprintf(luafiledir, sizeof luafiledir, "%s" PATHSEP "luafiles", userhome);
-#endif
 #endif // DEFAULTDIR
 		}
 
diff --git a/src/d_net.c b/src/d_net.c
index 77a58e9bd..1db75f3da 100644
--- a/src/d_net.c
+++ b/src/d_net.c
@@ -715,10 +715,8 @@ void Net_CloseConnection(INT32 node)
 
 	InitNode(&nodes[node]);
 	SV_AbortSendFiles(node);
-#ifdef HAVE_BLUA
 	if (server)
 		SV_AbortLuaFileTransfer(node);
-#endif
 	I_NetFreeNodenum(node);
 #endif
 }
@@ -803,11 +801,9 @@ static const char *packettypename[NUMPACKETTYPE] =
 	"RESYNCHEND",
 	"RESYNCHGET",
 
-#ifdef HAVE_BLUA
 	"SENDINGLUAFILE",
 	"ASKLUAFILE",
 	"HASLUAFILE",
-#endif
 
 	"FILEFRAGMENT",
 	"TEXTCMD",
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 5ad972b29..aaa01c57f 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -157,10 +157,8 @@ static void Command_Isgamemodified_f(void);
 static void Command_Cheats_f(void);
 #ifdef _DEBUG
 static void Command_Togglemodified_f(void);
-#ifdef HAVE_BLUA
 static void Command_Archivetest_f(void);
 #endif
-#endif
 
 // =========================================================================
 //                           CLIENT VARIABLES
@@ -415,11 +413,9 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
 	"DELFILE", // replace next time we add an XD
 	"SETMOTD",
 	"SUICIDE",
-#ifdef HAVE_BLUA
 	"LUACMD",
 	"LUAVAR",
 	"LUAFILE"
-#endif
 };
 
 // =========================================================================
@@ -452,10 +448,8 @@ void D_RegisterServerCommands(void)
 	RegisterNetXCmd(XD_PAUSE, Got_Pause);
 	RegisterNetXCmd(XD_SUICIDE, Got_Suicide);
 	RegisterNetXCmd(XD_RUNSOC, Got_RunSOCcmd);
-#ifdef HAVE_BLUA
 	RegisterNetXCmd(XD_LUACMD, Got_Luacmd);
 	RegisterNetXCmd(XD_LUAFILE, Got_LuaFile);
-#endif
 
 	// Remote Administration
 	COM_AddCommand("password", Command_Changepassword_f);
@@ -504,9 +498,7 @@ void D_RegisterServerCommands(void)
 	COM_AddCommand("cheats", Command_Cheats_f); // test
 #ifdef _DEBUG
 	COM_AddCommand("togglemodified", Command_Togglemodified_f);
-#ifdef HAVE_BLUA
 	COM_AddCommand("archivetest", Command_Archivetest_f);
-#endif
 #endif
 
 	// for master server connection
@@ -915,7 +907,7 @@ void D_RegisterClientCommands(void)
 #ifdef _DEBUG
 	COM_AddCommand("causecfail", Command_CauseCfail_f);
 #endif
-#if defined(HAVE_BLUA) && defined(LUA_ALLOW_BYTECODE)
+#ifdef LUA_ALLOW_BYTECODE
 	COM_AddCommand("dumplua", Command_Dumplua_f);
 #endif
 }
@@ -2029,9 +2021,7 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
 	UINT8 flags;
 	INT32 resetplayer = 1, lastgametype;
 	UINT8 skipprecutscene, FLS;
-#ifdef HAVE_BLUA
 	INT16 mapnumber;
-#endif
 
 	if (playernum != serverplayer && !IsPlayerAdmin(playernum))
 	{
@@ -2093,10 +2083,8 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
 		CV_StealthSetValue(&cv_playercolor, players[0].skincolor);
 	}
 
-#ifdef HAVE_BLUA
 	mapnumber = M_MapNumber(mapname[3], mapname[4]);
 	LUAh_MapChange(mapnumber);
-#endif
 
 	G_InitNew(ultimatemode, mapname, resetplayer, skipprecutscene, FLS);
 	if (demoplayback && !timingdemo)
@@ -2680,11 +2668,9 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
 		return;
 	}
 
-#ifdef HAVE_BLUA
 	// Don't switch team, just go away, please, go awaayyyy, aaauuauugghhhghgh
 	if (!LUAh_TeamSwitch(&players[playernum], NetPacket.packet.newteam, players[playernum].spectator, NetPacket.packet.autobalance, NetPacket.packet.scrambled))
 		return;
-#endif
 
 	//no status changes after hidetime
 	if ((gametyperules & GTR_HIDEFROZEN) && (leveltime >= (hidetime * TICRATE)))
@@ -2841,12 +2827,10 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
 	//reset view if you are changed, or viewing someone who was changed.
 	if (playernum == consoleplayer || displayplayer == playernum)
 	{
-#ifdef HAVE_BLUA
 		// Call ViewpointSwitch hooks here.
 		// The viewpoint was forcibly changed.
 		if (displayplayer != consoleplayer) // You're already viewing yourself. No big deal.
 			LUAh_ViewpointSwitch(&players[consoleplayer], &players[consoleplayer], true);
-#endif
 		displayplayer = consoleplayer;
 	}
 
@@ -4332,7 +4316,6 @@ static void Command_Togglemodified_f(void)
 	modifiedgame = !modifiedgame;
 }
 
-#ifdef HAVE_BLUA
 extern UINT8 *save_p;
 static void Command_Archivetest_f(void)
 {
@@ -4377,7 +4360,6 @@ static void Command_Archivetest_f(void)
 	CONS_Printf("Done. No crash.\n");
 }
 #endif
-#endif
 
 /** Makes a change to ::cv_forceskin take effect immediately.
   *
diff --git a/src/d_netcmd.h b/src/d_netcmd.h
index 6e6ae0c0a..897c28968 100644
--- a/src/d_netcmd.h
+++ b/src/d_netcmd.h
@@ -142,11 +142,9 @@ typedef enum
 	XD_SETMOTD,     // 19
 	XD_SUICIDE,     // 20
 	XD_DEMOTED,     // 21
-#ifdef HAVE_BLUA
 	XD_LUACMD,      // 22
 	XD_LUAVAR,      // 23
 	XD_LUAFILE,     // 24
-#endif
 	MAXNETXCMD
 } netxcmd_t;
 
diff --git a/src/d_netfil.c b/src/d_netfil.c
index 9ce423cd4..6d3ac7f9d 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -95,11 +95,9 @@ char downloaddir[512] = "DOWNLOAD";
 INT32 lastfilenum = -1;
 #endif
 
-#ifdef HAVE_BLUA
 luafiletransfer_t *luafiletransfers = NULL;
 boolean waitingforluafiletransfer = false;
 char luafiledir[256 + 16] = "luafiles";
-#endif
 
 
 /** Fills a serverinfo packet with information about wad files loaded.
@@ -458,7 +456,6 @@ void CL_LoadServerFiles(void)
 	}
 }
 
-#ifdef HAVE_BLUA
 void AddLuaFileTransfer(const char *filename, const char *mode)
 {
 	luafiletransfer_t **prevnext; // A pointer to the "next" field of the last transfer in the list
@@ -614,7 +611,6 @@ void CL_PrepareDownloadLuaFile(void)
 	// Make sure all directories in the file path exist
 	MakePathDirs(fileneeded[0].filename);
 }
-#endif
 
 // Number of files to send
 // Little optimization to quickly test if there is a file in the queue
@@ -749,7 +745,6 @@ void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UI
 	filestosend++;
 }
 
-#ifdef HAVE_BLUA
 /** Adds a file requested by Lua to the file list for a node
   *
   * \param node The node to send the file to
@@ -798,7 +793,6 @@ boolean SV_SendLuaFile(INT32 node, const char *filename, boolean textmode)
 	filestosend++;
 	return true;
 }
-#endif
 
 /** Stops sending a file for a node, and removes the file request from the list,
   * either because the file has been fully sent or because the node was disconnected
@@ -1035,14 +1029,12 @@ void Got_Filetxpak(void)
 			file->status = FS_FOUND;
 			CONS_Printf(M_GetText("Downloading %s...(done)\n"),
 				filename);
-#ifdef HAVE_BLUA
 			if (luafiletransfers)
 			{
 				// Tell the server we have received the file
 				netbuffer->packettype = PT_HASLUAFILE;
 				HSendPacket(servernode, true, 0, 0);
 			}
-#endif
 		}
 	}
 	else
diff --git a/src/d_netfil.h b/src/d_netfil.h
index f0a7cf8cc..7d6efada0 100644
--- a/src/d_netfil.h
+++ b/src/d_netfil.h
@@ -72,7 +72,6 @@ boolean CL_CheckDownloadable(void);
 boolean CL_SendRequestFile(void);
 boolean Got_RequestFilePak(INT32 node);
 
-#ifdef HAVE_BLUA
 typedef enum
 {
 	LFTNS_WAITING, // This node is waiting for the server to send the file
@@ -108,7 +107,6 @@ void Got_LuaFile(UINT8 **cp, INT32 playernum);
 void StoreLuaFileCallback(INT32 id);
 void RemoveLuaFileCallback(INT32 id);
 void MakePathDirs(char *path);
-#endif
 
 void SV_AbortSendFiles(INT32 node);
 void CloseNetFile(void);
diff --git a/src/dehacked.c b/src/dehacked.c
index ab9bd136b..588b78142 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -40,9 +40,7 @@
 
 #include "m_cond.h"
 
-#ifdef HAVE_BLUA
 #include "v_video.h" // video flags (for lua)
-#endif
 
 #ifdef HWRENDER
 #include "hardware/hw_light.h"
@@ -77,10 +75,8 @@ static UINT16 get_mus(const char *word, UINT8 dehacked_mode);
 #endif
 static hudnum_t get_huditem(const char *word);
 static menutype_t get_menutype(const char *word);
-#ifndef HAVE_BLUA
-static INT16 get_gametype(const char *word);
-static powertype_t get_power(const char *word);
-#endif
+//static INT16 get_gametype(const char *word);
+//static powertype_t get_power(const char *word);
 
 boolean deh_loaded = false;
 static int dbg_line;
@@ -1416,7 +1412,6 @@ static void readlevelheader(MYFILE *f, INT32 num)
 			// Lua custom options also go above, contents may be case sensitive.
 			if (fastncmp(word, "LUA.", 4))
 			{
-#ifdef HAVE_BLUA
 				UINT8 j;
 				customoption_t *modoption;
 
@@ -1450,9 +1445,6 @@ static void readlevelheader(MYFILE *f, INT32 num)
 				modoption->option[31] = '\0';
 				strncpy(modoption->value,  word2, 255);
 				modoption->value[255] = '\0';
-#else
-				// Silently ignore.
-#endif
 				continue;
 			}
 
@@ -3124,22 +3116,20 @@ static void readframe(MYFILE *f, INT32 num)
 				}
 
 				z = 0;
-#ifdef HAVE_BLUA
 				found = LUA_SetLuaAction(&states[num], actiontocompare);
 				if (!found)
-#endif
-				while (actionpointers[z].name)
-				{
-					if (fastcmp(actiontocompare, actionpointers[z].name))
+					while (actionpointers[z].name)
 					{
-						states[num].action = actionpointers[z].action;
-						states[num].action.acv = actionpointers[z].action.acv; // assign
-						states[num].action.acp1 = actionpointers[z].action.acp1;
-						found = true;
-						break;
+						if (fastcmp(actiontocompare, actionpointers[z].name))
+						{
+							states[num].action = actionpointers[z].action;
+							states[num].action.acv = actionpointers[z].action.acv; // assign
+							states[num].action.acp1 = actionpointers[z].action.acp1;
+							found = true;
+							break;
+						}
+						z++;
 					}
-					z++;
-				}
 
 				if (!found)
 					deh_warning("Unknown action %s", actiontocompare);
@@ -8849,14 +8839,12 @@ static const char *const MOBJEFLAG_LIST[] = {
 	NULL
 };
 
-#ifdef HAVE_BLUA
 static const char *const MAPTHINGFLAG_LIST[4] = {
 	"EXTRA", // Extra flag for objects.
 	"OBJECTFLIP", // Reverse gravity flag for objects.
 	"OBJECTSPECIAL", // Special flag used with certain objects.
 	"AMBUSH" // Deaf monsters/do not react to sound.
 };
-#endif
 
 static const char *const PLAYERFLAG_LIST[] = {
 
@@ -8953,7 +8941,6 @@ static const char *const GAMETYPERULE_LIST[] = {
 	NULL
 };
 
-#ifdef HAVE_BLUA
 // Linedef flags
 static const char *const ML_LIST[16] = {
 	"IMPASSIBLE",
@@ -8973,7 +8960,6 @@ static const char *const ML_LIST[16] = {
 	"BOUNCY",
 	"TFERLINE"
 };
-#endif
 
 // This DOES differ from r_draw's Color_Names, unfortunately.
 // Also includes Super colors
@@ -9272,11 +9258,7 @@ static const char *const MENUTYPES_LIST[] = {
 struct {
 	const char *n;
 	// has to be able to hold both fixed_t and angle_t, so drastic measure!!
-#ifdef HAVE_BLUA
 	lua_Integer v;
-#else
-	INT64 v;
-#endif
 } const INT_CONST[] = {
 	// If a mod removes some variables here,
 	// please leave the names in-tact and just set
@@ -9532,7 +9514,6 @@ struct {
 	{"ME_ULTIMATE",ME_ULTIMATE},
 	{"ME_PERFECT",ME_PERFECT},
 
-#ifdef HAVE_BLUA
 	// p_local.h constants
 	{"FLOATSPEED",FLOATSPEED},
 	{"MAXSTEPMOVE",MAXSTEPMOVE},
@@ -9865,7 +9846,6 @@ struct {
 	{"TC_RAINBOW",TC_RAINBOW},
 	{"TC_BLINK",TC_BLINK},
 	{"TC_DASHMODE",TC_DASHMODE},
-#endif
 
 	{NULL,0}
 };
@@ -10022,8 +10002,7 @@ static menutype_t get_menutype(const char *word)
 	return MN_NONE;
 }
 
-#ifndef HAVE_BLUA
-static INT16 get_gametype(const char *word)
+/*static INT16 get_gametype(const char *word)
 { // Returns the value of GT_ enumerations
 	INT16 i;
 	if (*word >= '0' && *word <= '9')
@@ -10049,7 +10028,7 @@ static powertype_t get_power(const char *word)
 			return i;
 	deh_warning("Couldn't find power named 'pw_%s'",word);
 	return pw_invulnerability;
-}
+}*/
 
 /// \todo Make ANY of this completely over-the-top math craziness obey the order of operations.
 static fixed_t op_mul(fixed_t a, fixed_t b) { return a*b; }
@@ -10077,7 +10056,7 @@ struct {
 };
 
 // Returns the full word, cut at the first symbol or whitespace
-static char *read_word(const char *line)
+/*static char *read_word(const char *line)
 {
 	// Part 1: You got the start of the word, now find the end.
   const char *p;
@@ -10307,16 +10286,14 @@ static fixed_t find_const(const char **rword)
 	const_warning("constant",word);
 	free(word);
 	return 0;
-}
-#endif
+}*/
 
 // Loops through every constant and operation in word and performs its calculations, returning the final value.
 fixed_t get_number(const char *word)
 {
-#ifdef HAVE_BLUA
 	return LUA_EvalMath(word);
-#else
-	// DESPERATELY NEEDED: Order of operations support! :x
+
+	/*// DESPERATELY NEEDED: Order of operations support! :x
 	fixed_t i = find_const(&word);
 	INT32 o;
 	while(*word) {
@@ -10326,8 +10303,7 @@ fixed_t get_number(const char *word)
 		else
 			break;
 	}
-	return i;
-#endif
+	return i;*/
 }
 
 void DEH_Check(void)
@@ -10352,7 +10328,6 @@ void DEH_Check(void)
 #endif
 }
 
-#ifdef HAVE_BLUA
 #include "lua_script.h"
 #include "lua_libs.h"
 
@@ -10978,5 +10953,3 @@ void LUA_SetActionByName(void *state, const char *actiontocompare)
 		}
 	}
 }
-
-#endif // HAVE_BLUA
diff --git a/src/dehacked.h b/src/dehacked.h
index 80c31f3de..54225f36e 100644
--- a/src/dehacked.h
+++ b/src/dehacked.h
@@ -34,11 +34,9 @@ void DEH_Check(void);
 
 fixed_t get_number(const char *word);
 
-#ifdef HAVE_BLUA
 boolean LUA_SetLuaAction(void *state, const char *actiontocompare);
 const char *LUA_GetActionName(void *action);
 void LUA_SetActionByName(void *state, const char *actiontocompare);
-#endif
 
 extern boolean deh_loaded;
 
diff --git a/src/doomstat.h b/src/doomstat.h
index b7388fd96..893514b32 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -493,7 +493,6 @@ extern UINT16 emeralds;
 #define EMERALD7 64
 #define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7))
 
-// yes, even in non HAVE_BLUA
 #define NUM_LUABANKS 16 // please only make this number go up between versions, never down. you'll break saves otherwise. also, must fit in UINT8
 extern INT32 luabanks[NUM_LUABANKS];
 
diff --git a/src/f_finale.c b/src/f_finale.c
index c98d49842..95535a7ea 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -39,9 +39,7 @@
 #include "fastcmp.h"
 #include "console.h"
 
-#ifdef HAVE_BLUA
 #include "lua_hud.h"
-#endif
 
 // Stage of animation:
 // 0 = text, 1 = art screen
@@ -2762,11 +2760,7 @@ void F_TitleScreenDrawer(void)
 	// rei|miru: use title pics?
 	hidepics = curhidepics;
 	if (hidepics)
-#ifdef HAVE_BLUA
 		goto luahook;
-#else
-		return;
-#endif
 
 	switch(curttmode)
 	{
@@ -3488,10 +3482,8 @@ void F_TitleScreenDrawer(void)
 			break;
 	}
 
-#ifdef HAVE_BLUA
 luahook:
 	LUAh_TitleHUD();
-#endif
 }
 
 // separate animation timer for backgrounds, since we also count
diff --git a/src/f_wipe.c b/src/f_wipe.c
index 0fd6c1431..08d7ed991 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -33,9 +33,7 @@
 
 #include "doomstat.h"
 
-#ifdef HAVE_BLUA
 #include "lua_hud.h" // level title
-#endif
 
 #ifdef HWRENDER
 #include "hardware/hw_main.h"
diff --git a/src/filesrch.h b/src/filesrch.h
index 4186271b0..dfea8979e 100644
--- a/src/filesrch.h
+++ b/src/filesrch.h
@@ -60,7 +60,7 @@ typedef enum
 #endif
 	EXT_PK3,
 	EXT_SOC,
-	EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt
+	EXT_LUA,
 	NUM_EXT,
 	NUM_EXT_TABLE = NUM_EXT-EXT_START,
 	EXT_LOADED = 0x80
diff --git a/src/g_game.c b/src/g_game.c
index 030892223..bf73f6ce2 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -47,9 +47,7 @@
 #include "m_cond.h" // condition sets
 #include "md5.h" // demo checksums
 
-#ifdef HAVE_BLUA
 #include "lua_hud.h"
-#endif
 
 gameaction_t gameaction;
 gamestate_t gamestate = GS_NULL;
@@ -177,7 +175,7 @@ static boolean retryingmodeattack = false;
 UINT8 stagefailed; // Used for GEMS BONUS? Also to see if you beat the stage.
 
 UINT16 emeralds;
-INT32 luabanks[NUM_LUABANKS]; // yes, even in non HAVE_BLUA
+INT32 luabanks[NUM_LUABANKS];
 UINT32 token; // Number of tokens collected in a level
 UINT32 tokenlist; // List of tokens collected
 boolean gottoken; // Did you get a token? Used for end of act
@@ -1714,11 +1712,9 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 	if (ssplayer == 1 && (cmd->forwardmove || cmd->sidemove || cmd->buttons)
 		&& displayplayer != consoleplayer)
 	{
-#ifdef HAVE_BLUA
 		// Call ViewpointSwitch hooks here.
 		// The viewpoint was forcibly changed.
 		LUAh_ViewpointSwitch(player, &players[consoleplayer], true);
-#endif
 		displayplayer = consoleplayer;
 	}
 }
@@ -2048,9 +2044,7 @@ boolean G_Responder(event_t *ev)
 		&& (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1]))
 	{
 		// ViewpointSwitch Lua hook.
-#ifdef HAVE_BLUA
 		UINT8 canSwitchView = 0;
-#endif
 
 		if (splitscreen || !netgame)
 			displayplayer = consoleplayer;
@@ -2066,14 +2060,12 @@ boolean G_Responder(event_t *ev)
 				if (!playeringame[displayplayer])
 					continue;
 
-#ifdef HAVE_BLUA
 				// Call ViewpointSwitch hooks here.
 				canSwitchView = LUAh_ViewpointSwitch(&players[consoleplayer], &players[displayplayer], false);
 				if (canSwitchView == 1) // Set viewpoint to this player
 					break;
 				else if (canSwitchView == 2) // Skip this player
 					continue;
-#endif
 
 				if (players[displayplayer].spectator)
 					continue;
@@ -2673,9 +2665,7 @@ void G_SpawnPlayer(INT32 playernum)
 
 	P_SpawnPlayer(playernum);
 	G_MovePlayerToSpawnOrStarpost(playernum);
-#ifdef HAVE_BLUA
 	LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :)
-#endif
 }
 
 void G_MovePlayerToSpawnOrStarpost(INT32 playernum)
@@ -3029,9 +3019,7 @@ void G_DoReborn(INT32 playernum)
 		}
 		else
 		{
-#ifdef HAVE_BLUA
 			LUAh_MapChange(gamemap);
-#endif
 			titlecardforreload = true;
 			G_DoLoadLevel(true);
 			titlecardforreload = false;
@@ -6803,9 +6791,7 @@ void G_DoPlayDemo(char *defdemoname)
 	// Set skin
 	SetPlayerSkin(0, skin);
 
-#ifdef HAVE_BLUA
 	LUAh_MapChange(gamemap);
-#endif
 	displayplayer = consoleplayer = 0;
 	memset(playeringame,0,sizeof(playeringame));
 	playeringame[0] = true;
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 98f3ca5a9..6aa5a4510 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -47,10 +47,8 @@
 #include "hardware/hw_main.h"
 #endif
 
-#ifdef HAVE_BLUA
 #include "lua_hud.h"
 #include "lua_hook.h"
-#endif
 
 // coords are scaled
 #define HU_INPUTX 0
@@ -688,10 +686,8 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
 
 	// run the lua hook even if we were supposed to eat the msg, netgame consistency goes first.
 
-#ifdef HAVE_BLUA
 	if (LUAh_PlayerMsg(playernum, target, flags, msg))
 		return;
-#endif
 
 	if (spam_eatmsg)
 		return; // don't proceed if we were supposed to eat the message.
@@ -2177,18 +2173,14 @@ void HU_Drawer(void)
 	{
 		if (netgame || multiplayer)
 		{
-#ifdef HAVE_BLUA
 			if (LUA_HudEnabled(hud_rankings))
-#endif
-			HU_DrawRankings();
+				HU_DrawRankings();
 			if (gametype == GT_COOP)
 				HU_DrawNetplayCoopOverlay();
 		}
 		else
 			HU_DrawCoopOverlay();
-#ifdef HAVE_BLUA
 		LUAh_ScoresHUD();
-#endif
 	}
 
 	if (gamestate != GS_LEVEL)
@@ -3171,29 +3163,20 @@ static void HU_DrawRankings(void)
 
 static void HU_DrawCoopOverlay(void)
 {
-	if (token
-#ifdef HAVE_BLUA
-	&& LUA_HudEnabled(hud_tokens)
-#endif
-	)
+	if (token && LUA_HudEnabled(hud_tokens))
 	{
 		V_DrawString(168, 176, 0, va("- %d", token));
 		V_DrawSmallScaledPatch(148, 172, 0, tokenicon);
 	}
 
-#ifdef HAVE_BLUA
-	if (LUA_HudEnabled(hud_tabemblems))
-#endif
-	if (!modifiedgame || savemoddata)
+	if (LUA_HudEnabled(hud_tabemblems) && (!modifiedgame || savemoddata))
 	{
 		V_DrawString(160, 144, 0, va("- %d/%d", M_CountEmblems(), numemblems+numextraemblems));
 		V_DrawScaledPatch(128, 144 - SHORT(emblemicon->height)/4, 0, emblemicon);
 	}
 
-#ifdef HAVE_BLUA
 	if (!LUA_HudEnabled(hud_coopemeralds))
 		return;
-#endif
 
 	if (emeralds & EMERALD1)
 		V_DrawScaledPatch((BASEVIDWIDTH/2)-8   , (BASEVIDHEIGHT/3)-32, 0, emeraldpics[0][0]);
@@ -3215,20 +3198,14 @@ static void HU_DrawNetplayCoopOverlay(void)
 {
 	int i;
 
-	if (token
-#ifdef HAVE_BLUA
-	&& LUA_HudEnabled(hud_tokens)
-#endif
-	)
+	if (token && LUA_HudEnabled(hud_tokens))
 	{
 		V_DrawString(168, 10, 0, va("- %d", token));
 		V_DrawSmallScaledPatch(148, 6, 0, tokenicon);
 	}
 
-#ifdef HAVE_BLUA
 	if (!LUA_HudEnabled(hud_coopemeralds))
 		return;
-#endif
 
 	for (i = 0; i < 7; ++i)
 	{
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 26887da25..4f924aa18 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -11,7 +11,6 @@
 /// \brief basic functions for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "fastcmp.h"
 #include "p_local.h"
 #include "p_setup.h" // So we can have P_SetupLevelSky
@@ -3312,5 +3311,3 @@ int LUA_BaseLib(lua_State *L)
 	luaL_register(L, NULL, lib);
 	return 0;
 }
-
-#endif
diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c
index 78a9e75a1..bc8d20e8e 100644
--- a/src/lua_blockmaplib.c
+++ b/src/lua_blockmaplib.c
@@ -11,7 +11,6 @@
 /// \brief blockmap library for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "p_local.h"
 #include "r_main.h" // validcount
 #include "lua_script.h"
@@ -264,5 +263,3 @@ int LUA_BlockmapLib(lua_State *L)
 	lua_register(L, "searchBlockmap", lib_searchBlockmap);
 	return 0;
 }
-
-#endif
diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c
index 923722eb8..a9fbad65f 100644
--- a/src/lua_consolelib.c
+++ b/src/lua_consolelib.c
@@ -11,7 +11,6 @@
 /// \brief console modifying/etc library for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "fastcmp.h"
 #include "p_local.h"
 #include "g_game.h"
@@ -551,5 +550,3 @@ int LUA_ConsoleLib(lua_State *L)
 	luaL_register(L, NULL, lib);
 	return 0;
 }
-
-#endif
diff --git a/src/lua_hook.h b/src/lua_hook.h
index dde8d4c41..244b1bbb8 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -10,8 +10,6 @@
 /// \file  lua_hook.h
 /// \brief hooks for Lua scripting
 
-#ifdef HAVE_BLUA
-
 #include "r_defs.h"
 #include "d_player.h"
 
@@ -112,5 +110,3 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_
 #endif
 #define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
 boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing
-
-#endif
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 20a7738e7..522be8c32 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -11,7 +11,6 @@
 /// \brief hooks for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "doomstat.h"
 #include "p_mobj.h"
 #include "g_game.h"
@@ -1705,5 +1704,3 @@ boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname)
 
 	return keepplaying;
 }
-
-#endif
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 7d5f9325e..818e760c9 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -11,7 +11,6 @@
 /// \brief custom HUD rendering library for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "fastcmp.h"
 #include "r_defs.h"
 #include "r_local.h"
@@ -1466,5 +1465,3 @@ void LUAh_IntermissionHUD(void)
 	lua_pop(gL, -1);
 	hud_running = false;
 }
-
-#endif
diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index 6760b4203..25870d0b1 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -11,7 +11,6 @@
 /// \brief infotable editing library for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "fastcmp.h"
 #include "info.h"
 #include "dehacked.h"
@@ -1651,5 +1650,3 @@ int LUA_InfoLib(lua_State *L)
 
 	return 0;
 }
-
-#endif
diff --git a/src/lua_libs.h b/src/lua_libs.h
index f217d4b2a..bf1e28b5d 100644
--- a/src/lua_libs.h
+++ b/src/lua_libs.h
@@ -10,8 +10,6 @@
 /// \file  lua_libs.h
 /// \brief libraries for Lua scripting
 
-#ifdef HAVE_BLUA
-
 extern lua_State *gL;
 
 #define LREG_VALID "VALID_USERDATA"
@@ -88,5 +86,3 @@ int LUA_ThinkerLib(lua_State *L);
 int LUA_MapLib(lua_State *L);
 int LUA_BlockmapLib(lua_State *L);
 int LUA_HudLib(lua_State *L);
-
-#endif
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index 0344fd5bb..32150a4bc 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -11,7 +11,6 @@
 /// \brief game map library for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "r_state.h"
 #include "p_local.h"
 #include "p_setup.h"
@@ -2337,5 +2336,3 @@ int LUA_MapLib(lua_State *L)
 	lua_setglobal(L, "mapheaderinfo");
 	return 0;
 }
-
-#endif
diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c
index d2a959dde..215903278 100644
--- a/src/lua_mathlib.c
+++ b/src/lua_mathlib.c
@@ -11,7 +11,6 @@
 /// \brief basic math library for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 //#include "fastcmp.h"
 #include "tables.h"
 #include "p_local.h"
@@ -217,5 +216,3 @@ int LUA_MathLib(lua_State *L)
 	luaL_register(L, NULL, lib);
 	return 0;
 }
-
-#endif
diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c
index 9e46344cf..4b580a2fe 100644
--- a/src/lua_mobjlib.c
+++ b/src/lua_mobjlib.c
@@ -11,7 +11,6 @@
 /// \brief mobj/thing library for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "fastcmp.h"
 #include "r_skins.h"
 #include "p_local.h"
@@ -915,5 +914,3 @@ int LUA_MobjLib(lua_State *L)
 	lua_setglobal(L, "mapthings");
 	return 0;
 }
-
-#endif
diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index a33ecb7e0..cdece1fb7 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -11,7 +11,6 @@
 /// \brief player object library for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "fastcmp.h"
 #include "p_mobj.h"
 #include "d_player.h"
@@ -878,5 +877,3 @@ int LUA_PlayerLib(lua_State *L)
 	lua_setglobal(L, "players");
 	return 0;
 }
-
-#endif
diff --git a/src/lua_script.c b/src/lua_script.c
index e7ce35ff1..6fa6cf57d 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -11,7 +11,6 @@
 /// \brief Lua scripting basics
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "fastcmp.h"
 #include "dehacked.h"
 #include "z_zone.h"
@@ -1423,5 +1422,3 @@ int Lua_optoption(lua_State *L, int narg,
 			return i;
 	return -1;
 }
-
-#endif // HAVE_BLUA
diff --git a/src/lua_script.h b/src/lua_script.h
index 6caccd69b..7bdf7685b 100644
--- a/src/lua_script.h
+++ b/src/lua_script.h
@@ -10,8 +10,6 @@
 /// \file  lua_script.h
 /// \brief Lua scripting basics
 
-#ifdef HAVE_BLUA
-
 #include "m_fixed.h"
 #include "doomtype.h"
 #include "d_player.h"
@@ -102,5 +100,3 @@ void COM_Lua_f(void);
 
 #define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\
 return luaL_error(L, "This can only be used in a level!");
-
-#endif
diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c
index f26aed2f0..3e4ddb9f0 100644
--- a/src/lua_skinlib.c
+++ b/src/lua_skinlib.c
@@ -11,7 +11,6 @@
 /// \brief player skin structure library for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "fastcmp.h"
 #include "r_skins.h"
 #include "sounds.h"
@@ -358,5 +357,3 @@ int LUA_SkinLib(lua_State *L)
 
 	return 0;
 }
-
-#endif
diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c
index ddb5abf72..82baa6469 100644
--- a/src/lua_thinkerlib.c
+++ b/src/lua_thinkerlib.c
@@ -11,7 +11,6 @@
 /// \brief thinker library for Lua scripting
 
 #include "doomdef.h"
-#ifdef HAVE_BLUA
 #include "p_local.h"
 #include "lua_script.h"
 #include "lua_libs.h"
@@ -139,5 +138,3 @@ int LUA_ThinkerLib(lua_State *L)
 	lua_setglobal(L, "mobjs");
 	return 0;
 }
-
-#endif
diff --git a/src/m_cheat.c b/src/m_cheat.c
index 1431e8873..93e8f2911 100644
--- a/src/m_cheat.c
+++ b/src/m_cheat.c
@@ -788,7 +788,7 @@ void Command_CauseCfail_f(void)
 }
 #endif
 
-#if defined(HAVE_BLUA) && defined(LUA_ALLOW_BYTECODE)
+#ifdef LUA_ALLOW_BYTECODE
 void Command_Dumplua_f(void)
 {
 	if (modifiedgame)
@@ -1062,9 +1062,7 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
 	mapthing_t *mt = mapthings;
 	sector_t *sec = player->mo->subsector->sector;
 
-#ifdef HAVE_BLUA
 	LUA_InvalidateMapthings();
-#endif
 
 	mapthings = Z_Realloc(mapthings, ++nummapthings * sizeof (*mapthings), PU_LEVEL, NULL);
 
diff --git a/src/m_cheat.h b/src/m_cheat.h
index 092e51756..ac2540408 100644
--- a/src/m_cheat.h
+++ b/src/m_cheat.h
@@ -68,7 +68,7 @@ void Command_Toggletwod_f(void);
 #ifdef _DEBUG
 void Command_CauseCfail_f(void);
 #endif
-#if defined(HAVE_BLUA) && defined(LUA_ALLOW_BYTECODE)
+#ifdef LUA_ALLOW_BYTECODE
 void Command_Dumplua_f(void);
 #endif
 
diff --git a/src/m_menu.c b/src/m_menu.c
index e8915f91f..84ee898d6 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -6657,12 +6657,6 @@ static void M_HandleAddons(INT32 choice)
 							M_AddonExec(KEY_ENTER);
 							break;
 						case EXT_LUA:
-#ifndef HAVE_BLUA
-							S_StartSound(NULL, sfx_lose);
-							M_StartMessage(va("%c%s\x80\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING);
-							break;
-#endif
-						/* FALLTHRU */
 						case EXT_SOC:
 						case EXT_WAD:
 #ifdef USE_KART
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 14e5c4d3e..9dea0ecc5 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -30,9 +30,7 @@
 #include "hardware/hw3sound.h"
 #endif
 
-#ifdef HAVE_BLUA
 boolean LUA_CallAction(const char *action, mobj_t *actor);
-#endif
 
 player_t *stplyr;
 INT32 var1;
@@ -981,10 +979,8 @@ void A_Look(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Look", actor))
 		return;
-#endif
 
 	if (!P_LookForPlayers(actor, locvar1 & 65535, false , FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale)))
 		return;
@@ -1016,10 +1012,8 @@ void A_Chase(mobj_t *actor)
 	INT32 delta;
 	INT32 locvar1 = var1;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Chase", actor))
 		return;
-#endif
 
 	I_Assert(actor != NULL);
 	I_Assert(!P_MobjWasRemoved(actor));
@@ -1109,10 +1103,8 @@ void A_FaceStabChase(mobj_t *actor)
 {
 	INT32 delta;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FaceStabChase", actor))
 		return;
-#endif
 
 	if (actor->reactiontime)
 		actor->reactiontime--;
@@ -1233,10 +1225,8 @@ void A_FaceStabRev(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FaceStabRev", actor))
 		return;
-#endif
 
 	if (!actor->target)
 	{
@@ -1278,10 +1268,8 @@ void A_FaceStabHurl(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FaceStabHurl", actor))
 		return;
-#endif
 
 	if (actor->target)
 	{
@@ -1368,13 +1356,10 @@ void A_FaceStabHurl(mobj_t *actor)
 //
 void A_FaceStabMiss(mobj_t *actor)
 {
-	//INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FaceStabMiss", actor))
 		return;
-#endif
 
 	if (++actor->extravalue1 >= 3)
 	{
@@ -1408,10 +1393,8 @@ void A_StatueBurst(mobj_t *actor)
 	mobjtype_t chunktype = (mobjtype_t)actor->info->raisestate;
 	mobj_t *new;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_StatueBurst", actor))
 		return;
-#endif
 
 	if (!locvar1 || !(new = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar1)))
 		return;
@@ -1460,10 +1443,9 @@ void A_StatueBurst(mobj_t *actor)
 //
 void A_JetJawRoam(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_JetJawRoam", actor))
 		return;
-#endif
+
 	if (actor->reactiontime)
 	{
 		actor->reactiontime--;
@@ -1489,10 +1471,9 @@ void A_JetJawRoam(mobj_t *actor)
 void A_JetJawChomp(mobj_t *actor)
 {
 	INT32 delta;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_JetJawChomp", actor))
 		return;
-#endif
 
 	// turn towards movement direction if not there yet
 	if (actor->movedir < NUMDIRS)
@@ -1538,10 +1519,9 @@ void A_PointyThink(mobj_t *actor)
 	boolean firsttime = true;
 	INT32 sign;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_PointyThink", actor))
 		return;
-#endif
+
 	actor->momx = actor->momy = actor->momz = 0;
 
 	// Find nearest player
@@ -1637,10 +1617,9 @@ void A_CheckBuddy(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_CheckBuddy", actor))
 		return;
-#endif
+
 	if (locvar1 && (!actor->tracer || actor->tracer->health <= 0))
 		P_RemoveMobj(actor);
 	else if (!locvar1 && (!actor->target || actor->target->health <= 0))
@@ -1680,11 +1659,9 @@ void A_HoodFire(mobj_t *actor)
 {
 	mobj_t *arrow;
 	INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_HoodFire", actor))
 		return;
-#endif
 
 	// Check target first.
 	if (!actor->target)
@@ -1714,10 +1691,9 @@ void A_HoodThink(mobj_t *actor)
 {
 	fixed_t dx, dy, dz, dm;
 	boolean checksight;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_HoodThink", actor))
 		return;
-#endif
 
 	// Check target first.
 	if (!actor->target)
@@ -1783,10 +1759,8 @@ void A_HoodThink(mobj_t *actor)
 //
 void A_HoodFall(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_HoodFall", actor))
 		return;
-#endif
 
 	if (!P_IsObjectOnGround(actor))
 		return;
@@ -1805,10 +1779,8 @@ void A_HoodFall(mobj_t *actor)
 //
 void A_ArrowBonks(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_ArrowBonks", actor))
 		return;
-#endif
 
 	if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)
 		|| (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz))
@@ -1830,10 +1802,8 @@ void A_ArrowBonks(mobj_t *actor)
 //
 void A_SnailerThink(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SnailerThink", actor))
 		return;
-#endif
 
 	if (!actor->target || !(actor->target->flags & MF_SHOOTABLE))
 	{
@@ -1905,10 +1875,8 @@ void A_SnailerThink(mobj_t *actor)
 //
 void A_SharpChase(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SharpChase", actor))
 		return;
-#endif
 
 	if (actor->reactiontime)
 	{
@@ -1963,10 +1931,8 @@ void A_SharpSpin(mobj_t *actor)
 	INT32 locvar2 = var2;
 	angle_t oldang = actor->angle;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SharpSpin", actor))
 		return;
-#endif
 
 	if (actor->threshold && actor->target)
 	{
@@ -1998,10 +1964,8 @@ void A_SharpSpin(mobj_t *actor)
 //
 void A_SharpDecel(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SharpDecel", actor))
 		return;
-#endif
 
 	if (actor->momx > 2 || actor->momy > 2)
 	{
@@ -2024,10 +1988,9 @@ void A_CrushstaceanWalk(mobj_t *actor)
 	INT32 locvar1 = (var1 ? var1 : (INT32)actor->info->speed);
 	INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate);
 	angle_t ang = actor->angle + ((actor->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CrushstaceanWalk", actor))
 		return;
-#endif
 
 	actor->reactiontime--;
 
@@ -2053,12 +2016,10 @@ void A_CrushstaceanWalk(mobj_t *actor)
 //
 void A_CrushstaceanPunch(mobj_t *actor)
 {
-	//INT32 locvar1 = var1;
 	INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CrushstaceanPunch", actor))
 		return;
-#endif
 
 	if (!actor->tracer)
 		return;
@@ -2088,10 +2049,9 @@ void A_CrushclawAim(mobj_t *actor)
 	INT32 locvar2 = var2;
 	mobj_t *crab = actor->tracer;
 	angle_t ang;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CrushclawAim", actor))
 		return;
-#endif
 
 	if (!crab)
 	{
@@ -2150,10 +2110,9 @@ void A_CrushclawLaunch(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	mobj_t *crab = actor->tracer;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CrushclawLaunch", actor))
 		return;
-#endif
 
 	if (!crab)
 	{
@@ -2283,10 +2242,8 @@ void A_CrushclawLaunch(mobj_t *actor)
 //
 void A_VultureVtol(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_VultureVtol", actor))
 		return;
-#endif
 
 	if (!actor->target)
 		return;
@@ -2320,10 +2277,8 @@ void A_VultureVtol(mobj_t *actor)
 //
 void A_VultureCheck(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_VultureCheck", actor))
 		return;
-#endif
 
 	if (actor->momx || actor->momy)
 		return;
@@ -2378,10 +2333,8 @@ void A_VultureHover(mobj_t *actor)
 	fixed_t memz = actor->z;
 	SINT8 i;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_VultureHover", actor))
 		return;
-#endif
 
 	if (!actor->target || P_MobjWasRemoved(actor->target))
 	{
@@ -2442,10 +2395,8 @@ void A_VultureBlast(mobj_t *actor)
 	angle_t faa;
 	fixed_t faacos, faasin;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_VultureBlast", actor))
 		return;
-#endif
 
 	S_StartSound(actor, actor->info->attacksound);
 
@@ -2483,10 +2434,8 @@ void A_VultureFly(mobj_t *actor)
 	mobj_t *dust;
 	fixed_t momm;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_VultureFly", actor))
 		return;
-#endif
 
 	if (!actor->target || P_MobjWasRemoved(actor->target))
 	{
@@ -2577,10 +2526,9 @@ void A_SkimChase(mobj_t *actor)
 {
 	INT32 delta;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SkimChase", actor))
 		return;
-#endif
+
 	if (actor->reactiontime)
 		actor->reactiontime--;
 
@@ -2664,10 +2612,9 @@ nomissile:
 //
 void A_FaceTarget(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FaceTarget", actor))
 		return;
-#endif
+
 	if (!actor->target)
 		return;
 
@@ -2683,10 +2630,9 @@ void A_FaceTarget(mobj_t *actor)
 //
 void A_FaceTracer(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FaceTracer", actor))
 		return;
-#endif
+
 	if (!actor->tracer)
 		return;
 
@@ -2713,10 +2659,9 @@ void A_LobShot(mobj_t *actor)
 	fixed_t vertical, horizontal;
 	fixed_t airtime = var2 & 65535;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_LobShot", actor))
 		return;
-#endif
+
 	if (!actor->target)
 		return;
 
@@ -2814,10 +2759,9 @@ void A_FireShot(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FireShot", actor))
 		return;
-#endif
+
 	if (!actor->target)
 		return;
 
@@ -2853,10 +2797,9 @@ void A_SuperFireShot(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SuperFireShot", actor))
 		return;
-#endif
+
 	if (!actor->target)
 		return;
 
@@ -2901,10 +2844,9 @@ void A_BossFireShot(mobj_t *actor)
 	INT32 locvar2 = var2;
 	mobj_t *missile;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_BossFireShot", actor))
 		return;
-#endif
+
 	if (!actor->target)
 		return;
 
@@ -2986,10 +2928,8 @@ void A_Boss7FireMissiles(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Boss7FireMissiles", actor))
 		return;
-#endif
 
 	if (!actor->target)
 	{
@@ -3050,10 +2990,9 @@ void A_Boss1Laser(mobj_t *actor)
 	mobj_t *point;
 	tic_t dur;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Boss1Laser", actor))
 		return;
-#endif
+
 	if (!actor->target)
 		return;
 
@@ -3175,10 +3114,9 @@ void A_FocusTarget(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FocusTarget", actor))
 		return;
-#endif
 
 	if (actor->target)
 	{
@@ -3227,10 +3165,10 @@ void A_Boss4Reverse(mobj_t *actor)
 {
 	sfxenum_t locvar1 = (sfxenum_t)var1;
 	sfxenum_t locvar2 = (sfxenum_t)var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss4Reverse", actor))
 		return;
-#endif
+
 	actor->reactiontime = 0;
 	if (actor->movedir < 3)
 	{
@@ -3262,10 +3200,10 @@ void A_Boss4Reverse(mobj_t *actor)
 void A_Boss4SpeedUp(mobj_t *actor)
 {
 	sfxenum_t locvar1 = (sfxenum_t)var1;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss4SpeedUp", actor))
 		return;
-#endif
+
 	S_StartSound(NULL, locvar1);
 	actor->reactiontime = 2;
 }
@@ -3280,10 +3218,10 @@ void A_Boss4SpeedUp(mobj_t *actor)
 void A_Boss4Raise(mobj_t *actor)
 {
 	sfxenum_t locvar1 = (sfxenum_t)var1;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss4Raise", actor))
 		return;
-#endif
+
 	S_StartSound(NULL, locvar1);
 	actor->reactiontime = 1;
 }
@@ -3312,10 +3250,9 @@ void A_SkullAttack(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SkullAttack", actor))
 		return;
-#endif
+
 	if (!actor->target)
 		return;
 
@@ -3431,10 +3368,9 @@ void A_BossZoom(mobj_t *actor)
 	angle_t an;
 	INT32 dist;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_BossZoom", actor))
 		return;
-#endif
+
 	if (!actor->target)
 		return;
 
@@ -3472,10 +3408,9 @@ void A_BossScream(mobj_t *actor)
 	INT32 locvar2 = var2;
 	mobjtype_t explodetype;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_BossScream", actor))
 		return;
-#endif
+
 	if (locvar1 & 1)
 		fa = (FixedAngle(P_RandomKey(360)*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK;
 	else
@@ -3518,10 +3453,9 @@ void A_BossScream(mobj_t *actor)
 //
 void A_Scream(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Scream", actor))
 		return;
-#endif
+
 	if (actor->tracer && (actor->tracer->type == MT_SHELL || actor->tracer->type == MT_FIREBALL))
 		S_StartScreamSound(actor, sfx_mario2);
 	else if (actor->info->deathsound)
@@ -3537,10 +3471,9 @@ void A_Scream(mobj_t *actor)
 //
 void A_Pain(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Pain", actor))
 		return;
-#endif
+
 	if (actor->info->painsound)
 		S_StartSound(actor, actor->info->painsound);
 
@@ -3559,10 +3492,9 @@ void A_Fall(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Fall", actor))
 		return;
-#endif
+
 	// actor is on ground, it can be walked over
 	actor->flags &= ~MF_SOLID;
 
@@ -3592,10 +3524,9 @@ void A_1upThinker(mobj_t *actor)
 	fixed_t temp;
 	INT32 closestplayer = -1;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_1upThinker", actor))
 		return;
-#endif
+
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
 		if (!playeringame[i] || players[i].bot || players[i].spectator)
@@ -3659,10 +3590,8 @@ void A_MonitorPop(mobj_t *actor)
 	mobjtype_t item = 0;
 	mobj_t *newmobj;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_MonitorPop", actor))
 		return;
-#endif
 
 	// Spawn the "pop" explosion.
 	if (actor->info->deathsound)
@@ -3742,10 +3671,8 @@ void A_GoldMonitorPop(mobj_t *actor)
 	mobjtype_t item = 0;
 	mobj_t *newmobj;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_GoldMonitorPop", actor))
 		return;
-#endif
 
 	// Don't spawn the "pop" explosion, because the monitor isn't broken.
 	if (actor->info->deathsound)
@@ -3827,10 +3754,8 @@ void A_GoldMonitorPop(mobj_t *actor)
 //
 void A_GoldMonitorRestore(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_GoldMonitorRestore", actor))
 		return;
-#endif
 
 	actor->flags |= MF_MONITOR|MF_SHOOTABLE;
 	actor->health = 1; // Just in case.
@@ -3847,10 +3772,8 @@ void A_GoldMonitorSparkle(mobj_t *actor)
 {
 	fixed_t i, ngangle, xofs, yofs;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_GoldMonitorSparkle", actor))
 		return;
-#endif
 
 	ngangle = FixedAngle(((leveltime * 21) % 360) << FRACBITS);
 	xofs = FINESINE((ngangle>>ANGLETOFINESHIFT) & FINEMASK)   * (actor->radius>>FRACBITS);
@@ -3870,10 +3793,10 @@ void A_GoldMonitorSparkle(mobj_t *actor)
 void A_Explode(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Explode", actor))
 		return;
-#endif
+
 	P_RadiusAttack(actor, actor->target, actor->info->damage, locvar1);
 }
 
@@ -3890,10 +3813,9 @@ void A_BossDeath(mobj_t *mo)
 	mobj_t *mo2;
 	line_t junk;
 	INT32 i;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_BossDeath", mo))
 		return;
-#endif
 
 	if (mo->spawnpoint && mo->spawnpoint->extrainfo)
 		P_LinedefExecute(LE_BOSSDEAD+(mo->spawnpoint->extrainfo*LE_PARAMWIDTH), mo, NULL);
@@ -3973,12 +3895,10 @@ void A_BossDeath(mobj_t *mo)
 	}
 
 bossjustdie:
-#ifdef HAVE_BLUA
 	if (LUAh_BossDeath(mo))
 		return;
 	else if (P_MobjWasRemoved(mo))
 		return;
-#endif
 
 	// Spawn your junk
 	switch (mo->type)
@@ -4202,10 +4122,9 @@ void A_CustomPower(mobj_t *actor)
 	INT32 locvar2 = var2;
 	boolean spawnshield = false;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_CustomPower", actor))
 		return;
-#endif
+
 	if (!actor->target || !actor->target->player)
 	{
 		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
@@ -4243,10 +4162,9 @@ void A_GiveWeapon(mobj_t *actor)
 	player_t *player;
 	INT32 locvar1 = var1;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_GiveWeapon", actor))
 		return;
-#endif
+
 	if (!actor->target || !actor->target->player)
 	{
 		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
@@ -4277,10 +4195,9 @@ void A_RingBox(mobj_t *actor)
 {
 	player_t *player;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_RingBox", actor))
 		return;
-#endif
+
 	if (!actor->target || !actor->target->player)
 	{
 		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
@@ -4305,10 +4222,9 @@ void A_Invincibility(mobj_t *actor)
 {
 	player_t *player;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Invincibility", actor))
 		return;
-#endif
+
 	if (!actor->target || !actor->target->player)
 	{
 		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
@@ -4339,10 +4255,9 @@ void A_SuperSneakers(mobj_t *actor)
 {
 	player_t *player;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SuperSneakers", actor))
 		return;
-#endif
+
 	if (!actor->target || !actor->target->player)
 	{
 		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
@@ -4375,10 +4290,9 @@ void A_AwardScore(mobj_t *actor)
 {
 	player_t *player;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_AwardScore", actor))
 		return;
-#endif
+
 	if (!actor->target || !actor->target->player)
 	{
 		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
@@ -4403,10 +4317,9 @@ void A_ExtraLife(mobj_t *actor)
 {
 	player_t *player;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_ExtraLife", actor))
 		return;
-#endif
+
 	if (!actor->target || !actor->target->player)
 	{
 		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
@@ -4442,10 +4355,9 @@ void A_GiveShield(mobj_t *actor)
 	player_t *player;
 	UINT16 locvar1 = var1;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_GiveShield", actor))
 		return;
-#endif
+
 	if (!actor->target || !actor->target->player)
 	{
 		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
@@ -4469,10 +4381,9 @@ void A_GravityBox(mobj_t *actor)
 {
 	player_t *player;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_GravityBox", actor))
 		return;
-#endif
+
 	if (!actor->target || !actor->target->player)
 	{
 		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
@@ -4495,10 +4406,9 @@ void A_GravityBox(mobj_t *actor)
 //
 void A_ScoreRise(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_ScoreRise", actor))
 		return;
-#endif
+
 	// make logo rise!
 	P_SetObjectMomZ(actor, actor->info->speed, false);
 }
@@ -4515,10 +4425,9 @@ void A_BunnyHop(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_BunnyHop", actor))
 		return;
-#endif
+
 	if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)
 		|| (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz))
 	{
@@ -4539,10 +4448,10 @@ void A_BubbleSpawn(mobj_t *actor)
 	INT32 i, locvar1 = var1;
 	UINT8 prandom;
 	mobj_t *bubble = NULL;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_BubbleSpawn", actor))
 		return;
-#endif
+
 	if (!(actor->eflags & MFE_UNDERWATER))
 	{
 		// Don't draw or spawn bubbles above water
@@ -4592,10 +4501,10 @@ void A_FanBubbleSpawn(mobj_t *actor)
 	UINT8 prandom;
 	mobj_t *bubble = NULL;
 	fixed_t hz = actor->z + (4*actor->height)/5;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FanBubbleSpawn", actor))
 		return;
-#endif
+
 	if (!(actor->eflags & MFE_UNDERWATER))
 		return;
 
@@ -4639,10 +4548,9 @@ void A_BubbleRise(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_BubbleRise", actor))
 		return;
-#endif
+
 	if (actor->type == MT_EXTRALARGEBUBBLE)
 		P_SetObjectMomZ(actor, FixedDiv(6*FRACUNIT,5*FRACUNIT), false); // make bubbles rise!
 	else
@@ -4676,10 +4584,9 @@ void A_BubbleRise(mobj_t *actor)
 //
 void A_BubbleCheck(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_BubbleCheck", actor))
 		return;
-#endif
+
 	if (actor->eflags & MFE_UNDERWATER)
 		actor->flags2 &= ~MF2_DONTDRAW; // underwater so draw
 	else
@@ -4695,10 +4602,9 @@ void A_BubbleCheck(mobj_t *actor)
 //
 void A_AttractChase(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_AttractChase", actor))
 		return;
-#endif
+
 	if (actor->flags2 & MF2_NIGHTSPULL || !actor->health)
 		return;
 
@@ -4766,10 +4672,9 @@ void A_DropMine(mobj_t *actor)
 	INT32 locvar2 = var2;
 	fixed_t z;
 	mobj_t *mine;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_DropMine", actor))
 		return;
-#endif
 
 	if (locvar2 & 65535)
 	{
@@ -4815,10 +4720,9 @@ void A_FishJump(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FishJump", actor))
 		return;
-#endif
 
 	if (locvar2)
 	{
@@ -4867,10 +4771,9 @@ void A_ThrownRing(mobj_t *actor)
 	INT32 stop;
 	player_t *player;
 	fixed_t dist;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ThrownRing", actor))
 		return;
-#endif
 
 	if (leveltime % (TICRATE/7) == 0)
 	{
@@ -5025,10 +4928,9 @@ void A_ThrownRing(mobj_t *actor)
 //
 void A_SetSolidSteam(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SetSolidSteam", actor))
 		return;
-#endif
+
 	actor->flags &= ~MF_NOCLIP;
 	actor->flags |= MF_SOLID;
 	if (!(actor->flags2 & MF2_AMBUSH))
@@ -5057,10 +4959,9 @@ void A_SetSolidSteam(mobj_t *actor)
 //
 void A_UnsetSolidSteam(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_UnsetSolidSteam", actor))
 		return;
-#endif
+
 	actor->flags &= ~MF_SOLID;
 	actor->flags |= MF_NOCLIP;
 }
@@ -5078,10 +4979,8 @@ void A_SignSpin(mobj_t *actor)
 	INT16 i;
 	angle_t rotateangle = FixedAngle(locvar1 << FRACBITS);
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SignSpin", actor))
 		return;
-#endif
 
 	if (P_IsObjectOnGround(actor) && P_MobjFlip(actor) * actor->momz <= 0)
 	{
@@ -5149,10 +5048,8 @@ void A_SignPlayer(mobj_t *actor)
 	UINT8 facecolor, signcolor = (UINT8)locvar2;
 	UINT32 signframe = states[actor->info->raisestate].frame;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SignPlayer", actor))
 		return;
-#endif
 
 	if (actor->tracer == NULL || locvar1 < -3 || locvar1 >= numskins || signcolor >= MAXTRANSLATIONS)
 		return;
@@ -5280,10 +5177,10 @@ void A_SignPlayer(mobj_t *actor)
 void A_OverlayThink(mobj_t *actor)
 {
 	fixed_t destx, desty;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_OverlayThink", actor))
 		return;
-#endif
+
 	if (!actor->target)
 		return;
 
@@ -5332,10 +5229,9 @@ void A_OverlayThink(mobj_t *actor)
 void A_JetChase(mobj_t *actor)
 {
 	fixed_t thefloor;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_JetChase", actor))
 		return;
-#endif
 
 	if (actor->flags2 & MF2_AMBUSH)
 		return;
@@ -5429,10 +5325,9 @@ void A_JetbThink(mobj_t *actor)
 {
 	sector_t *nextsector;
 	fixed_t thefloor;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_JetbThink", actor))
 		return;
-#endif
 
 	if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz
 		&& actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale))
@@ -5495,10 +5390,9 @@ void A_JetbThink(mobj_t *actor)
 void A_JetgShoot(mobj_t *actor)
 {
 	fixed_t dist;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_JetgShoot", actor))
 		return;
-#endif
 
 	if (!actor->target)
 		return;
@@ -5536,10 +5430,9 @@ void A_JetgShoot(mobj_t *actor)
 void A_ShootBullet(mobj_t *actor)
 {
 	fixed_t dist;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ShootBullet", actor))
 		return;
-#endif
 
 	if (!actor->target)
 		return;
@@ -5598,10 +5491,8 @@ void A_MinusDigging(mobj_t *actor)
 	fixed_t mz = (actor->eflags & MFE_VERTICALFLIP) ? actor->ceilingz : actor->floorz;
 	mobj_t *par;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_MinusDigging", actor))
 		return;
-#endif
 
 	if (!actor->target)
 	{
@@ -5681,10 +5572,8 @@ void A_MinusPopup(mobj_t *actor)
 	angle_t ani = FixedAngle(FRACUNIT*360/num);
 	INT32 i;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_MinusPopup", actor))
 		return;
-#endif
 
 	if (actor->eflags & MFE_VERTICALFLIP)
 		actor->momz = -10*FRACUNIT;
@@ -5718,10 +5607,8 @@ void A_MinusCheck(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_MinusCheck", actor))
 		return;
-#endif
 
 	if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz) || (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz))
 	{
@@ -5751,10 +5638,9 @@ void A_MinusCheck(mobj_t *actor)
 //
 void A_ChickenCheck(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_ChickenCheck", actor))
 		return;
-#endif
+
 	if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)
 	|| (actor->eflags & MFE_VERTICALFLIP && actor->z + actor->height >= actor->ceilingz))
 	{
@@ -5782,10 +5668,9 @@ void A_JetgThink(mobj_t *actor)
 	sector_t *nextsector;
 
 	fixed_t thefloor;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_JetgThink", actor))
 		return;
-#endif
 
 	if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz
 		&& actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale))
@@ -5834,10 +5719,8 @@ void A_JetgThink(mobj_t *actor)
 //
 void A_MouseThink(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_MouseThink", actor))
 		return;
-#endif
 
 	if (actor->reactiontime)
 		actor->reactiontime--;
@@ -5872,10 +5755,9 @@ void A_DetonChase(mobj_t *actor)
 {
 	angle_t exact;
 	fixed_t xydist, dist;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_DetonChase", actor))
 		return;
-#endif
 
 	// modify tracer threshold
 	if (!actor->tracer || actor->tracer->health <= 0)
@@ -6020,10 +5902,9 @@ void A_CapeChase(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	angle_t angle;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CapeChase", actor))
 		return;
-#endif
 
 	CONS_Debug(DBG_GAMELOGIC, "A_CapeChase called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
 
@@ -6081,10 +5962,9 @@ void A_RotateSpikeBall(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	const fixed_t radius = FixedMul(12*actor->info->speed, actor->scale);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_RotateSpikeBall", actor))
 		return;
-#endif
 
 	if (!((!locvar1 && (actor->target)) || (locvar1 && (actor->tracer))))// This should NEVER happen.
 	{
@@ -6134,10 +6014,8 @@ void A_UnidusBall(mobj_t *actor)
 	INT32 locvar1 = var1;
 	boolean canthrow = false;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_UnidusBall", actor))
 		return;
-#endif
 
 	actor->angle += ANGLE_11hh;
 
@@ -6232,10 +6110,9 @@ void A_RockSpawn(mobj_t *actor)
 	line_t *line;
 	fixed_t dist;
 	fixed_t randomoomph;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_RockSpawn", actor))
 		return;
-#endif
 
 	if (i == -1)
 	{
@@ -6286,10 +6163,9 @@ void A_SlingAppear(mobj_t *actor)
 {
 	UINT8 mlength = 4;
 	mobj_t *spawnee, *hprev;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SlingAppear", actor))
 		return;
-#endif
 
 	P_UnsetThingPosition(actor);
 	actor->flags &= ~(MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT);
@@ -6337,10 +6213,9 @@ void A_SetFuse(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SetFuse", actor))
 		return;
-#endif
 
 	if ((!actor->fuse || (locvar2 >> 16)) && (locvar2 >> 16) != 2) // set the actor's fuse value
 		actor->fuse = locvar1;
@@ -6367,10 +6242,9 @@ void A_CrawlaCommanderThink(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	boolean hovermode = (actor->health > 1 || actor->fuse);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CrawlaCommanderThink", actor))
 		return;
-#endif
 
 	if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz
 		&& actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale))
@@ -6526,10 +6400,9 @@ void A_RingExplode(mobj_t *actor)
 	mobj_t *mo2;
 	thinker_t *th;
 	angle_t d;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_RingExplode", actor))
 		return;
-#endif
 
 	for (d = 0; d < 16; d++)
 		P_SpawnParaloop(actor->x, actor->y, actor->z + actor->height, FixedMul(actor->info->painchance, actor->scale), 16, MT_NIGHTSPARKLE, S_NULL, d*(ANGLE_22h), true);
@@ -6571,12 +6444,10 @@ void A_OldRingExplode(mobj_t *actor) {
 	mobj_t *mo;
 	const fixed_t ns = FixedMul(20 * FRACUNIT, actor->scale);
 	INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
 	boolean changecolor = (actor->target && actor->target->player);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_OldRingExplode", actor))
 		return;
-#endif
 
 	for (i = 0; i < 32; i++)
 	{
@@ -6650,12 +6521,9 @@ void A_MixUp(mobj_t *actor)
 {
 	boolean teleported[MAXPLAYERS];
 	INT32 i, numplayers = 0, prandom = 0;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_MixUp", actor))
 		return;
-#else
-	(void)actor;
-#endif
 
 	if (!multiplayer)
 		return;
@@ -6934,15 +6802,8 @@ void A_RecyclePowers(mobj_t *actor)
 	INT32 weapons[MAXPLAYERS];
 	INT32 weaponheld[MAXPLAYERS];
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_RecyclePowers", actor))
 		return;
-#endif
-
-#if !defined(WEIGHTEDRECYCLER) && !defined(HAVE_BLUA)
-	// actor is used in all scenarios but this one, funny enough
-	(void)actor;
-#endif
 
 	if (!multiplayer)
 	{
@@ -7069,10 +6930,9 @@ void A_RecyclePowers(mobj_t *actor)
 void A_Boss1Chase(mobj_t *actor)
 {
 	INT32 delta;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss1Chase", actor))
 		return;
-#endif
 
 	if (!actor->target || !(actor->target->flags & MF_SHOOTABLE))
 	{
@@ -7193,10 +7053,9 @@ void A_Boss2Chase(mobj_t *actor)
 	fixed_t radius;
 	boolean reverse = false;
 	INT32 speedvar;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss2Chase", actor))
 		return;
-#endif
 
 	if (actor->health <= 0)
 		return;
@@ -7321,10 +7180,9 @@ void A_Boss2Chase(mobj_t *actor)
 //
 void A_Boss2Pogo(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Boss2Pogo", actor))
 		return;
-#endif
+
 	if (actor->z <= actor->floorz + FixedMul(8*FRACUNIT, actor->scale) && actor->momz <= 0)
 	{
 		if (actor->state != &states[actor->info->raisestate])
@@ -7369,10 +7227,10 @@ void A_Boss2Pogo(mobj_t *actor)
 void A_Boss2TakeDamage(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss2TakeDamage", actor))
 		return;
-#endif
+
 	A_Pain(actor);
 	actor->reactiontime = 1; // turn around
 	if (locvar1 == 0) // old A_Invincibilerize behavior
@@ -7392,10 +7250,9 @@ void A_Boss7Chase(mobj_t *actor)
 {
 	INT32 delta;
 	INT32 i;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss7Chase", actor))
 		return;
-#endif
 
 	if (actor->z != actor->floorz)
 		return;
@@ -7524,10 +7381,9 @@ void A_Boss7Chase(mobj_t *actor)
 //
 void A_GoopSplat(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_GoopSplat", actor))
 		return;
-#endif
+
 	P_UnsetThingPosition(actor);
 	if (sector_list)
 	{
@@ -7549,10 +7405,9 @@ void A_Boss2PogoSFX(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss2PogoSFX", actor))
 		return;
-#endif
 
 	if (!actor->target || !(actor->target->flags & MF_SHOOTABLE))
 	{
@@ -7593,10 +7448,8 @@ void A_Boss2PogoTarget(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Boss2PogoTarget", actor))
 		return;
-#endif
 
 	if (!actor->target || !(actor->target->flags & MF_SHOOTABLE) || (actor->target->player && actor->target->player->powers[pw_flashing])
 	|| P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) >= FixedMul(512*FRACUNIT, actor->scale))
@@ -7680,10 +7533,9 @@ void A_Boss2PogoTarget(mobj_t *actor)
 //
 void A_EggmanBox(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_EggmanBox", actor))
 		return;
-#endif
+
 	if (!actor->target || !actor->target->player)
 	{
 		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
@@ -7706,10 +7558,9 @@ void A_TurretFire(mobj_t *actor)
 	fixed_t dist;
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_TurretFire", actor))
 		return;
-#endif
 
 	if (locvar2)
 		dist = FixedMul(locvar2*FRACUNIT, actor->scale);
@@ -7745,10 +7596,9 @@ void A_SuperTurretFire(mobj_t *actor)
 	fixed_t dist;
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SuperTurretFire", actor))
 		return;
-#endif
 
 	if (locvar2)
 		dist = FixedMul(locvar2*FRACUNIT, actor->scale);
@@ -7782,10 +7632,9 @@ void A_SuperTurretFire(mobj_t *actor)
 void A_TurretStop(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_TurretStop", actor))
 		return;
-#endif
 
 	actor->flags2 &= ~MF2_FIRING;
 	actor->flags2 &= ~MF2_SUPERFIRE;
@@ -7803,10 +7652,8 @@ void A_TurretStop(mobj_t *actor)
 //
 void A_SparkFollow(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SparkFollow", actor))
 		return;
-#endif
 
 	if ((!actor->target || (actor->target->health <= 0))
 		|| (actor->target->player && !actor->target->player->powers[pw_super]))
@@ -7840,10 +7687,10 @@ void A_BuzzFly(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_BuzzFly", actor))
 		return;
-#endif
+
 	if (actor->flags2 & MF2_AMBUSH)
 		return;
 
@@ -7939,10 +7786,9 @@ void A_BuzzFly(mobj_t *actor)
 void A_GuardChase(mobj_t *actor)
 {
 	INT32 delta;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_GuardChase", actor))
 		return;
-#endif
 
 	if (actor->reactiontime)
 		actor->reactiontime--;
@@ -8045,10 +7891,9 @@ void A_EggShield(mobj_t *actor)
 	fixed_t newx, newy;
 	fixed_t movex, movey;
 	angle_t angle;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_EggShield", actor))
 		return;
-#endif
 
 	if (!actor->target || !actor->target->health)
 	{
@@ -8129,10 +7974,9 @@ void A_EggShield(mobj_t *actor)
 //
 void A_SetReactionTime(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SetReactionTime", actor))
 		return;
-#endif
+
 	if (var1)
 		actor->reactiontime = var2;
 	else
@@ -8152,10 +7996,8 @@ void A_Boss1Spikeballs(mobj_t *actor)
 	INT32 locvar2 = var2;
 	mobj_t *ball;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Boss1Spikeballs", actor))
 		return;
-#endif
 
 	ball = P_SpawnMobj(actor->x, actor->y, actor->z, MT_EGGMOBILE_BALL);
 	P_SetTarget(&ball->target, actor);
@@ -8176,10 +8018,9 @@ void A_Boss1Spikeballs(mobj_t *actor)
 //
 void A_Boss3TakeDamage(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Boss3TakeDamage", actor))
 		return;
-#endif
+
 	actor->movecount = var1;
 	actor->movefactor = -512*FRACUNIT;
 
@@ -8197,10 +8038,8 @@ void A_Boss3TakeDamage(mobj_t *actor)
 //
 void A_Boss3Path(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Boss3Path", actor))
 		return;
-#endif
 
 	if (actor->tracer && actor->tracer->health && actor->tracer->movecount)
 		actor->movecount |= 1;
@@ -8326,10 +8165,8 @@ void A_Boss3Path(mobj_t *actor)
 //
 void A_Boss3ShockThink(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Boss3ShockThink", actor))
 		return;
-#endif
 
 	if (actor->momx || actor->momy)
 		actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy) + ANGLE_90;
@@ -8380,10 +8217,9 @@ void A_LinedefExecute(mobj_t *actor)
 	INT32 tagnum;
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_LinedefExecute", actor))
 		return;
-#endif
 
 	tagnum = locvar1;
 	// state numbers option is no more, custom states cannot be guaranteed to stay the same number anymore, now that they can be defined by names instead
@@ -8408,10 +8244,9 @@ void A_LinedefExecute(mobj_t *actor)
 //
 void A_PlaySeeSound(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_PlaySeeSound", actor))
 		return;
-#endif
+
 	if (actor->info->seesound)
 		S_StartScreamSound(actor, actor->info->seesound);
 }
@@ -8425,10 +8260,9 @@ void A_PlaySeeSound(mobj_t *actor)
 //
 void A_PlayAttackSound(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_PlayAttackSound", actor))
 		return;
-#endif
+
 	if (actor->info->attacksound)
 		S_StartAttackSound(actor, actor->info->attacksound);
 }
@@ -8442,10 +8276,9 @@ void A_PlayAttackSound(mobj_t *actor)
 //
 void A_PlayActiveSound(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_PlayActiveSound", actor))
 		return;
-#endif
+
 	if (actor->info->activesound)
 		S_StartSound(actor, actor->info->activesound);
 }
@@ -8461,10 +8294,9 @@ void A_SmokeTrailer(mobj_t *actor)
 {
 	mobj_t *th;
 	INT32 locvar1 = var1;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SmokeTrailer", actor))
 		return;
-#endif
 
 	if (leveltime % 4)
 		return;
@@ -8503,10 +8335,9 @@ void A_SpawnObjectAbsolute(mobj_t *actor)
 	mobj_t *mo;
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SpawnObjectAbsolute", actor))
 		return;
-#endif
 
 	x = (INT16)(locvar1>>16);
 	y = (INT16)(locvar1&65535);
@@ -8540,10 +8371,9 @@ void A_SpawnObjectRelative(mobj_t *actor)
 	mobj_t *mo;
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SpawnObjectRelative", actor))
 		return;
-#endif
 
 	CONS_Debug(DBG_GAMELOGIC, "A_SpawnObjectRelative called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
 
@@ -8585,10 +8415,9 @@ void A_ChangeAngleRelative(mobj_t *actor)
 	const fixed_t amax = locvar2*FRACUNIT;
 	//const angle_t amin = FixedAngle(locvar1*FRACUNIT);
 	//const angle_t amax = FixedAngle(locvar2*FRACUNIT);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ChangeAngleRelative", actor))
 		return;
-#endif
 
 #ifdef PARANOIA
 	if (amin > amax)
@@ -8619,10 +8448,9 @@ void A_ChangeAngleAbsolute(mobj_t *actor)
 	const fixed_t amax = locvar2*FRACUNIT;
 	//const angle_t amin = FixedAngle(locvar1*FRACUNIT);
 	//const angle_t amax = FixedAngle(locvar2*FRACUNIT);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ChangeAngleAbsolute", actor))
 		return;
-#endif
 
 #ifdef PARANOIA
 	if (amin > amax)
@@ -8650,10 +8478,8 @@ void A_RollAngle(mobj_t *actor)
 	INT32 locvar2 = var2;
 	const angle_t angle = FixedAngle(locvar1*FRACUNIT);
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_RollAngle", actor))
 		return;
-#endif
 
 	// relative (default)
 	if (!locvar2)
@@ -8676,10 +8502,9 @@ void A_ChangeRollAngleRelative(mobj_t *actor)
 	INT32 locvar2 = var2;
 	const fixed_t amin = locvar1*FRACUNIT;
 	const fixed_t amax = locvar2*FRACUNIT;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ChangeRollAngleRelative", actor))
 		return;
-#endif
 
 #ifdef PARANOIA
 	if (amin > amax)
@@ -8702,10 +8527,9 @@ void A_ChangeRollAngleAbsolute(mobj_t *actor)
 	INT32 locvar2 = var2;
 	const fixed_t amin = locvar1*FRACUNIT;
 	const fixed_t amax = locvar2*FRACUNIT;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ChangeRollAngleAbsolute", actor))
 		return;
-#endif
 
 #ifdef PARANOIA
 	if (amin > amax)
@@ -8728,10 +8552,9 @@ void A_PlaySound(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_PlaySound", actor))
 		return;
-#endif
 
 	if (leveltime < 2 && (locvar2 >> 16))
 		return;
@@ -8754,10 +8577,9 @@ void A_FindTarget(mobj_t *actor)
 	thinker_t *th;
 	mobj_t *mo2;
 	fixed_t dist1 = 0, dist2 = 0;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FindTarget", actor))
 		return;
-#endif
 
 	CONS_Debug(DBG_GAMELOGIC, "A_FindTarget called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
 
@@ -8819,10 +8641,9 @@ void A_FindTracer(mobj_t *actor)
 	thinker_t *th;
 	mobj_t *mo2;
 	fixed_t dist1 = 0, dist2 = 0;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FindTracer", actor))
 		return;
-#endif
 
 	CONS_Debug(DBG_GAMELOGIC, "A_FindTracer called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
 
@@ -8880,10 +8701,9 @@ void A_SetTics(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SetTics", actor))
 		return;
-#endif
 
 	if (locvar1)
 		actor->tics = locvar1;
@@ -8902,10 +8722,9 @@ void A_SetRandomTics(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SetRandomTics", actor))
 		return;
-#endif
 
 	actor->tics = P_RandomRange(locvar1, locvar2);
 }
@@ -8921,10 +8740,9 @@ void A_ChangeColorRelative(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ChangeColorRelative", actor))
 		return;
-#endif
 
 	if (locvar1)
 	{
@@ -8947,10 +8765,9 @@ void A_ChangeColorAbsolute(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ChangeColorAbsolute", actor))
 		return;
-#endif
 
 	if (locvar1)
 	{
@@ -8972,10 +8789,9 @@ void A_MoveRelative(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_MoveRelative", actor))
 		return;
-#endif
 
 	P_Thrust(actor, actor->angle+FixedAngle(locvar1*FRACUNIT), FixedMul(locvar2*FRACUNIT, actor->scale));
 }
@@ -8991,10 +8807,9 @@ void A_MoveAbsolute(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_MoveAbsolute", actor))
 		return;
-#endif
 
 	P_InstaThrust(actor, FixedAngle(locvar1*FRACUNIT), FixedMul(locvar2*FRACUNIT, actor->scale));
 }
@@ -9010,10 +8825,9 @@ void A_Thrust(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Thrust", actor))
 		return;
-#endif
 
 	if (!locvar1)
 		CONS_Debug(DBG_GAMELOGIC, "A_Thrust: Var1 not specified!\n");
@@ -9037,10 +8851,9 @@ void A_ZThrust(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ZThrust", actor))
 		return;
-#endif
 
 	if (!locvar1)
 		CONS_Debug(DBG_GAMELOGIC, "A_ZThrust: Var1 not specified!\n");
@@ -9072,10 +8885,9 @@ void A_SetTargetsTarget(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	mobj_t *oldtarg = NULL, *newtarg = NULL;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SetTargetsTarget", actor))
 		return;
-#endif
 
 	// actor's target
 	if (locvar1) // or tracer
@@ -9117,10 +8929,9 @@ void A_SetObjectFlags(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	boolean unlinkthings = false;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SetObjectFlags", actor))
 		return;
-#endif
 
 	if (locvar2 == 2)
 		locvar1 = actor->flags | locvar1;
@@ -9159,10 +8970,9 @@ void A_SetObjectFlags2(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SetObjectFlags2", actor))
 		return;
-#endif
 
 	if (locvar2 == 2)
 		actor->flags2 |= locvar1;
@@ -9187,10 +8997,9 @@ void A_BossJetFume(mobj_t *actor)
 {
 	mobj_t *filler;
 	INT32 locvar1 = var1;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_BossJetFume", actor))
 		return;
-#endif
 
 	if (locvar1 == 0) // Boss1 jet fumes
 	{
@@ -9323,10 +9132,9 @@ void A_RandomState(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_RandomState", actor))
 		return;
-#endif
 
 	P_SetMobjState(actor, P_RandomChance(FRACUNIT/2) ? locvar1 : locvar2);
 }
@@ -9343,10 +9151,8 @@ void A_RandomStateRange(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_RandomStateRange", actor))
 		return;
-#endif
 
 	P_SetMobjState(actor, P_RandomRange(locvar1, locvar2));
 }
@@ -9362,27 +9168,22 @@ void A_DualAction(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_DualAction", actor))
 		return;
-#endif
 
 	CONS_Debug(DBG_GAMELOGIC, "A_DualAction called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
 
 	var1 = states[locvar1].var1;
 	var2 = states[locvar1].var2;
-#ifdef HAVE_BLUA
 	astate = &states[locvar1];
-#endif
 
 	CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling First Action (state %d)...\n", locvar1);
 	states[locvar1].action.acp1(actor);
 
 	var1 = states[locvar2].var1;
 	var2 = states[locvar2].var2;
-#ifdef HAVE_BLUA
 	astate = &states[locvar2];
-#endif
 
 	CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling Second Action (state %d)...\n", locvar2);
 	states[locvar2].action.acp1(actor);
@@ -9400,10 +9201,9 @@ void A_RemoteAction(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	mobj_t *originaltarget = actor->target; // Hold on to the target for later.
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_RemoteAction", actor))
 		return;
-#endif
 
 	// If >=0, find the closest target.
 	if (locvar1 >= 0)
@@ -9465,9 +9265,7 @@ void A_RemoteAction(mobj_t *actor)
 		// Steal the var1 and var2 from "locvar2"
 		var1 = states[locvar2].var1;
 		var2 = states[locvar2].var2;
-#ifdef HAVE_BLUA
 		astate = &states[locvar2];
-#endif
 
 		CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Calling action on %p\n"
 				"var1 is %d\nvar2 is %d\n", actor->target, var1, var2);
@@ -9486,10 +9284,9 @@ void A_RemoteAction(mobj_t *actor)
 //
 void A_ToggleFlameJet(mobj_t* actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_ToggleFlameJet", actor))
 		return;
-#endif
+
 	// threshold - off delay
 	// movecount - on timer
 
@@ -9533,10 +9330,9 @@ void A_OrbitNights(mobj_t* actor)
 	boolean ishelper = (var2 & 0x10000);
 	boolean donotrescale = (var2 & 0x40000);
 	INT32 xfactor = 32, yfactor = 32, zfactor = 20;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_OrbitNights", actor))
 		return;
-#endif
 
 	if (actor->flags & MF_GRENADEBOUNCE)
 	{
@@ -9607,10 +9403,10 @@ void A_GhostMe(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	mobj_t *ghost;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_GhostMe", actor))
 		return;
-#endif
+
 	ghost = P_SpawnGhostMobj(actor);
 	if (ghost && locvar1 > 0)
 		ghost->fuse = locvar1;
@@ -9630,10 +9426,9 @@ void A_SetObjectState(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	mobj_t *target;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SetObjectState", actor))
 		return;
-#endif
 
 	if ((!locvar2 && !actor->target) || (locvar2 && !actor->tracer))
 	{
@@ -9676,10 +9471,8 @@ void A_SetObjectTypeState(mobj_t *actor)
 	mobj_t *mo2;
 	fixed_t dist = 0;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SetObjectTypeState", actor))
 		return;
-#endif
 
 	for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
 	{
@@ -9719,10 +9512,9 @@ void A_KnockBack(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	mobj_t *target;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_KnockBack", actor))
 		return;
-#endif
 
 	if (!locvar1)
 		target = actor->target;
@@ -9755,10 +9547,9 @@ void A_PushAway(mobj_t *actor)
 	INT32 locvar2 = var2;
 	mobj_t *target; // target
 	angle_t an; // actor to target angle
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_PushAway", actor))
 		return;
-#endif
 
 	if ((!(locvar2 >> 16) && !actor->target) || ((locvar2 >> 16) && !actor->tracer))
 		return;
@@ -9790,10 +9581,9 @@ void A_RingDrain(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	player_t *player;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_RingDrain", actor))
 		return;
-#endif
 
 	if (!actor->target || !actor->target->player)
 	{
@@ -9823,10 +9613,9 @@ void A_SplitShot(mobj_t *actor)
 	const UINT16 loc2up = (UINT16)(locvar2 >> 16);
 	const fixed_t offs = (fixed_t)(locvar1*FRACUNIT);
 	const fixed_t hoffs = (fixed_t)(loc2up*FRACUNIT);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SplitShot", actor))
 		return;
-#endif
 
 	A_FaceTarget(actor);
 	{
@@ -9858,10 +9647,10 @@ void A_MissileSplit(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_MissileSplit", actor))
 		return;
-#endif
+
 	if (actor->eflags & MFE_VERTICALFLIP)
 		P_SpawnAlteredDirectionMissile(actor, locvar1, actor->x, actor->y, actor->z+actor->height, locvar2);
 	else
@@ -9886,10 +9675,9 @@ void A_MultiShot(mobj_t *actor)
 	const UINT16 loc1up = (UINT16)(locvar1 >> 16);
 	INT32 count = 0;
 	fixed_t ad;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_MultiShot", actor))
 		return;
-#endif
 
 	if (actor->target)
 		A_FaceTarget(actor);
@@ -9948,10 +9736,9 @@ void A_InstaLoop(mobj_t *actor)
 	const angle_t fa = FixedAngleC(loc1lw*FRACUNIT*360, loc1up*FRACUNIT)>>ANGLETOFINESHIFT;
 	const fixed_t ac = FINECOSINE(fa);
 	const fixed_t as = FINESINE(fa);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_InstaLoop", actor))
 		return;
-#endif
 
 	P_InstaThrust(actor, actor->angle, FixedMul(ac, FixedMul(force, actor->scale)));
 	P_SetObjectMomZ(actor, FixedMul(as, force), false);
@@ -9982,10 +9769,9 @@ void A_Custom3DRotate(mobj_t *actor)
 	const fixed_t hOff = FixedMul(loc1up*FRACUNIT, actor->scale);
 	const fixed_t hspeed = FixedMul(loc2up*FRACUNIT/10, actor->scale);
 	const fixed_t vspeed = FixedMul(loc2lw*FRACUNIT/10, actor->scale);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Custom3DRotate", actor))
 		return;
-#endif
 
 	if (actor->target->health == 0)
 	{
@@ -10042,10 +9828,9 @@ void A_SearchForPlayers(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SearchForPlayers", actor))
 		return;
-#endif
 
 	if (!actor->target || !(actor->target->flags & MF_SHOOTABLE))
 	{
@@ -10076,10 +9861,9 @@ void A_CheckRandom(mobj_t *actor)
 	INT32 locvar2 = var2;
 	fixed_t chance = FRACUNIT;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_CheckRandom", actor))
 		return;
-#endif
+
 	if ((locvar1 & 0xFFFF) == 0)
 		return;
 
@@ -10103,10 +9887,9 @@ void A_CheckTargetRings(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CheckTargetRings", actor))
 		return;
-#endif
 
 	if (!(actor->target) || !(actor->target->player))
 	   return;
@@ -10127,10 +9910,9 @@ void A_CheckRings(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	INT32 i, cntr = 0;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CheckRings", actor))
 		return;
-#endif
 
 	for (i = 0; i < MAXPLAYERS; i++)
 		cntr += players[i].rings;
@@ -10152,10 +9934,9 @@ void A_CheckTotalRings(mobj_t *actor)
 	INT32 locvar2 = var2;
 
 	INT32 i, cntr = 0;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CheckTotalRings", actor))
 		return;
-#endif
 
 	for (i = 0; i < MAXPLAYERS; i++)
 		cntr += players[i].totalring;
@@ -10175,10 +9956,9 @@ void A_CheckHealth(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CheckHealth", actor))
 		return;
-#endif
 
 	if (actor->health <= locvar1)
 		P_SetMobjState(actor, locvar2);
@@ -10198,10 +9978,9 @@ void A_CheckRange(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	fixed_t dist;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CheckRange", actor))
 		return;
-#endif
 
 	if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer))
 		return;
@@ -10229,10 +10008,9 @@ void A_CheckHeight(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	fixed_t height;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CheckHeight", actor))
 		return;
-#endif
 
 	if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer))
 		return;
@@ -10262,10 +10040,9 @@ void A_CheckTrueRange(mobj_t *actor)
 	fixed_t height; // vertical range
 	fixed_t dist; // horizontal range
 	fixed_t l; // true range
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CheckTrueRange", actor))
 		return;
-#endif
 
 	if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer))
 		return;
@@ -10314,10 +10091,9 @@ void A_CheckThingCount(mobj_t *actor)
 	thinker_t *th;
 	mobj_t *mo2;
 	fixed_t dist = 0;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CheckThingCount", actor))
 		return;
-#endif
 
 	for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
 	{
@@ -10361,10 +10137,8 @@ void A_CheckAmbush(mobj_t *actor)
 	angle_t atp; // actor to target angle
 	angle_t an; // angle between at and atp
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_CheckAmbush", actor))
 		return;
-#endif
 
 	if ((!locvar1 && !actor->target) || (locvar1 && !actor->tracer))
 		return;
@@ -10400,10 +10174,9 @@ void A_CheckCustomValue(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CheckCustomValue", actor))
 		return;
-#endif
 
 	if (actor->cusval >= locvar1)
 		P_SetMobjState(actor, locvar2);
@@ -10420,10 +10193,9 @@ void A_CheckCusValMemo(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CheckCusValMemo", actor))
 		return;
-#endif
 
 	if (actor->cvmem >= locvar1)
 		P_SetMobjState(actor, locvar2);
@@ -10446,10 +10218,9 @@ void A_SetCustomValue(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SetCustomValue", actor))
 		return;
-#endif
 
 	if (cv_debug)
 		CONS_Printf("Init custom value is %d\n", actor->cusval);
@@ -10497,10 +10268,9 @@ void A_UseCusValMemo(mobj_t *actor)
 
 	INT32 temp = actor->cusval; // value being manipulated
 	INT32 tempM = actor->cvmem; // value used to manipulate temp with
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_UseCusValMemo", actor))
 		return;
-#endif
 
 	if (locvar1 == 1) // cvmem being changed using cusval
 	{
@@ -10561,10 +10331,9 @@ void A_RelayCustomValue(mobj_t *actor)
 
 	INT32 temp; // reference value - var1 lower 16 bits changes this
 	INT32 tempT; // target's value - changed to tracer if var1 upper 16 bits set, then modified to become final value
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_RelayCustomValue", actor))
 		return;
-#endif
 
 	if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer))
 		return;
@@ -10621,10 +10390,9 @@ void A_CusValAction(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CusValAction", actor))
 		return;
-#endif
 
 	if (locvar2 == 5)
 	{
@@ -10657,9 +10425,7 @@ void A_CusValAction(mobj_t *actor)
 		var2 = states[locvar1].var2;
 	}
 
-#ifdef HAVE_BLUA
 	astate = &states[locvar1];
-#endif
 	states[locvar1].action.acp1(actor);
 }
 
@@ -10675,10 +10441,9 @@ void A_CusValAction(mobj_t *actor)
 void A_ForceStop(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ForceStop", actor))
 		return;
-#endif
 
 	actor->momx = actor->momy = 0;
 	if (locvar1 == 0)
@@ -10696,12 +10461,8 @@ void A_ForceWin(mobj_t *actor)
 {
 	INT32 i;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_ForceWin", actor))
 		return;
-#else
-	(void)actor;
-#endif
 
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
@@ -10733,10 +10494,9 @@ void A_ForceWin(mobj_t *actor)
 void A_SpikeRetract(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SpikeRetract", actor))
 		return;
-#endif
 
 	if (actor->flags & MF_NOBLOCKMAP)
 		return;
@@ -10818,10 +10578,9 @@ void A_Repeat(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Repeat", actor))
 		return;
-#endif
 
 	if (locvar1 && (!actor->extravalue2 || actor->extravalue2 > locvar1))
 		actor->extravalue2 = locvar1;
@@ -10844,10 +10603,9 @@ void A_SetScale(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	mobj_t *target;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SetScale", actor))
 		return;
-#endif
 
 	if (locvar1 <= 0)
 	{
@@ -10888,10 +10646,10 @@ void A_RemoteDamage(mobj_t *actor)
 	INT32 locvar2 = var2;
 	mobj_t *target; // we MUST have a target
 	mobj_t *source = NULL; // on the other hand we don't necessarily need a source
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_RemoteDamage", actor))
 		return;
-#endif
+
 	if (locvar1 == 1)
 		target = actor->target;
 	else if (locvar1 == 2)
@@ -10941,10 +10699,9 @@ void A_HomingChase(mobj_t *actor)
 	mobj_t *dest;
 	fixed_t dist;
 	fixed_t speedmul;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_HomingChase", actor))
 		return;
-#endif
 
 	if (locvar2 == 1)
 		dest = actor->tracer;
@@ -10995,10 +10752,9 @@ void A_TrapShot(mobj_t *actor)
 	INT16 vertoff = (INT16)(locvar2 >> 16);
 	fixed_t x, y, z;
 	fixed_t speed;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_TrapShot", actor))
 		return;
-#endif
 
 	x = actor->x + P_ReturnThrustX(actor, actor->angle, FixedMul(frontoff*FRACUNIT, actor->scale));
 	y = actor->y + P_ReturnThrustY(actor, actor->angle, FixedMul(frontoff*FRACUNIT, actor->scale));
@@ -11062,10 +10818,8 @@ void A_VileTarget(mobj_t *actor)
 	mobjtype_t fogtype;
 	INT32 i;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_VileTarget", actor))
 		return;
-#endif
 
 	if (!actor->target)
 		return;
@@ -11151,10 +10905,8 @@ void A_VileAttack(mobj_t *actor)
 	mobj_t *fire;
 	INT32 i;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_VileAttack", actor))
 		return;
-#endif
 
 	if (!actor->target)
 		return;
@@ -11265,10 +11017,8 @@ void A_VileFire(mobj_t *actor)
 	INT32 locvar2 = var2;
 	mobj_t *dest;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_VileFire", actor))
 		return;
-#endif
 
 	dest = actor->tracer;
 	if (!dest)
@@ -11353,10 +11103,8 @@ void A_BrakChase(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_BrakChase", actor))
 		return;
-#endif
 
 	// Set new tics NOW, in case the state changes while we're doing this and we try applying this to the painstate or something silly
 	if (actor->tics > 1 && locvar1 < actor->tics) // Not much point, otherwise
@@ -11475,10 +11223,9 @@ void A_BrakFireShot(mobj_t *actor)
 	fixed_t x, y, z;
 	INT32 locvar1 = var1;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_BrakFireShot", actor))
 		return;
-#endif
+
 	if (!actor->target)
 		return;
 
@@ -11539,10 +11286,8 @@ void A_BrakLobShot(mobj_t *actor)
 	INT32 locvar2 = var2 & 0x0000FFFF;
 	INT32 aimDirect = var2 & 0xFFFF0000;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_BrakLobShot", actor))
 		return;
-#endif
 
 	if (!actor->target)
 		return; // Don't even bother if we've got nothing to aim at.
@@ -11647,10 +11392,8 @@ void A_NapalmScatter(mobj_t *actor)
 	INT32 i; // for-loop cursor
 	mobj_t *mo; // each and every spawned napalm burst
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_NapalmScatter", actor))
 		return;
-#endif
 
 	// Some quick sanity-checking
 	if (typeOfShot >= NUMMOBJTYPES) // I'd add a <0 check, too, but 0x0000FFFF isn't negative in this case
@@ -11701,10 +11444,8 @@ void A_SpawnFreshCopy(mobj_t *actor)
 {
 	mobj_t *newObject;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SpawnFreshCopy", actor))
 		return;
-#endif
 
 	newObject = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->type);
 	newObject->flags2 = actor->flags2 & MF2_AMBUSH;
@@ -11778,10 +11519,9 @@ void A_FlickySpawn(mobj_t *actor)
 	INT32 locvar2 = var2;
 	INT32 test = (var1 >> 16);
 	SINT8 moveforward = 0;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FlickySpawn", actor))
 		return;
-#endif
 
 	if (test & 1)
 		A_Scream(actor); // A shortcut for the truly lazy.
@@ -11847,10 +11587,9 @@ void A_FlickyCenter(mobj_t *actor)
 	UINT16 flickytype = (locvar1 & 0xFFFF);
 	UINT8 flickycolor = ((locvar1 >> 16) & 0xFF);
 	UINT8 flickyflags = ((locvar1 >> 20) & 0xF);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FlickyCenter", actor))
 		return;
-#endif
 
 	if (!actor->tracer)
 	{
@@ -11969,10 +11708,8 @@ void A_FlickyAim(mobj_t *actor)
 	INT32 locvar2 = var2;
 	boolean flickyhitwall = false;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FlickyAim", actor))
 		return;
-#endif
 
 	if ((actor->momx == actor->momy && actor->momy == 0)
 		|| (actor->target && P_IsFlickyCenter(actor->target->type)
@@ -12070,10 +11807,10 @@ void A_FlickyFly(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FlickyFly", actor))
 		return;
-#endif
+
 	P_InternalFlickyFly(actor, locvar1, locvar2,
 	FINECOSINE((((actor->fuse % 36) * ANG10) >> ANGLETOFINESHIFT) & FINEMASK)
 	);
@@ -12090,10 +11827,10 @@ void A_FlickySoar(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FlickySoar", actor))
 		return;
-#endif
+
 	P_InternalFlickyFly(actor, locvar1, locvar2,
 	2*(FRACUNIT/2 - abs(FINECOSINE((((actor->fuse % 144) * 5*ANG1/2) >> ANGLETOFINESHIFT) & FINEMASK)))
 	);
@@ -12114,10 +11851,10 @@ void A_FlickyCoast(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FlickyCoast", actor))
 		return;
-#endif
+
 	if (actor->eflags & MFE_UNDERWATER)
 	{
 		actor->momx = (11*actor->momx)/12;
@@ -12161,10 +11898,10 @@ void A_FlickyHop(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FlickyHop", actor))
 		return;
-#endif
+
 	P_InternalFlickyHop(actor, locvar1, locvar2, actor->angle);
 }
 
@@ -12180,10 +11917,10 @@ void A_FlickyFlounder(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	angle_t hopangle;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FlickyFlounder", actor))
 		return;
-#endif
+
 	locvar1 *= (P_RandomKey(2) + 1);
 	locvar2 *= (P_RandomKey(2) + 1);
 	hopangle = (actor->angle + (P_RandomKey(9) - 4)*ANG2);
@@ -12202,10 +11939,10 @@ void A_FlickyCheck(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FlickyCheck", actor))
 		return;
-#endif
+
 	if (actor->target
 		&& P_IsFlickyCenter(actor->target->type)
 		&& (actor->target->flags & MF_GRENADEBOUNCE))
@@ -12239,10 +11976,10 @@ void A_FlickyHeightCheck(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FlickyHeightCheck", actor))
 		return;
-#endif
+
 	if (actor->target
 		&& P_IsFlickyCenter(actor->target->type)
 		&& (actor->target->flags & MF_GRENADEBOUNCE))
@@ -12274,10 +12011,10 @@ void A_FlickyFlutter(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_FlickyFlutter", actor))
 		return;
-#endif
+
 	var1 = locvar1;
 	var2 = locvar2;
 	A_FlickyCheck(actor);
@@ -12305,13 +12042,9 @@ void A_FlameParticle(mobj_t *actor)
 	mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance);
 	fixed_t rad, hei;
 	mobj_t *particle;
-	//INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FlameParticle", actor))
 		return;
-#endif
 
 	if (!type)
 		return;
@@ -12337,12 +12070,9 @@ void A_FadeOverlay(mobj_t *actor)
 {
 	mobj_t *fade;
 	INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FadeOverlay", actor))
 		return;
-#endif
 
 	fade = P_SpawnGhostMobj(actor);
 	fade->frame = actor->frame;
@@ -12382,10 +12112,8 @@ void A_Boss5Jump(mobj_t *actor)
 	// INT32 locvar1 = var1;
 	// INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Boss5Jump", actor))
 		return;
-#endif
 
 	if (!actor->tracer)
 		return; // Don't even bother if we've got nothing to aim at.
@@ -12461,10 +12189,8 @@ void A_LightBeamReset(mobj_t *actor)
 	// INT32 locvar1 = var1;
 	// INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_LightBeamReset", actor))
 		return;
-#endif
 
 	actor->destscale = FRACUNIT + P_SignedRandom()*FRACUNIT/256;
 	P_SetScale(actor, actor->destscale);
@@ -12493,10 +12219,8 @@ void A_MineExplode(mobj_t *actor)
 	// INT32 locvar1 = var1;
 	// INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_MineExplode", actor))
 		return;
-#endif
 
 	A_Scream(actor);
 	actor->flags = MF_NOGRAVITY|MF_NOCLIP;
@@ -12548,10 +12272,8 @@ void A_MineRange(mobj_t *actor)
 	INT32 locvar1 = var1;
 	// INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_MineRange", actor))
 		return;
-#endif
 
 	if (!actor->target)
 		return;
@@ -12576,10 +12298,8 @@ void A_ConnectToGround(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_ConnectToGround", actor))
 		return;
-#endif
 
 	if (actor->subsector->sector->ffloors)
 		P_AdjustMobjFloorZ_FFloors(actor, actor->subsector->sector, 2);
@@ -12636,10 +12356,10 @@ void A_SpawnParticleRelative(mobj_t *actor)
 	mobj_t *mo;
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_SpawnParticleRelative", actor))
 		return;
-#endif
+
 
 	CONS_Debug(DBG_GAMELOGIC, "A_SpawnParticleRelative called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
 
@@ -12674,10 +12394,9 @@ void A_MultiShotDist(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_MultiShotDist", actor))
 		return;
-#endif
 
 	{
 		UINT8 i;
@@ -12714,10 +12433,9 @@ void A_WhoCaresIfYourSonIsABee(mobj_t *actor)
 	fixed_t foffsetx;
 	fixed_t foffsety;
 	mobj_t *son;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_WhoCaresIfYourSonIsABee", actor))
 		return;
-#endif
 
 	A_FaceTarget(actor);
 
@@ -12749,11 +12467,9 @@ void A_WhoCaresIfYourSonIsABee(mobj_t *actor)
 void A_ParentTriesToSleep(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ParentTriesToSleep", actor))
 		return;
-#endif
 
 	if (actor->extravalue1)
 	{
@@ -12780,12 +12496,8 @@ void A_ParentTriesToSleep(mobj_t *actor)
 //
 void A_CryingToMomma(mobj_t *actor)
 {
-	//INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_CryingToMomma", actor))
 		return;
-#endif
 
 	if (actor->tracer)
 		actor->tracer->extravalue1++;
@@ -12813,10 +12525,9 @@ void A_CheckFlags2(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_CheckFlags2", actor))
 		return;
-#endif
 
 	if (actor->flags2 & locvar1)
 		P_SetMobjState(actor, (statenum_t)locvar2);
@@ -12832,14 +12543,12 @@ void A_CheckFlags2(mobj_t *actor)
 void A_Boss5FindWaypoint(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
 	boolean avoidcenter;
 	UINT32 i;
 	UINT8 extrainfo = (actor->spawnpoint ? actor->spawnpoint->extrainfo : 0);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss5FindWaypoint", actor))
 		return;
-#endif
 
 	avoidcenter = !actor->tracer || (actor->health == actor->info->damage+1);
 
@@ -13054,10 +12763,9 @@ void A_DoNPCSkid(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 	fixed_t x, y, z;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_DoNPCSkid", actor))
 		return;
-#endif
 
 	x = actor->x;
 	y = actor->y;
@@ -13111,10 +12819,9 @@ void A_DoNPCPain(mobj_t *actor)
 	INT32 locvar2 = var2;
 	fixed_t vspeed = 0;
 	fixed_t hspeed = FixedMul(4*FRACUNIT, actor->scale);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_DoNPCPain", actor))
 		return;
-#endif
 
 	actor->flags &= ~(MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT);
 
@@ -13160,11 +12867,9 @@ void A_DoNPCPain(mobj_t *actor)
 void A_PrepareRepeat(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_PrepareRepeat", actor))
 		return;
-#endif
 
 	actor->extravalue2 = locvar1;
 }
@@ -13183,10 +12888,9 @@ void A_Boss5ExtraRepeat(mobj_t *actor)
 	INT32 calc;
 	INT32 locspawn;
 	INT32 lochealth;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss5ExtraRepeat", actor))
 		return;
-#endif
 
 	if (actor->extravalue2 > 0 && !(actor->flags2 & MF2_FRET))
 		return;
@@ -13217,10 +12921,9 @@ void A_Boss5ExtraRepeat(mobj_t *actor)
 //
 void A_Boss5Calm(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_Boss5Calm", actor))
 		return;
-#endif
+
 	actor->flags |= MF_SHOOTABLE;
 	actor->flags2 &= ~MF2_FRET;
 }
@@ -13236,10 +12939,9 @@ void A_Boss5CheckOnGround(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss5CheckOnGround", actor))
 		return;
-#endif
 
 	if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)
 	|| (actor->eflags & MFE_VERTICALFLIP && actor->z + actor->height >= actor->ceilingz))
@@ -13268,10 +12970,9 @@ void A_Boss5CheckFalling(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss5CheckFalling", actor))
 		return;
-#endif
 
 	if (actor->health && actor->extravalue2 > 1)
 	{
@@ -13298,10 +12999,9 @@ void A_Boss5PinchShot(mobj_t *actor)
 	INT32 locvar2 = var2;
 	fixed_t zoffset;
 	mobj_t *missile;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss5PinchShot", actor))
 		return;
-#endif
 
 	if (actor->health > actor->info->damage)
 		return;
@@ -13334,10 +13034,9 @@ void A_Boss5MakeItRain(mobj_t *actor)
 	INT32 locvar2 = var2;
 	INT32 offset = (48 + locvar2)<<16; // upper 16 bits, not fixed_t!
 	INT32 i;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss5MakeItRain", actor))
 		return;
-#endif
 
 	actor->flags2 |= MF2_STRONGBOX;
 
@@ -13371,10 +13070,9 @@ void A_Boss5MakeJunk(mobj_t *actor)
 	mobj_t *broked = NULL;
 	angle_t ang;
 	INT32 i = ((locvar2 & 1) ? 8 : 1);
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss5MakeJunk", actor))
 		return;
-#endif
 
 	if (locvar1 < 0 && (actor->flags2 & MF2_SLIDEPUSH)) // this entire action is a hack, don't judge me
 	{
@@ -13462,11 +13160,9 @@ void A_Boss5MakeJunk(mobj_t *actor)
 void A_LookForBetter(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_LookForBetter", actor))
 		return;
-#endif
 
 	P_LookForPlayers(actor, (locvar1 & 65535), false, FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale));
 	A_FaceTarget(actor);
@@ -13524,11 +13220,9 @@ static void P_DustRing(mobjtype_t mobjtype, UINT32 div, fixed_t x, fixed_t y, fi
 void A_Boss5BombExplode(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_Boss5BombExplode", actor))
 		return;
-#endif
 
 	// The original Lua script did not use |= to add flags but just set these flags exactly apparently?
 	// (I may modify this later)
@@ -13631,10 +13325,8 @@ void A_DustDevilThink(mobj_t *actor)
 	INT32 bx, by, xl, xh, yl, yh;
 	fixed_t radius = actor->radius;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_DustDevilThink", actor))
 		return;
-#endif
 
 	//Chained thinker for the spiralling dust column.
 	while (layer && !P_MobjWasRemoved(layer)) {
@@ -13771,15 +13463,12 @@ static boolean PIT_TNTExplode(mobj_t *nearby)
 void A_TNTExplode(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
 	INT32 x, y;
 	INT32 xl, xh, yl, yh;
 	static mappoint_t epicenter = {0,0,0};
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_TNTExplode", actor))
 		return;
-#endif
 
 	if (actor->tracer)
 	{
@@ -13843,12 +13532,9 @@ void A_TNTExplode(mobj_t *actor)
 void A_DebrisRandom(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_DebrisRandom", actor))
 		return;
-#endif
 
 	actor->frame |= P_RandomRange(0, locvar1);
 	var1 = 0;
@@ -13888,10 +13574,8 @@ void A_TrainCameo(mobj_t *actor)
 	fixed_t span = locvar1*FRACUNIT;
 	fixed_t len = locvar2*FRACUNIT;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_TrainCameo", actor))
 		return;
-#endif
 
 	//Spawn sides.
 	P_TrainSeg(actor, x, y + span, z, ang, spr, 0);
@@ -13928,10 +13612,8 @@ void A_TrainCameo2(mobj_t *actor)
 	fixed_t span = locvar1*FRACUNIT;
 	fixed_t len = locvar2*FRACUNIT;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_TrainCameo2", actor))
 		return;
-#endif
 
 	//Spawn sides.
 	P_TrainSeg(actor, x, y + span, z, ang, spr, 0);
@@ -13956,10 +13638,8 @@ void A_CanarivoreGas(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_CanarivoreGas", actor))
 		return;
-#endif
 
 	P_DustRing(locvar1, 4, actor->x, actor->y, actor->z + actor->height / 5, 18, 0, FRACUNIT/10, actor->scale);
 	P_DustRing(locvar1, 6, actor->x, actor->y, actor->z + actor->height / 5, 28, FRACUNIT, FRACUNIT/10, actor->scale);
@@ -13979,10 +13659,8 @@ void A_KillSegments(mobj_t *actor)
 	mobj_t *seg = actor->tracer;
 	INT32 fuse = locvar1 ? locvar1 : TICRATE/2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_KillSegments", actor))
 		return;
-#endif
 
 	while (seg)
 	{
@@ -14064,10 +13742,8 @@ void A_SnapperSpawn(mobj_t *actor)
 	INT32 i;
 	mobj_t *seg;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SnapperSpawn", actor))
 		return;
-#endif
 
 	// It spawns 1 head.
 	seg = P_SpawnMobjFromMobj(actor, 0, 0, 0, headtype);
@@ -14116,10 +13792,8 @@ void A_SnapperThinker(mobj_t *actor)
 	fixed_t dist;
 	boolean chasing;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SnapperThinker", actor))
 		return;
-#endif
 
 	// We make a check just in case there's no spawnpoint.
 	if (actor->spawnpoint)
@@ -14239,10 +13913,8 @@ void A_SaloonDoorSpawn(mobj_t *actor)
 	mobj_t *door;
 	mobjflag2_t ambush = (actor->flags2 & MF2_AMBUSH);
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SaloonDoorSpawn", actor))
 		return;
-#endif
 
 	if (!locvar1)
 		return;
@@ -14278,10 +13950,8 @@ void A_MinecartSparkThink(mobj_t *actor)
 	fixed_t dz, dm;
 	UINT8 i;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_MinecartSparkThink", actor))
 		return;
-#endif
 
 	if (actor->momz == 0 && P_IsObjectOnGround(actor))
 		actor->momz = P_RandomRange(2, 4)*FRACUNIT;
@@ -14313,10 +13983,9 @@ void A_ModuloToState(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-#ifdef HAVE_BLUA
+
 	if (LUA_CallAction("A_ModuloToState", actor))
 		return;
-#endif
 
 	if ((modulothing % locvar1 == 0))
 		P_SetMobjState(actor, (locvar2));
@@ -14334,10 +14003,8 @@ void A_LavafallRocks(mobj_t *actor)
 {
 	UINT8 i;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_LavafallRocks", actor))
 		return;
-#endif
 
 	// Don't spawn rocks unless a player is relatively close by.
 	for (i = 0; i < MAXPLAYERS; ++i)
@@ -14367,10 +14034,8 @@ void A_LavafallLava(mobj_t *actor)
 	mobj_t *lavafall;
 	UINT8 i;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_LavafallLava", actor))
 		return;
-#endif
 
 	if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS)))
 		return;
@@ -14397,10 +14062,8 @@ void A_LavafallLava(mobj_t *actor)
 //
 void A_FallingLavaCheck(mobj_t *actor)
 {
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FallingLavaCheck", actor))
 		return;
-#endif
 
 	if (actor->eflags & MFE_TOUCHWATER || P_IsObjectOnGround(actor))
 	{
@@ -14424,10 +14087,8 @@ void A_FireShrink(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FireShrink", actor))
 		return;
-#endif
 
 	actor->destscale = locvar1;
 	actor->scalespeed = FRACUNIT/locvar2;
@@ -14450,10 +14111,8 @@ void A_SpawnPterabytes(mobj_t *actor)
 	UINT8 amount = 1;
 	UINT8 i;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SpawnPterabytes", actor))
 		return;
-#endif
 
 	if (actor->spawnpoint)
 		amount = actor->spawnpoint->extrainfo + 1;
@@ -14487,10 +14146,8 @@ void A_PterabyteHover(mobj_t *actor)
 {
 	angle_t ang, fa;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_PterabyteHover", actor))
 		return;
-#endif
 
 	P_InstaThrust(actor, actor->angle, actor->info->speed);
 	actor->angle += ANG1;
@@ -14511,10 +14168,8 @@ void A_RolloutSpawn(mobj_t *actor)
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_RolloutSpawn", actor))
 		return;
-#endif
 
 	if (!(actor->target)
 		|| P_MobjWasRemoved(actor->target)
@@ -14549,10 +14204,8 @@ void A_RolloutRock(mobj_t *actor)
 	fixed_t speed = P_AproxDistance(actor->momx, actor->momy), topspeed = FixedMul(actor->info->speed, actor->scale);
 	boolean inwater = actor->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER);
 
-#ifdef HAVE_BLUA
 	if (LUA_CallAction("A_RolloutRock", actor))
 		return;
-#endif
 
 	actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves
 
@@ -14634,10 +14287,8 @@ void A_DragonbomberSpawn(mobj_t *actor)
 	UINT8 i;
 	mobj_t *mo = actor;
 
-	#ifdef HAVE_BLUA
-		if (LUA_CallAction("A_DragonbomberSpawn", actor))
-			return;
-	#endif
+	if (LUA_CallAction("A_DragonbomberSpawn", actor))
+		return;
 
 	for (i = 0; i < var1; i++) // spawn tail segments
 	{
@@ -14672,10 +14323,8 @@ void A_DragonWing(mobj_t *actor)
 	mobj_t *target = actor->target;
 	fixed_t x, y;
 
-	#ifdef HAVE_BLUA
-		if (LUA_CallAction("A_DragonWing", actor))
-			return;
-	#endif
+	if (LUA_CallAction("A_DragonWing", actor))
+		return;
 
 	if (target == NULL || !target->health)
 	{
@@ -14707,10 +14356,8 @@ void A_DragonSegment(mobj_t *actor)
 	fixed_t ydist;
 	fixed_t zdist;
 
-	#ifdef HAVE_BLUA
-		if (LUA_CallAction("A_DragonSegment", actor))
-			return;
-	#endif
+	if (LUA_CallAction("A_DragonSegment", actor))
+		return;
 
 	if (target == NULL || !target->health)
 	{
diff --git a/src/p_inter.c b/src/p_inter.c
index 95f8fba41..67d197375 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -365,10 +365,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 	if (special->flags & (MF_ENEMY|MF_BOSS) && special->flags2 & MF2_FRET)
 		return;
 
-#ifdef HAVE_BLUA
 	if (LUAh_TouchSpecial(special, toucher) || P_MobjWasRemoved(special))
 		return;
-#endif
 
 	// 0 = none, 1 = elemental pierce, 2 = bubble bounce
 	elementalpierce = (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY)
@@ -1919,10 +1917,8 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
 	if (!netgame)
 		return; // Presumably it's obvious what's happening in splitscreen.
 
-#ifdef HAVE_BLUA
 	if (LUAh_HurtMsg(player, inflictor, source, damagetype))
 		return;
-#endif
 
 	deadtarget = (player->mo->health <= 0);
 
@@ -2395,10 +2391,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 	target->flags2 &= ~(MF2_SKULLFLY|MF2_NIGHTSPULL);
 	target->health = 0; // This makes it easy to check if something's dead elsewhere.
 
-#ifdef HAVE_BLUA
 	if (LUAh_MobjDeath(target, inflictor, source, damagetype) || P_MobjWasRemoved(target))
 		return;
-#endif
 
 	// Let EVERYONE know what happened to a player! 01-29-2002 Tails
 	if (target->player && !target->player->spectator)
@@ -3511,11 +3505,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source)
 boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
 {
 	player_t *player;
-#ifdef HAVE_BLUA
 	boolean force = false;
-#else
-	static const boolean force = false;
-#endif
 
 	if (objectplacing)
 		return false;
@@ -3533,7 +3523,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 			return false;
 	}
 
-#ifdef HAVE_BLUA
 	// Everything above here can't be forced.
 	if (!metalrecording)
 	{
@@ -3545,7 +3534,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 		else if (shouldForce == 2)
 			return false;
 	}
-#endif
 
 	if (!force)
 	{
@@ -3579,10 +3567,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 		if (!force && target->flags2 & MF2_FRET) // Currently flashing from being hit
 			return false;
 
-#ifdef HAVE_BLUA
 		if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype) || P_MobjWasRemoved(target))
 			return true;
-#endif
 
 		if (target->health > 1)
 			target->flags2 |= MF2_FRET;
@@ -3631,10 +3617,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 				|| (G_GametypeHasTeams() && player->ctfteam == source->player->ctfteam)))
 					return false; // Don't run eachother over in special stages and team games and such
 			}
-#ifdef HAVE_BLUA
 			if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype))
 				return true;
-#endif
 			P_NiGHTSDamage(target, source); // -5s :(
 			return true;
 		}
@@ -3687,18 +3671,14 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 			if (force
 			|| (inflictor && inflictor->flags & MF_MISSILE && inflictor->flags2 & MF2_SUPERFIRE)) // Super Sonic is stunned!
 			{
-#ifdef HAVE_BLUA
 				if (!LUAh_MobjDamage(target, inflictor, source, damage, damagetype))
-#endif
 					P_SuperDamage(player, inflictor, source, damage);
 				return true;
 			}
 			return false;
 		}
-#ifdef HAVE_BLUA
 		else if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype))
 			return true;
-#endif
 		else if (player->powers[pw_shield] || (player->bot && !ultimatemode))  //If One-Hit Shield
 		{
 			P_ShieldDamage(player, inflictor, source, damage, damagetype);
diff --git a/src/p_map.c b/src/p_map.c
index 966684818..988089989 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -756,11 +756,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
 		if (tmthing->z + tmthing->height < thing->z)
 			return true; // underneath
 
-#ifdef HAVE_BLUA
 		// REX HAS SEEN YOU
 		if (!LUAh_SeenPlayer(tmthing->target->player, thing->player))
 			return false;
-#endif
 
 		seenplayer = thing->player;
 		return false;
@@ -948,7 +946,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
 			return true; // the line doesn't cross between either pair of opposite corners
 	}
 
-#ifdef HAVE_BLUA
 	{
 		UINT8 shouldCollide = LUAh_MobjCollide(thing, tmthing); // checks hook for thing's type
 		if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing))
@@ -957,9 +954,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
 			return false; // force collide
 		else if (shouldCollide == 2)
 			return true; // force no collide
-	}
-	{
-		UINT8 shouldCollide = LUAh_MobjMoveCollide(tmthing, thing); // checks hook for tmthing's type
+
+		shouldCollide = LUAh_MobjMoveCollide(tmthing, thing); // checks hook for tmthing's type
 		if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing))
 			return true; // one of them was removed???
 		if (shouldCollide == 1)
@@ -967,7 +963,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
 		else if (shouldCollide == 2)
 			return true; // force no collide
 	}
-#endif
 
 	if (tmthing->type == MT_LAVAFALL_LAVA && (thing->type == MT_RING || thing->type == MT_REDTEAMRING || thing->type == MT_BLUETEAMRING || thing->type == MT_FLINGRING))
 	{
@@ -1946,7 +1941,6 @@ static boolean PIT_CheckLine(line_t *ld)
 	// this line is out of the if so upper and lower textures can be hit by a splat
 	blockingline = ld;
 
-#ifdef HAVE_BLUA
 	{
 		UINT8 shouldCollide = LUAh_MobjLineCollide(tmthing, blockingline); // checks hook for thing's type
 		if (P_MobjWasRemoved(tmthing))
@@ -1956,7 +1950,6 @@ static boolean PIT_CheckLine(line_t *ld)
 		else if (shouldCollide == 2)
 			return true; // force no collide
 	}
-#endif
 
 	if (!ld->backsector) // one sided line
 	{
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 9194cf9f7..8ba1adc73 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -62,9 +62,7 @@ void P_RunCachedActions(void)
 	{
 		var1 = states[ac->statenum].var1;
 		var2 = states[ac->statenum].var2;
-#ifdef HAVE_BLUA
 		astate = &states[ac->statenum];
-#endif
 		if (ac->mobj && !P_MobjWasRemoved(ac->mobj)) // just in case...
 			states[ac->statenum].action.acp1(ac->mobj);
 		next = ac->next;
@@ -459,9 +457,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 		{
 			var1 = st->var1;
 			var2 = st->var2;
-#ifdef HAVE_BLUA
 			astate = st;
-#endif
 			st->action.acp1(mobj);
 
 			// woah. a player was removed by an action.
@@ -585,9 +581,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
 		{
 			var1 = st->var1;
 			var2 = st->var2;
-#ifdef HAVE_BLUA
 			astate = st;
-#endif
 			st->action.acp1(mobj);
 			if (P_MobjWasRemoved(mobj))
 				return false;
@@ -1906,15 +1900,12 @@ void P_XYMovement(mobj_t *mo)
 				B_MoveBlocked(player);
 		}
 
-#ifdef HAVE_BLUA
 		if (LUAh_MobjMoveBlocked(mo))
 		{
 			if (P_MobjWasRemoved(mo))
 				return;
 		}
-		else
-#endif
-		if (P_MobjWasRemoved(mo))
+		else if (P_MobjWasRemoved(mo))
 			return;
 		else if (mo->flags & MF_BOUNCE)
 		{
@@ -7643,12 +7634,10 @@ static void P_RosySceneryThink(mobj_t *mobj)
 
 static void P_MobjSceneryThink(mobj_t *mobj)
 {
-#ifdef HAVE_BLUA
 	if (LUAh_MobjThinker(mobj))
 		return;
 	if (P_MobjWasRemoved(mobj))
 		return;
-#endif
 
 	if ((mobj->flags2 & MF2_SHIELD) && !P_AddShield(mobj))
 		return;
@@ -7993,9 +7982,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
 
 		if (!mobj->fuse)
 		{
-#ifdef HAVE_BLUA
 			if (!LUAh_MobjFuse(mobj))
-#endif
 				P_RemoveMobj(mobj);
 			return;
 		}
@@ -8054,9 +8041,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
 			mobj->fuse--;
 			if (!mobj->fuse)
 			{
-#ifdef HAVE_BLUA
 				if (!LUAh_MobjFuse(mobj))
-#endif
 					P_RemoveMobj(mobj);
 				return;
 			}
@@ -8085,7 +8070,6 @@ static boolean P_MobjPushableThink(mobj_t *mobj)
 
 static boolean P_MobjBossThink(mobj_t *mobj)
 {
-#ifdef HAVE_BLUA
 	if (LUAh_BossThinker(mobj))
 	{
 		if (P_MobjWasRemoved(mobj))
@@ -8094,7 +8078,6 @@ static boolean P_MobjBossThink(mobj_t *mobj)
 	else if (P_MobjWasRemoved(mobj))
 		return false;
 	else
-#endif
 		switch (mobj->type)
 		{
 		case MT_EGGMOBILE:
@@ -10004,113 +9987,110 @@ static boolean P_FuseThink(mobj_t *mobj)
 	if (mobj->fuse)
 		return true;
 
-#ifdef HAVE_BLUA
 	if (LUAh_MobjFuse(mobj) || P_MobjWasRemoved(mobj))
 		;
-	else
-#endif
-		if (mobj->info->flags & MF_MONITOR)
+	else if (mobj->info->flags & MF_MONITOR)
+	{
+		P_MonitorFuseThink(mobj);
+		return false;
+	}
+	else switch (mobj->type)
+	{
+		// gargoyle and snowman handled in P_PushableThinker, not here
+	case MT_THROWNGRENADE:
+	case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE:
+		P_SetMobjState(mobj, mobj->info->deathstate);
+		break;
+	case MT_LHRT:
+		P_KillMobj(mobj, NULL, NULL, 0);
+		break;
+	case MT_BLUEFLAG:
+	case MT_REDFLAG:
+		P_FlagFuseThink(mobj);
+		P_RemoveMobj(mobj);
+		return false;
+	case MT_FANG:
+		if (mobj->flags2 & MF2_SLIDEPUSH)
 		{
-			P_MonitorFuseThink(mobj);
+			var1 = 0;
+			var2 = 0;
+			A_BossDeath(mobj);
 			return false;
 		}
-		else switch (mobj->type)
+		P_SetMobjState(mobj, mobj->state->nextstate);
+		if (P_MobjWasRemoved(mobj))
+			return false;
+		break;
+	case MT_METALSONIC_BATTLE:
+		break; // don't remove
+	case MT_SPIKE:
+		P_SetMobjState(mobj, mobj->state->nextstate);
+		mobj->fuse = mobj->info->speed;
+		if (mobj->spawnpoint)
+			mobj->fuse += mobj->spawnpoint->angle;
+		break;
+	case MT_WALLSPIKE:
+		P_SetMobjState(mobj, mobj->state->nextstate);
+		mobj->fuse = mobj->info->speed;
+		if (mobj->spawnpoint)
+			mobj->fuse += (mobj->spawnpoint->angle / 360);
+		break;
+	case MT_NIGHTSCORE:
+		P_RemoveMobj(mobj);
+		return false;
+	case MT_LAVAFALL:
+		if (mobj->state - states == S_LAVAFALL_DORMANT)
 		{
-			// gargoyle and snowman handled in P_PushableThinker, not here
-		case MT_THROWNGRENADE:
-		case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE:
-			P_SetMobjState(mobj, mobj->info->deathstate);
+			mobj->fuse = 30;
+			P_SetMobjState(mobj, S_LAVAFALL_TELL);
+			S_StartSound(mobj, mobj->info->seesound);
+		}
+		else if (mobj->state - states == S_LAVAFALL_TELL)
+		{
+			mobj->fuse = 40;
+			P_SetMobjState(mobj, S_LAVAFALL_SHOOT);
+			S_StopSound(mobj);
+			S_StartSound(mobj, mobj->info->attacksound);
+		}
+		else
+		{
+			mobj->fuse = 30;
+			P_SetMobjState(mobj, S_LAVAFALL_DORMANT);
+			S_StopSound(mobj);
+		}
+		return false;
+	case MT_PYREFLY:
+		if (mobj->health <= 0)
 			break;
-		case MT_LHRT:
-			P_KillMobj(mobj, NULL, NULL, 0);
-			break;
-		case MT_BLUEFLAG:
-		case MT_REDFLAG:
-			P_FlagFuseThink(mobj);
-			P_RemoveMobj(mobj);
-			return false;
-		case MT_FANG:
-			if (mobj->flags2 & MF2_SLIDEPUSH)
-			{
-				var1 = 0;
-				var2 = 0;
-				A_BossDeath(mobj);
-				return false;
-			}
-			P_SetMobjState(mobj, mobj->state->nextstate);
-			if (P_MobjWasRemoved(mobj))
-				return false;
-			break;
-		case MT_METALSONIC_BATTLE:
-			break; // don't remove
-		case MT_SPIKE:
-			P_SetMobjState(mobj, mobj->state->nextstate);
-			mobj->fuse = mobj->info->speed;
-			if (mobj->spawnpoint)
-				mobj->fuse += mobj->spawnpoint->angle;
-			break;
-		case MT_WALLSPIKE:
-			P_SetMobjState(mobj, mobj->state->nextstate);
-			mobj->fuse = mobj->info->speed;
-			if (mobj->spawnpoint)
-				mobj->fuse += (mobj->spawnpoint->angle / 360);
-			break;
-		case MT_NIGHTSCORE:
-			P_RemoveMobj(mobj);
-			return false;
-		case MT_LAVAFALL:
-			if (mobj->state - states == S_LAVAFALL_DORMANT)
-			{
-				mobj->fuse = 30;
-				P_SetMobjState(mobj, S_LAVAFALL_TELL);
-				S_StartSound(mobj, mobj->info->seesound);
-			}
-			else if (mobj->state - states == S_LAVAFALL_TELL)
-			{
-				mobj->fuse = 40;
-				P_SetMobjState(mobj, S_LAVAFALL_SHOOT);
-				S_StopSound(mobj);
-				S_StartSound(mobj, mobj->info->attacksound);
-			}
-			else
-			{
-				mobj->fuse = 30;
-				P_SetMobjState(mobj, S_LAVAFALL_DORMANT);
-				S_StopSound(mobj);
-			}
-			return false;
-		case MT_PYREFLY:
-			if (mobj->health <= 0)
-				break;
 
-			mobj->extravalue2 = (mobj->extravalue2 + 1) % 3;
-			if (mobj->extravalue2 == 0)
-			{
-				P_SetMobjState(mobj, mobj->info->spawnstate);
-				mobj->fuse = 100;
-				S_StopSound(mobj);
-				S_StartSound(mobj, sfx_s3k8c);
-			}
-			else if (mobj->extravalue2 == 1)
-			{
-				mobj->fuse = 50;
-				S_StartSound(mobj, sfx_s3ka3);
-			}
-			else
-			{
-				P_SetMobjState(mobj, mobj->info->meleestate);
-				mobj->fuse = 100;
-				S_StopSound(mobj);
-				S_StartSound(mobj, sfx_s3kc2l);
-			}
-			return false;
-		case MT_PLAYER:
-			break; // don't remove
-		default:
-			P_SetMobjState(mobj, mobj->info->xdeathstate); // will remove the mobj if S_NULL.
-			break;
-			// Looking for monitors? They moved to a special condition above.
+		mobj->extravalue2 = (mobj->extravalue2 + 1) % 3;
+		if (mobj->extravalue2 == 0)
+		{
+			P_SetMobjState(mobj, mobj->info->spawnstate);
+			mobj->fuse = 100;
+			S_StopSound(mobj);
+			S_StartSound(mobj, sfx_s3k8c);
 		}
+		else if (mobj->extravalue2 == 1)
+		{
+			mobj->fuse = 50;
+			S_StartSound(mobj, sfx_s3ka3);
+		}
+		else
+		{
+			P_SetMobjState(mobj, mobj->info->meleestate);
+			mobj->fuse = 100;
+			S_StopSound(mobj);
+			S_StartSound(mobj, sfx_s3kc2l);
+		}
+		return false;
+	case MT_PLAYER:
+		break; // don't remove
+	default:
+		P_SetMobjState(mobj, mobj->info->xdeathstate); // will remove the mobj if S_NULL.
+		break;
+		// Looking for monitors? They moved to a special condition above.
+	}
 
 	return !P_MobjWasRemoved(mobj);
 }
@@ -10179,7 +10159,6 @@ void P_MobjThinker(mobj_t *mobj)
 		return;
 	}
 
-#ifdef HAVE_BLUA
 	// Check for a Lua thinker first
 	if (!mobj->player)
 	{
@@ -10193,7 +10172,7 @@ void P_MobjThinker(mobj_t *mobj)
 		if (P_MobjWasRemoved(mobj))
 			return;
 	}
-#endif
+
 	// if it's pushable, or if it would be pushable other than temporary disablement, use the
 	// separate thinker
 	if (mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse))
@@ -10656,7 +10635,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 	// Set shadowscale here, before spawn hook so that Lua can change it
 	mobj->shadowscale = P_DefaultMobjShadowScale(mobj);
 
-#ifdef HAVE_BLUA
 	// DANGER! This can cause P_SpawnMobj to return NULL!
 	// Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks!
 	if (LUAh_MobjSpawn(mobj))
@@ -10667,7 +10645,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 	else if (P_MobjWasRemoved(mobj))
 		return NULL;
 	else
-#endif
 	switch (mobj->type)
 	{
 		case MT_ALTVIEWMAN:
@@ -10937,9 +10914,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 		{
 			var1 = st->var1;
 			var2 = st->var2;
-#ifdef HAVE_BLUA
 			astate = st;
-#endif
 			st->action.acp1(mobj);
 			// DANGER! This can cause P_SpawnMobj to return NULL!
 			// Avoid using MF_RUNSPAWNFUNC on mobjs whose spawn state expects target or tracer to already be set!
@@ -11037,16 +11012,12 @@ size_t iquehead, iquetail;
 void P_RemoveMobj(mobj_t *mobj)
 {
 	I_Assert(mobj != NULL);
-#ifdef HAVE_BLUA
 	if (P_MobjWasRemoved(mobj))
 		return; // something already removing this mobj.
 
 	mobj->thinker.function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; // shh. no recursing.
 	LUAh_MobjRemoved(mobj);
 	mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; // needed for P_UnsetThingPosition, etc. to work.
-#else
-	I_Assert(!P_MobjWasRemoved(mobj));
-#endif
 
 	// Rings only, please!
 	if (mobj->spawnpoint &&
@@ -12710,7 +12681,6 @@ static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong)
 
 static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle)
 {
-#ifdef HAVE_BLUA
 	boolean override = LUAh_MapThingSpawn(mobj, mthing);
 
 	if (P_MobjWasRemoved(mobj))
@@ -12718,7 +12688,6 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
 
 	if (override)
 		return true;
-#endif
 
 	switch (mobj->type)
 	{
diff --git a/src/p_saveg.c b/src/p_saveg.c
index e6c7d07fd..37d5f99ba 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -4183,8 +4183,6 @@ void P_SaveGame(void)
 {
 	P_ArchiveMisc();
 	P_ArchivePlayer();
-
-	// yes, even in non HAVE_BLUA
 	P_ArchiveLuabanksAndConsistency();
 }
 
@@ -4220,9 +4218,7 @@ void P_SaveNetGame(void)
 		P_NetArchiveSpecials();
 		P_NetArchiveColormaps();
 	}
-#ifdef HAVE_BLUA
 	LUA_Archive();
-#endif
 
 	P_ArchiveLuabanksAndConsistency();
 }
@@ -4264,9 +4260,7 @@ boolean P_LoadNetGame(void)
 		P_RelinkPointers();
 		P_FinishMobjs();
 	}
-#ifdef HAVE_BLUA
 	LUA_UnArchive();
-#endif
 
 	// This is stupid and hacky, but maybe it'll work!
 	P_SetRandSeed(P_GetInitSeed());
diff --git a/src/p_setup.c b/src/p_setup.c
index 766e82ca0..b3b86886f 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -57,9 +57,7 @@
 
 #include "filesrch.h" // refreshdirmenu
 
-#ifdef HAVE_BLUA
 #include "lua_hud.h" // level title
-#endif
 
 #include "f_finale.h" // wipes
 
@@ -3526,9 +3524,7 @@ boolean P_LoadLevel(boolean fromnetsave)
 	// Close text prompt before freeing the old level
 	F_EndTextPrompt(false, true);
 
-#ifdef HAVE_BLUA
 	LUA_InvalidateLevel();
-#endif
 
 	for (ss = sectors; sectors+numsectors != ss; ss++)
 	{
@@ -3665,9 +3661,7 @@ boolean P_LoadLevel(boolean fromnetsave)
 				G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
 		}
 		P_PreTicker(2);
-#ifdef HAVE_BLUA
 		LUAh_MapLoad();
-#endif
 	}
 
 	// No render mode, stop here.
@@ -3859,10 +3853,8 @@ boolean P_AddWadFile(const char *wadfilename)
 
 		// Update the detected resources.
 		// Note: ALWAYS load Lua scripts first, SOCs right after, and the remaining resources afterwards.
-#ifdef HAVE_BLUA
 //		if (luaNum) // Lua scripts.
 //			P_LoadLuaScrRange(wadnum, luaPos, luaNum);
-#endif
 //		if (socNum) // SOCs.
 //			P_LoadDehackRange(wadnum, socPos, socNum);
 		if (sfxNum) // Sounds. TODO: Function currently only updates already existing sounds, the rest is handled somewhere else.
diff --git a/src/p_spec.c b/src/p_spec.c
index aecdb3b98..8938a51b6 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -3366,14 +3366,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 		}
 
 		case 443: // Calls a named Lua function
-#ifdef HAVE_BLUA
 			if (line->text)
 				LUAh_LinedefExecute(line, mo, callsec);
 			else
 				CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(line-lines));
-#else
-			CONS_Alert(CONS_ERROR, "The map is trying to run a Lua script, but this exe was not compiled with Lua support!\n");
-#endif
 			break;
 
 		case 444: // Earthquake camera
diff --git a/src/p_tick.c b/src/p_tick.c
index 1d421ad37..7ea6edb2d 100644
--- a/src/p_tick.c
+++ b/src/p_tick.c
@@ -269,9 +269,7 @@ void P_RemoveThinkerDelayed(thinker_t *thinker)
 //
 void P_RemoveThinker(thinker_t *thinker)
 {
-#ifdef HAVE_BLUA
 	LUA_InvalidateUserdata(thinker);
-#endif
 	thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed;
 }
 
@@ -643,9 +641,7 @@ void P_Ticker(boolean run)
 		if (demoplayback)
 			G_ReadDemoTiccmd(&players[consoleplayer].cmd, 0);
 
-		#ifdef HAVE_BLUA
 		LUAh_PreThinkFrame();
-		#endif
 
 		for (i = 0; i < MAXPLAYERS; i++)
 			if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
@@ -671,9 +667,7 @@ void P_Ticker(boolean run)
 			if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
 				P_PlayerAfterThink(&players[i]);
 
-#ifdef HAVE_BLUA
 		LUAh_ThinkFrame();
-#endif
 	}
 
 	// Run shield positioning
@@ -745,9 +739,7 @@ void P_Ticker(boolean run)
 		if (modeattacking)
 			G_GhostTicker();
 
-#ifdef HAVE_BLUA
 		LUAh_PostThinkFrame();
-#endif
 	}
 
 	P_MapEnd();
@@ -767,9 +759,8 @@ void P_PreTicker(INT32 frames)
 	{
 		P_MapStart();
 
-#ifdef HAVE_BLUA
 		LUAh_PreThinkFrame();
-#endif
+
 		for (i = 0; i < MAXPLAYERS; i++)
 			if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
 			{
@@ -793,9 +784,7 @@ void P_PreTicker(INT32 frames)
 			if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
 				P_PlayerAfterThink(&players[i]);
 
-#ifdef HAVE_BLUA
 		LUAh_ThinkFrame();
-#endif
 
 		// Run shield positioning
 		P_RunShields();
@@ -804,9 +793,7 @@ void P_PreTicker(INT32 frames)
 		P_UpdateSpecials();
 		P_RespawnSpecials();
 
-#ifdef HAVE_BLUA
 		LUAh_PostThinkFrame();
-#endif
 
 		P_MapEnd();
 	}
diff --git a/src/p_user.c b/src/p_user.c
index 345da85ef..19b53e16f 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -1109,7 +1109,6 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing)
 	if (!player->mo || player->spectator || !thing || P_MobjWasRemoved(thing))
 		return false;
 
-#ifdef HAVE_BLUA
 	{
 		UINT8 shouldCollide = LUAh_PlayerCanDamage(player, thing);
 		if (P_MobjWasRemoved(thing))
@@ -1119,7 +1118,6 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing)
 		else if (shouldCollide == 2)
 			return false; // force no
 	}
-#endif
 
 	// Invinc/super. Not for Monitors.
 	if (!(thing->flags & MF_MONITOR) && (player->powers[pw_invulnerability] || player->powers[pw_super]))
@@ -1521,7 +1519,7 @@ void P_PlayJingle(player_t *player, jingletype_t jingletype)
 
 	char newmusic[7];
 	strncpy(newmusic, musname, 7);
-#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
+#ifdef HAVE_LUA_MUSICPLUS
  	if(LUAh_MusicJingle(jingletype, newmusic, &musflags, &looping))
  		return;
 #endif
@@ -1602,10 +1600,8 @@ boolean P_EvaluateMusicStatus(UINT16 status, const char *musname)
 				break;
 
 			case JT_OTHER:  // Other state
-#ifdef HAVE_BLUA
 				result = LUAh_ShouldJingleContinue(&players[i], musname);
 				break;
-#endif
 
 			case JT_NONE:   // Null state
 			case JT_MASTER: // Main level music
@@ -1870,10 +1866,8 @@ void P_SpawnShieldOrb(player_t *player)
 		I_Error("P_SpawnShieldOrb: player->mo is NULL!\n");
 #endif
 
-#ifdef HAVE_BLUA
 	if (LUAh_ShieldSpawn(player))
 		return;
-#endif
 
 	if (player->powers[pw_shield] & SH_FORCE)
 		orbtype = MT_FORCE_ORB;
@@ -4638,13 +4632,11 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
 		&& (player->pflags & PF_JUMPSTASIS || player->mo->state-states != S_PLAY_GLIDE_LANDING))
 		return;
 
-#ifdef HAVE_BLUA
 	if (cmd->buttons & BT_USE)
 	{
 		if (LUAh_SpinSpecial(player))
 			return;
 	}
-#endif
 
 #ifdef ESLOPE
 	canstand = (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2);
@@ -5130,11 +5122,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 					}
 				}
 			}
-			if (cmd->buttons & BT_USE // Spin button effects
-	#ifdef HAVE_BLUA
-			&& !LUAh_ShieldSpecial(player)
-	#endif
-				)
+			if (cmd->buttons & BT_USE && !LUAh_ShieldSpecial(player)) // Spin button effects
 			{
 				// Force stop
 				if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE)
@@ -5212,51 +5200,48 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 				// and you don't have a shield, do it!
 				P_DoSuperTransformation(player, false);
 			}
-			else
-#ifdef HAVE_BLUA
-			if (!LUAh_JumpSpinSpecial(player))
-#endif
-			switch (player->charability)
-			{
-				case CA_THOK:
-					if (player->powers[pw_super]) // Super Sonic float
-					{
-						if ((player->speed > 5*player->mo->scale) // FixedMul(5<<FRACBITS, player->mo->scale), but scale is FRACUNIT-based
-						&& (P_MobjFlip(player->mo)*player->mo->momz <= 0))
+			else if (!LUAh_JumpSpinSpecial(player))
+				switch (player->charability)
+				{
+					case CA_THOK:
+						if (player->powers[pw_super]) // Super Sonic float
 						{
-							if (player->panim != PA_RUN && player->panim != PA_WALK)
+							if ((player->speed > 5*player->mo->scale) // FixedMul(5<<FRACBITS, player->mo->scale), but scale is FRACUNIT-based
+							&& (P_MobjFlip(player->mo)*player->mo->momz <= 0))
 							{
-								if (player->speed >= FixedMul(player->runspeed, player->mo->scale))
-									P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT_RUN);
-								else
-									P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT);
-							}
+								if (player->panim != PA_RUN && player->panim != PA_WALK)
+								{
+									if (player->speed >= FixedMul(player->runspeed, player->mo->scale))
+										P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT_RUN);
+									else
+										P_SetPlayerMobjState(player->mo, S_PLAY_FLOAT);
+								}
 
-							player->mo->momz = 0;
-							player->pflags &= ~(PF_STARTJUMP|PF_SPINNING);
+								player->mo->momz = 0;
+								player->pflags &= ~(PF_STARTJUMP|PF_SPINNING);
+							}
 						}
-					}
-					break;
-				case CA_TELEKINESIS:
-					if (!(player->pflags & (PF_THOKKED|PF_USEDOWN)) || (player->charflags & SF_MULTIABILITY))
-					{
-						P_Telekinesis(player,
-							-FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player)
-							FixedMul(384*FRACUNIT, player->mo->scale));
-					}
-					break;
-				case CA_TWINSPIN:
-					if ((player->charability2 == CA2_MELEE) && (!(player->pflags & (PF_THOKKED|PF_USEDOWN)) || player->charflags & SF_MULTIABILITY))
-					{
-						player->pflags |= PF_THOKKED;
-						S_StartSound(player->mo, sfx_s3k42);
-						player->mo->frame = 0;
-						P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN);
-					}
-					break;
-				default:
-					break;
-			}
+						break;
+					case CA_TELEKINESIS:
+						if (!(player->pflags & (PF_THOKKED|PF_USEDOWN)) || (player->charflags & SF_MULTIABILITY))
+						{
+							P_Telekinesis(player,
+								-FixedMul(player->actionspd, player->mo->scale), // -ve thrust (pulling towards player)
+								FixedMul(384*FRACUNIT, player->mo->scale));
+						}
+						break;
+					case CA_TWINSPIN:
+						if ((player->charability2 == CA2_MELEE) && (!(player->pflags & (PF_THOKKED|PF_USEDOWN)) || player->charflags & SF_MULTIABILITY))
+						{
+							player->pflags |= PF_THOKKED;
+							S_StartSound(player->mo, sfx_s3k42);
+							player->mo->frame = 0;
+							P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN);
+						}
+						break;
+					default:
+						break;
+				}
 		}
 	}
 
@@ -5292,16 +5277,13 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 
 	if (cmd->buttons & BT_JUMP && !player->exiting && !P_PlayerInPain(player))
 	{
-#ifdef HAVE_BLUA
 		if (LUAh_JumpSpecial(player))
 			;
-		else
-#endif
-		if (player->pflags & PF_JUMPDOWN) // all situations below this require jump button not to be pressed already
+		// all situations below this require jump button not to be pressed already
+		else if (player->pflags & PF_JUMPDOWN)
 			;
-		else
 		// Jump S3&K style while in quicksand.
-		if (P_InQuicksand(player->mo))
+		else if (P_InQuicksand(player->mo))
 		{
 			P_DoJump(player, true);
 			player->secondjump = 0;
@@ -5313,9 +5295,8 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 			P_SetTarget(&player->mo->tracer, NULL);
 			player->powers[pw_flashing] = TICRATE/4;
 		}
-		else
 		// can't jump while in air, can't jump while jumping
-		if (onground || player->climbing || player->powers[pw_carry])
+		else if (onground || player->climbing || player->powers[pw_carry])
 		{
 			P_DoJump(player, true);
 			player->secondjump = 0;
@@ -5331,9 +5312,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 		}*/
 		else if (player->pflags & PF_JUMPED)
 		{
-#ifdef HAVE_BLUA
 			if (!LUAh_AbilitySpecial(player))
-#endif
 			switch (player->charability)
 			{
 				case CA_THOK:
@@ -5528,30 +5507,28 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 		}
 		else if (player->pflags & PF_THOKKED)
 		{
-#ifdef HAVE_BLUA
 			if (!LUAh_AbilitySpecial(player))
-#endif
-			switch (player->charability)
-			{
-				case CA_FLY:
-				case CA_SWIM: // Swim
-					if (player->charability == CA_SWIM && !(player->mo->eflags & MFE_UNDERWATER))
-						; // Can't do anything if you're a fish out of water!
-					else if (player->powers[pw_tailsfly]) // If currently flying, give an ascend boost.
-					{
-						player->fly1 = 20;
+				switch (player->charability)
+				{
+					case CA_FLY:
+					case CA_SWIM: // Swim
+						if (player->charability == CA_SWIM && !(player->mo->eflags & MFE_UNDERWATER))
+							; // Can't do anything if you're a fish out of water!
+						else if (player->powers[pw_tailsfly]) // If currently flying, give an ascend boost.
+						{
+							player->fly1 = 20;
 
-						if (player->charability == CA_SWIM)
-							player->fly1 /= 2;
+							if (player->charability == CA_SWIM)
+								player->fly1 /= 2;
 
-						// Slow down!
-						if (player->speed > FixedMul(8*FRACUNIT, player->mo->scale) && player->speed > FixedMul(player->normalspeed>>1, player->mo->scale))
-							P_Thrust(player->mo, R_PointToAngle2(0,0,player->mo->momx,player->mo->momy), FixedMul(-4*FRACUNIT, player->mo->scale));
-					}
-					break;
-				default:
-					break;
-			}
+							// Slow down!
+							if (player->speed > FixedMul(8*FRACUNIT, player->mo->scale) && player->speed > FixedMul(player->normalspeed>>1, player->mo->scale))
+								P_Thrust(player->mo, R_PointToAngle2(0,0,player->mo->momx,player->mo->momy), FixedMul(-4*FRACUNIT, player->mo->scale));
+						}
+						break;
+					default:
+						break;
+				}
 		}
 		else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super])
 			P_DoJumpShield(player);
@@ -10638,10 +10615,8 @@ boolean P_SpectatorJoinGame(player_t *player)
 		else
 			changeto = (P_RandomFixed() & 1) + 1;
 
-#ifdef HAVE_BLUA
 		if (!LUAh_TeamSwitch(player, changeto, true, false, false))
 			return false;
-#endif
 
 		if (player->mo)
 		{
@@ -10655,11 +10630,9 @@ boolean P_SpectatorJoinGame(player_t *player)
 		//Reset away view
 		if (P_IsLocalPlayer(player) && displayplayer != consoleplayer)
 		{
-#ifdef HAVE_BLUA
 			// Call ViewpointSwitch hooks here.
 			// The viewpoint was forcibly changed.
 			LUAh_ViewpointSwitch(player, &players[consoleplayer], true);
-#endif
 			displayplayer = consoleplayer;
 		}
 
@@ -10677,10 +10650,8 @@ boolean P_SpectatorJoinGame(player_t *player)
 		// respawn in place and sit there for the rest of the round.
 		if (!((gametyperules & GTR_HIDEFROZEN) && leveltime > (hidetime * TICRATE)))
 		{
-#ifdef HAVE_BLUA
 			if (!LUAh_TeamSwitch(player, 3, true, false, false))
 				return false;
-#endif
 			if (player->mo)
 			{
 				P_RemoveMobj(player->mo);
@@ -10704,11 +10675,9 @@ boolean P_SpectatorJoinGame(player_t *player)
 			//Reset away view
 			if (P_IsLocalPlayer(player) && displayplayer != consoleplayer)
 			{
-#ifdef HAVE_BLUA
 				// Call ViewpointSwitch hooks here.
 				// The viewpoint was forcibly changed.
 				LUAh_ViewpointSwitch(player, &players[consoleplayer], true);
-#endif
 				displayplayer = consoleplayer;
 			}
 
@@ -11631,9 +11600,7 @@ void P_PlayerThink(player_t *player)
 		}
 		if (player->playerstate == PST_REBORN)
 		{
-#ifdef HAVE_BLUA
 			LUAh_PlayerThink(player);
-#endif
 			return;
 		}
 	}
@@ -11737,9 +11704,7 @@ void P_PlayerThink(player_t *player)
 
 			if (player->playerstate == PST_DEAD)
 			{
-#ifdef HAVE_BLUA
 				LUAh_PlayerThink(player);
-#endif
 				return;
 			}
 		}
@@ -11862,9 +11827,7 @@ void P_PlayerThink(player_t *player)
 	{
 		player->mo->flags2 &= ~MF2_SHADOW;
 		P_DeathThink(player);
-#ifdef HAVE_BLUA
 		LUAh_PlayerThink(player);
-#endif
 		return;
 	}
 
@@ -11906,9 +11869,7 @@ void P_PlayerThink(player_t *player)
 	{
 		if (P_SpectatorJoinGame(player))
 		{
-#ifdef HAVE_BLUA
 			LUAh_PlayerThink(player);
-#endif
 			return; // player->mo was removed.
 		}
 	}
@@ -12013,9 +11974,7 @@ void P_PlayerThink(player_t *player)
 
 	if (!player->mo)
 	{
-#ifdef HAVE_BLUA
 		LUAh_PlayerThink(player);
-#endif
 		return; // P_MovePlayer removed player->mo.
 	}
 
@@ -12457,9 +12416,7 @@ void P_PlayerThink(player_t *player)
 	}
 #undef dashmode
 
-#ifdef HAVE_BLUA
 	LUAh_PlayerThink(player);
-#endif
 
 /*
 //	Colormap verification
@@ -13009,11 +12966,9 @@ void P_PlayerAfterThink(player_t *player)
 
 		if (player->followmobj)
 		{
-#ifdef HAVE_BLUA
 			if (LUAh_FollowMobj(player, player->followmobj) || P_MobjWasRemoved(player->followmobj))
 				{;}
 			else
-#endif
 			{
 				switch (player->followmobj->type)
 				{
diff --git a/src/s_sound.c b/src/s_sound.c
index 91345b3a2..0cc40a9ce 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -40,7 +40,7 @@ extern INT32 msg_id;
 #include "m_misc.h" // for tunes command
 #include "m_cond.h" // for conditionsets
 
-#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
+#ifdef HAVE_LUA_MUSICPLUS
 #include "lua_hook.h" // MusicChange hook
 #endif
 
@@ -2314,7 +2314,7 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32
 		return;
 
 	strncpy(newmusic, mmusic, 7);
-#if defined(HAVE_BLUA) && defined(HAVE_LUA_MUSICPLUS)
+#ifdef HAVE_LUA_MUSICPLUS
 	if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms))
 		return;
 #endif
diff --git a/src/sdl/Srb2SDL-vc9.vcproj b/src/sdl/Srb2SDL-vc9.vcproj
index 3898aeba4..9ef4301cc 100644
--- a/src/sdl/Srb2SDL-vc9.vcproj
+++ b/src/sdl/Srb2SDL-vc9.vcproj
@@ -50,7 +50,7 @@
 				Name="VCCLCompilerTool"
 				Optimization="0"
 				AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
-				PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
+				PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
 				MinimalRebuild="true"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -145,7 +145,7 @@
 				Name="VCCLCompilerTool"
 				Optimization="0"
 				AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
-				PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
+				PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
 				MinimalRebuild="true"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -248,7 +248,7 @@
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
 				AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
-				PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
+				PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
 				StringPooling="true"
 				RuntimeLibrary="0"
 				PrecompiledHeaderFile=".\..\..\objs\VC9\$(Platform)\$(Configuration)\SDL\Srb2SDL-vc9.pch"
@@ -350,7 +350,7 @@
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
 				AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
-				PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
+				PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
 				StringPooling="true"
 				RuntimeLibrary="0"
 				PrecompiledHeaderFile=".\..\..\objs\VC9\$(Platform)\$(Configuration)\SDL\Srb2SDL-vc9.pch"
diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
index b615bc1df..182220265 100644
--- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
+++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
@@ -1272,7 +1272,6 @@
 					HAVE_SDL,
 					HAVE_MIXER,
 					HAVE_PNG,
-					HAVE_BLUA,
 					LUA_USE_POSIX,
 					COMPVERSION,
 					HWRENDER,
@@ -1395,7 +1394,6 @@
 					HAVE_SDL,
 					HAVE_MIXER,
 					HAVE_PNG,
-					HAVE_BLUA,
 					LUA_USE_POSIX,
 					COMPVERSION,
 					HWRENDER,
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 4864f2af6..ee7fc3f21 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -42,9 +42,7 @@
 #include "hardware/hw_main.h"
 #endif
 
-#ifdef HAVE_BLUA
 #include "lua_hud.h"
-#endif
 
 UINT16 objectsdrawn = 0;
 
@@ -969,11 +967,7 @@ static void ST_drawLivesArea(void)
 		V_DrawThinString(hudinfo[HUD_LIVES].x+18, hudinfo[HUD_LIVES].y, v_colmap, skins[stplyr->skin].hudname);
 
 	// Power Stones collected
-	if (G_RingSlingerGametype()
-#ifdef HAVE_BLUA
-	&& LUA_HudEnabled(hud_powerstones)
-#endif
-	)
+	if (G_RingSlingerGametype() && LUA_HudEnabled(hud_powerstones))
 	{
 		INT32 workx = hudinfo[HUD_LIVES].x+1, j;
 		if ((leveltime & 1) && stplyr->powers[pw_invulnerability] && (stplyr->powers[pw_sneakers] == stplyr->powers[pw_invulnerability])) // hack; extremely unlikely to be activated unintentionally
@@ -1341,17 +1335,11 @@ void ST_drawTitleCard(void)
 	if (!G_IsTitleCardAvailable())
 		return;
 
-#ifdef HAVE_BLUA
 	if (!LUA_HudEnabled(hud_stagetitle))
 		goto luahook;
-#endif
 
 	if (lt_ticker >= (lt_endtime + TICRATE))
-#ifdef HAVE_BLUA
 		goto luahook;
-#else
-		return;
-#endif
 
 	if ((lt_ticker-lt_lasttic) > 1)
 		lt_ticker = lt_lasttic+1;
@@ -1396,10 +1384,8 @@ void ST_drawTitleCard(void)
 
 	lt_lasttic = lt_ticker;
 
-#ifdef HAVE_BLUA
 luahook:
 	LUAh_TitleCardHUD(stplyr);
-#endif
 }
 
 //
@@ -1444,7 +1430,7 @@ static void ST_drawPowerupHUD(void)
 
 	if (stplyr->spectator || stplyr->playerstate != PST_LIVE)
 		return;
-	
+
 // ---------
 // Finish icon
 // ---------
@@ -1785,11 +1771,7 @@ static void ST_drawNiGHTSHUD(void)
 	const boolean oldspecialstage = (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS));
 
 	// Drill meter
-	if (
-#ifdef HAVE_BLUA
-	LUA_HudEnabled(hud_nightsdrill) &&
-#endif
-	stplyr->powers[pw_carry] == CR_NIGHTSMODE)
+	if (LUA_HudEnabled(hud_nightsdrill) && stplyr->powers[pw_carry] == CR_NIGHTSMODE)
 	{
 		INT32 locx = 16, locy = 180;
 		INT32 dfill;
@@ -1831,9 +1813,7 @@ static void ST_drawNiGHTSHUD(void)
 	if (!oldspecialstage
 	// Don't display when the score is showing (it popping up for a split second when exiting a map is intentional)
 	&& !(stplyr->texttimer && stplyr->textvar == 4)
-#ifdef HAVE_BLUA
 	&& LUA_HudEnabled(hud_nightslink)
-#endif
 	&& ((cv_debug & DBG_NIGHTSBASIC) || stplyr->linkcount > 1)) // When debugging, show "0 Link".
 	{
 		ST_drawNiGHTSLink();
@@ -1847,10 +1827,8 @@ static void ST_drawNiGHTSHUD(void)
 	}
 
 	// Begin drawing brackets/chip display
-#ifdef HAVE_BLUA
 	if (LUA_HudEnabled(hud_nightsspheres))
 	{
-#endif
 	ST_DrawTopLeftOverlayPatch(16, 8, nbracket);
 	if (G_IsSpecialStage(gamemap))
 		ST_DrawTopLeftOverlayPatch(24, 16, (
@@ -1987,24 +1965,14 @@ static void ST_drawNiGHTSHUD(void)
 		V_DrawTallNum((total_spherecount >= 1000) ? 76 : 72, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_spherecount);
 	else
 		V_DrawTallNum(68, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_spherecount);
-#ifdef HAVE_BLUA
 	}
-#endif
 
 	// Score
-	if (!stplyr->exiting && !oldspecialstage
-#ifdef HAVE_BLUA
-	&& LUA_HudEnabled(hud_nightsscore)
-#endif
-	)
+	if (!stplyr->exiting && !oldspecialstage && LUA_HudEnabled(hud_nightsscore))
 		ST_DrawNightsOverlayNum(304<<FRACBITS, 14<<FRACBITS, FRACUNIT, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTORIGHT, stplyr->marescore, nightsnum, SKINCOLOR_AZURE);
 
-	if (!stplyr->exiting
-#ifdef HAVE_BLUA
 	// TODO give this its own section for Lua
-	&& LUA_HudEnabled(hud_nightsscore)
-#endif
-	)
+	if (!stplyr->exiting && LUA_HudEnabled(hud_nightsscore))
 	{
 		if (modeattacking == ATTACKING_NIGHTS)
 		{
@@ -2027,11 +1995,7 @@ static void ST_drawNiGHTSHUD(void)
 	}
 
 	// Ideya time remaining
-	if (!stplyr->exiting && stplyr->nightstime > 0
-#ifdef HAVE_BLUA
-	&& LUA_HudEnabled(hud_nightstime)
-#endif
-	)
+	if (!stplyr->exiting && stplyr->nightstime > 0 && LUA_HudEnabled(hud_nightstime))
 	{
 		INT32 realnightstime = stplyr->nightstime/TICRATE;
 		INT32 numbersize;
@@ -2122,10 +2086,8 @@ static void ST_drawNiGHTSHUD(void)
 		}
 
 		// Records/extra text
-#ifdef HAVE_BLUA
 		if (LUA_HudEnabled(hud_nightsrecords))
-#endif
-		ST_drawNightsRecords();
+			ST_drawNightsRecords();
 	}
 }
 
@@ -2403,20 +2365,16 @@ static void ST_drawTeamHUD(void)
 	else
 		p = bmatcico;
 
-#ifdef HAVE_BLUA
 	if (LUA_HudEnabled(hud_teamscores))
-#endif
-	V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p);
+		V_DrawSmallScaledPatch(BASEVIDWIDTH/2 - SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p);
 
 	if (gametyperules & GTR_TEAMFLAGS)
 		p = rflagico;
 	else
 		p = rmatcico;
 
-#ifdef HAVE_BLUA
 	if (LUA_HudEnabled(hud_teamscores))
-#endif
-	V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p);
+		V_DrawSmallScaledPatch(BASEVIDWIDTH/2 + SEP - SHORT(p->width)/4, 4, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, p);
 
 	if (!(gametyperules & GTR_TEAMFLAGS))
 		goto num;
@@ -2427,18 +2385,12 @@ static void ST_drawTeamHUD(void)
 		// Show which flags aren't at base.
 		for (i = 0; i < MAXPLAYERS; i++)
 		{
-			if (players[i].gotflag & GF_BLUEFLAG // Blue flag isn't at base
-#ifdef HAVE_BLUA
-			&& LUA_HudEnabled(hud_teamscores)
-#endif
-			)
+			// Blue flag isn't at base
+			if (players[i].gotflag & GF_BLUEFLAG && LUA_HudEnabled(hud_teamscores))
 				V_DrawScaledPatch(BASEVIDWIDTH/2 - SEP - SHORT(nonicon->width)/2, 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, nonicon);
 
-			if (players[i].gotflag & GF_REDFLAG // Red flag isn't at base
-#ifdef HAVE_BLUA
-			&& LUA_HudEnabled(hud_teamscores)
-#endif
-			)
+			// Red flag isn't at base
+			if (players[i].gotflag & GF_REDFLAG && LUA_HudEnabled(hud_teamscores))
 				V_DrawScaledPatch(BASEVIDWIDTH/2 + SEP - SHORT(nonicon2->width)/2, 0, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, nonicon2);
 
 			whichflag |= players[i].gotflag;
@@ -2449,32 +2401,20 @@ static void ST_drawTeamHUD(void)
 
 		// Display a countdown timer showing how much time left until the flag returns to base.
 		{
-			if (blueflag && blueflag->fuse > 1
-#ifdef HAVE_BLUA
-			&& LUA_HudEnabled(hud_teamscores)
-#endif
-			)
+			if (blueflag && blueflag->fuse > 1 && LUA_HudEnabled(hud_teamscores))
 				V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (blueflag->fuse / TICRATE)));
 
-			if (redflag && redflag->fuse > 1
-#ifdef HAVE_BLUA
-			&& LUA_HudEnabled(hud_teamscores)
-#endif
-			)
+			if (redflag && redflag->fuse > 1 && LUA_HudEnabled(hud_teamscores))
 				V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 8, V_YELLOWMAP|V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", (redflag->fuse / TICRATE)));
 		}
 	}
 
 num:
-#ifdef HAVE_BLUA
 	if (LUA_HudEnabled(hud_teamscores))
-#endif
-	V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", bluescore));
+		V_DrawCenteredString(BASEVIDWIDTH/2 - SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", bluescore));
 
-#ifdef HAVE_BLUA
 	if (LUA_HudEnabled(hud_teamscores))
-#endif
-	V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", redscore));
+		V_DrawCenteredString(BASEVIDWIDTH/2 + SEP, 16, V_HUDTRANS|V_PERPLAYER|V_SNAPTOTOP, va("%u", redscore));
 
 #undef SEP
 }
@@ -2661,24 +2601,14 @@ static void ST_overlayDrawer(void)
 			ST_drawNiGHTSHUD();
 		else
 		{
-#ifdef HAVE_BLUA
 			if (LUA_HudEnabled(hud_score))
-#endif
-			ST_drawScore();
-#ifdef HAVE_BLUA
+				ST_drawScore();
 			if (LUA_HudEnabled(hud_time))
-#endif
-			ST_drawTime();
-#ifdef HAVE_BLUA
+				ST_drawTime();
 			if (LUA_HudEnabled(hud_rings))
-#endif
-			ST_drawRings();
+				ST_drawRings();
 
-			if (!modeattacking
-#ifdef HAVE_BLUA
-			&& LUA_HudEnabled(hud_lives)
-#endif
-			)
+			if (!modeattacking && LUA_HudEnabled(hud_lives))
 				ST_drawLivesArea();
 		}
 	}
@@ -2753,11 +2683,7 @@ static void ST_overlayDrawer(void)
 		// Draw Match-related stuff
 		//\note Match HUD is drawn no matter what gametype.
 		// ... just not if you're a spectator.
-		if (!stplyr->spectator
-#ifdef HAVE_BLUA
-		&& (LUA_HudEnabled(hud_weaponrings))
-#endif
-		)
+		if (!stplyr->spectator && LUA_HudEnabled(hud_weaponrings))
 			ST_drawMatchHUD();
 
 		// Race HUD Stuff
@@ -2798,20 +2724,14 @@ static void ST_overlayDrawer(void)
 	else if (!(netgame || multiplayer) && cv_powerupdisplay.value == 2)
 		ST_drawPowerupHUD(); // same as it ever was...
 
-#ifdef HAVE_BLUA
 	if (!(netgame || multiplayer) || !hu_showscores)
 		LUAh_GameHUD(stplyr);
-#endif
 
 	// draw level title Tails
 	if (stagetitle && (!WipeInAction) && (!WipeStageTitle))
 		ST_drawTitleCard();
 
-	if (!hu_showscores && (netgame || multiplayer)
-#ifdef HAVE_BLUA
-		&& LUA_HudEnabled(hud_textspectator)
-#endif
-	)
+	if (!hu_showscores && (netgame || multiplayer) && LUA_HudEnabled(hud_textspectator))
 		ST_drawTextHUD();
 
 	if (modeattacking && !(demoplayback && hu_showscores))
diff --git a/src/w_wad.c b/src/w_wad.c
index e96afd050..f7ccc175b 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -189,7 +189,7 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors)
 static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum, boolean mainfile)
 {
 	UINT16 posStart, posEnd;
-#ifdef HAVE_BLUA
+
 	posStart = W_CheckNumForFolderStartPK3("Lua/", wadnum, 0);
 	if (posStart != INT16_MAX)
 	{
@@ -198,7 +198,7 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum, boolean mainfile)
 		for (; posStart < posEnd; posStart++)
 			LUA_LoadLump(wadnum, posStart);
 	}
-#endif
+
 	posStart = W_CheckNumForFolderStartPK3("SOC/", wadnum, 0);
 	if (posStart != INT16_MAX)
 	{
@@ -224,7 +224,6 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum, boolean mainfile)
 {
 	UINT16 lump;
 
-#ifdef HAVE_BLUA
 	// Find Lua scripts before SOCs to allow new A_Actions in SOC editing.
 	{
 		lumpinfo_t *lump_p = wadfiles[wadnum]->lumpinfo;
@@ -232,7 +231,6 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum, boolean mainfile)
 			if (memcmp(lump_p->name,"LUA_",4)==0)
 				LUA_LoadLump(wadnum, lump);
 	}
-#endif
 
 	{
 		lumpinfo_t *lump_p = wadfiles[wadnum]->lumpinfo;
@@ -749,11 +747,9 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
 	case RET_SOC:
 		lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "OBJCTCFG");
 		break;
-#ifdef HAVE_BLUA
 	case RET_LUA:
 		lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "LUA_INIT");
 		break;
-#endif
 	case RET_PK3:
 		lumpinfo = ResGetLumpsZip(handle, &numlumps);
 		break;
@@ -818,11 +814,9 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
 		CONS_Printf(M_GetText("Loading SOC from %s\n"), wadfile->filename);
 		DEH_LoadDehackedLumpPwad(numwadfiles - 1, 0, mainfile);
 		break;
-#ifdef HAVE_BLUA
 	case RET_LUA:
 		LUA_LoadLump(numwadfiles - 1, 0);
 		break;
-#endif
 	default:
 		break;
 	}
@@ -1860,10 +1854,7 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist,
 	{
 		// detect wad file by the absence of the other supported extensions
 		if (stricmp(&filename[strlen(filename) - 4], ".soc")
-#ifdef HAVE_BLUA
-		&& stricmp(&filename[strlen(filename) - 4], ".lua")
-#endif
-		)
+		&& stricmp(&filename[strlen(filename) - 4], ".lua"))
 		{
 			goodfile = W_VerifyWAD(handle, checklist, status);
 		}
diff --git a/src/win32/Srb2win-vc9.vcproj b/src/win32/Srb2win-vc9.vcproj
index a64b8638c..4c17bb6f7 100644
--- a/src/win32/Srb2win-vc9.vcproj
+++ b/src/win32/Srb2win-vc9.vcproj
@@ -55,7 +55,7 @@
 				Optimization="0"
 				OmitFramePointers="false"
 				AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
-				PreprocessorDefinitions="_DEBUG;_WINDOWS;USEASM;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
+				PreprocessorDefinitions="_DEBUG;_WINDOWS;USEASM;HAVE_PNG;COMPVERSION;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
 				MinimalRebuild="true"
 				RuntimeLibrary="1"
 				EnableFunctionLevelLinking="true"
@@ -153,7 +153,7 @@
 				Optimization="0"
 				OmitFramePointers="false"
 				AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
-				PreprocessorDefinitions="_DEBUG;_WINDOWS;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
+				PreprocessorDefinitions="_DEBUG;_WINDOWS;HAVE_PNG;COMPVERSION;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
 				MinimalRebuild="true"
 				BasicRuntimeChecks="3"
 				SmallerTypeCheck="true"
@@ -256,7 +256,7 @@
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
 				AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
-				PreprocessorDefinitions="NDEBUG;_WINDOWS;USEASM;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
+				PreprocessorDefinitions="NDEBUG;_WINDOWS;USEASM;HAVE_PNG;COMPVERSION;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
 				StringPooling="true"
 				RuntimeLibrary="0"
 				EnableFunctionLevelLinking="true"
@@ -356,7 +356,7 @@
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
 				AdditionalIncludeDirectories="&quot;$(ProjectDir)..\..\libs\libpng-src&quot;;&quot;$(ProjectDir)..\..\libs\zlib&quot;"
-				PreprocessorDefinitions="NDEBUG;_WINDOWS;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
+				PreprocessorDefinitions="NDEBUG;_WINDOWS;HAVE_PNG;COMPVERSION;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
 				StringPooling="true"
 				RuntimeLibrary="0"
 				EnableFunctionLevelLinking="true"
diff --git a/src/y_inter.c b/src/y_inter.c
index 6f23ef1b1..94a289817 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -37,9 +37,7 @@
 #include "m_cond.h" // condition sets
 #include "lua_hook.h" // IntermissionThinker hook
 
-#ifdef HAVE_BLUA
 #include "lua_hud.h"
-#endif
 
 #ifdef HWRENDER
 #include "hardware/hw_main.h"
@@ -330,9 +328,7 @@ void Y_IntermissionDrawer(void)
 
 	if (intertype == int_none)
 	{
-#ifdef HAVE_BLUA
 		LUAh_IntermissionHUD();
-#endif
 		return;
 	}
 
@@ -384,11 +380,9 @@ void Y_IntermissionDrawer(void)
 	else
 		V_DrawPatchFill(bgtile);
 
-#ifdef HAVE_BLUA
 	LUAh_IntermissionHUD();
 	if (!LUA_HudEnabled(hud_intermissiontally))
 		goto skiptallydrawer;
-#endif
 
 dontdrawbg:
 	if (intertype == int_coop)
@@ -944,11 +938,9 @@ dontdrawbg:
 		}
 	}
 
-#ifdef HAVE_BLUA
 skiptallydrawer:
 	if (!LUA_HudEnabled(hud_intermissionmessages))
 		return;
-#endif
 
 	if (timer)
 		V_DrawCenteredString(BASEVIDWIDTH/2, 188, V_YELLOWMAP,
@@ -973,9 +965,7 @@ void Y_Ticker(void)
 	if (paused || P_AutoPause())
 		return;
 
-#ifdef HAVE_BLUA
 	LUAh_IntermissionThinker();
-#endif
 
 	intertic++;
 
diff --git a/src/z_zone.c b/src/z_zone.c
index 67bc2b519..96dcd0cba 100644
--- a/src/z_zone.c
+++ b/src/z_zone.c
@@ -217,11 +217,9 @@ void Z_Free(void *ptr)
 	CONS_Debug(DBG_MEMORY, "Z_Free at %s:%d\n", file, line);
 #endif
 
-#ifdef HAVE_BLUA
 	// anything that isn't by lua gets passed to lua just in case.
 	if (block->tag != PU_LUA)
 		LUA_InvalidateUserdata(ptr);
-#endif
 
 	// TODO: if zdebugging, make sure no other block has a user
 	// that is about to be freed.

From a436ece941b9118565999b86eba97835a41fcc27 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Thu, 19 Mar 2020 19:26:46 +0100
Subject: [PATCH 126/251] Update CircleCI config

---
 .circleci/config.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.circleci/config.yml b/.circleci/config.yml
index 61e508e4d..8ecee2b19 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -51,8 +51,8 @@ jobs:
             - /var/cache/apt/archives
       - checkout
       - run:
-          name: Compile without network support and BLUA
-          command: make -C src LINUX=1 ERRORMODE=1 -k NONET=1 NO_LUA=1
+          name: Compile without network support
+          command: make -C src LINUX=1 ERRORMODE=1 -k NONET=1
       - run:
           name: wipe build
           command: make -C src LINUX=1 cleandep

From dcb4ce8cb99380ff5c474681ceb2de8f8ba8083e Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Thu, 19 Mar 2020 20:09:55 +0000
Subject: [PATCH 127/251] Created g_demo.c/.h, for the demo recording and
 playback code that formerly lived in g_game.c

---
 src/g_demo.c | 2501 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/g_demo.h |   85 ++
 src/g_game.c | 2500 +------------------------------------------------
 src/g_game.h |   65 +-
 4 files changed, 2607 insertions(+), 2544 deletions(-)
 create mode 100644 src/g_demo.c
 create mode 100644 src/g_demo.h

diff --git a/src/g_demo.c b/src/g_demo.c
new file mode 100644
index 000000000..22cd34ad5
--- /dev/null
+++ b/src/g_demo.c
@@ -0,0 +1,2501 @@
+// SONIC ROBO BLAST 2
+//-----------------------------------------------------------------------------
+// Copyright (C) 1993-1996 by id Software, Inc.
+// Copyright (C) 1998-2000 by DooM Legacy Team.
+// Copyright (C) 1999-2020 by Sonic Team Junior.
+//
+// This program is free software distributed under the
+// terms of the GNU General Public License, version 2.
+// See the 'LICENSE' file for more details.
+//-----------------------------------------------------------------------------
+/// \file  g_demo.c
+/// \brief Demo recording and playback
+
+#include "doomdef.h"
+#include "console.h"
+#include "d_main.h"
+#include "d_player.h"
+#include "d_clisrv.h"
+//#include "f_finale.h"
+#include "p_setup.h"
+#include "i_system.h"
+#include "m_random.h"
+#include "p_local.h"
+#include "r_draw.h"
+#include "r_main.h"
+//#include "s_sound.h"
+#include "g_game.h"
+#include "g_demo.h"
+#include "m_cheat.h"
+#include "m_misc.h"
+#include "m_menu.h"
+#include "m_argv.h"
+#include "hu_stuff.h"
+#include "z_zone.h"
+#include "i_video.h"
+#include "byteptr.h"
+#include "i_joy.h"
+#include "r_local.h"
+#include "r_skins.h"
+#include "y_inter.h"
+#include "v_video.h"
+#include "lua_hook.h"
+#include "md5.h" // demo checksums
+
+boolean timingdemo; // if true, exit with report on completion
+boolean nodrawers; // for comparative timing purposes
+boolean noblit; // for comparative timing purposes
+tic_t demostarttime; // for comparative timing purposes
+
+static char demoname[64];
+boolean demorecording;
+boolean demoplayback;
+boolean titledemo; // Title Screen demo can be cancelled by any key
+static UINT8 *demobuffer = NULL;
+static UINT8 *demo_p, *demotime_p;
+static UINT8 *demoend;
+static UINT8 demoflags;
+static UINT16 demoversion;
+boolean singledemo; // quit after playing a demo from cmdline
+boolean demo_start; // don't start playing demo right away
+boolean demosynced = true; // console warning message
+
+boolean metalrecording; // recording as metal sonic
+mobj_t *metalplayback;
+static UINT8 *metalbuffer = NULL;
+static UINT8 *metal_p;
+static UINT16 metalversion;
+
+// extra data stuff (events registered this frame while recording)
+static struct {
+	UINT8 flags; // EZT flags
+
+	// EZT_COLOR
+	UINT8 color, lastcolor;
+
+	// EZT_SCALE
+	fixed_t scale, lastscale;
+
+	// EZT_HIT
+	UINT16 hits;
+	mobj_t **hitlist;
+} ghostext;
+
+// Your naming conventions are stupid and useless.
+// There is no conflict here.
+typedef struct demoghost {
+	UINT8 checksum[16];
+	UINT8 *buffer, *p, color, fadein;
+	UINT16 version;
+	mobj_t oldmo, *mo;
+	struct demoghost *next;
+} demoghost;
+demoghost *ghosts = NULL;
+
+//
+// DEMO RECORDING
+//
+
+#define DEMOVERSION 0x000c
+#define DEMOHEADER  "\xF0" "SRB2Replay" "\x0F"
+
+#define DF_GHOST        0x01 // This demo contains ghost data too!
+#define DF_RECORDATTACK 0x02 // This demo is from record attack and contains its final completion time, score, and rings!
+#define DF_NIGHTSATTACK 0x04 // This demo is from NiGHTS attack and contains its time left, score, and mares!
+#define DF_ATTACKMASK   0x06 // This demo is from ??? attack and contains ???
+#define DF_ATTACKSHIFT  1
+
+// For demos
+#define ZT_FWD     0x01
+#define ZT_SIDE    0x02
+#define ZT_ANGLE   0x04
+#define ZT_BUTTONS 0x08
+#define ZT_AIMING  0x10
+#define DEMOMARKER 0x80 // demoend
+#define METALDEATH 0x44
+#define METALSNICE 0x69
+
+static ticcmd_t oldcmd;
+
+// For Metal Sonic and time attack ghosts
+#define GZT_XYZ    0x01
+#define GZT_MOMXY  0x02
+#define GZT_MOMZ   0x04
+#define GZT_ANGLE  0x08
+#define GZT_FRAME  0x10 // Animation frame
+#define GZT_SPR2   0x20 // Player animations
+#define GZT_EXTRA  0x40
+#define GZT_FOLLOW 0x80 // Followmobj
+
+// GZT_EXTRA flags
+#define EZT_THOK   0x01 // Spawned a thok object
+#define EZT_SPIN   0x02 // Because one type of thok object apparently wasn't enough
+#define EZT_REV    0x03 // And two types wasn't enough either yet
+#define EZT_THOKMASK 0x03
+#define EZT_COLOR  0x04 // Changed color (Super transformation, Mario fireflowers/invulnerability, etc.)
+#define EZT_FLIP   0x08 // Reversed gravity
+#define EZT_SCALE  0x10 // Changed size
+#define EZT_HIT    0x20 // Damaged a mobj
+#define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever)
+#define EZT_HEIGHT 0x80 // Changed height
+
+// GZT_FOLLOW flags
+#define FZT_SPAWNED 0x01 // just been spawned
+#define FZT_SKIN 0x02 // has skin
+#define FZT_LINKDRAW 0x04 // has linkdraw (combine with spawned only)
+#define FZT_COLORIZED 0x08 // colorized (ditto)
+#define FZT_SCALE 0x10 // different scale to object
+// spare FZT slots 0x20 to 0x80
+
+static mobj_t oldmetal, oldghost;
+
+void G_SaveMetal(UINT8 **buffer)
+{
+	I_Assert(buffer != NULL && *buffer != NULL);
+
+	WRITEUINT32(*buffer, metal_p - metalbuffer);
+}
+
+void G_LoadMetal(UINT8 **buffer)
+{
+	I_Assert(buffer != NULL && *buffer != NULL);
+
+	G_DoPlayMetal();
+	metal_p = metalbuffer + READUINT32(*buffer);
+}
+
+
+void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
+{
+	UINT8 ziptic;
+	(void)playernum;
+
+	if (!demo_p || !demo_start)
+		return;
+	ziptic = READUINT8(demo_p);
+
+	if (ziptic & ZT_FWD)
+		oldcmd.forwardmove = READSINT8(demo_p);
+	if (ziptic & ZT_SIDE)
+		oldcmd.sidemove = READSINT8(demo_p);
+	if (ziptic & ZT_ANGLE)
+		oldcmd.angleturn = READINT16(demo_p);
+	if (ziptic & ZT_BUTTONS)
+		oldcmd.buttons = (oldcmd.buttons & (BT_CAMLEFT|BT_CAMRIGHT)) | (READUINT16(demo_p) & ~(BT_CAMLEFT|BT_CAMRIGHT));
+	if (ziptic & ZT_AIMING)
+		oldcmd.aiming = READINT16(demo_p);
+
+	G_CopyTiccmd(cmd, &oldcmd, 1);
+
+	if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER)
+	{
+		// end of demo data stream
+		G_CheckDemoStatus();
+		return;
+	}
+}
+
+void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
+{
+	char ziptic = 0;
+	UINT8 *ziptic_p;
+	(void)playernum;
+
+	if (!demo_p)
+		return;
+	ziptic_p = demo_p++; // the ziptic, written at the end of this function
+
+	if (cmd->forwardmove != oldcmd.forwardmove)
+	{
+		WRITEUINT8(demo_p,cmd->forwardmove);
+		oldcmd.forwardmove = cmd->forwardmove;
+		ziptic |= ZT_FWD;
+	}
+
+	if (cmd->sidemove != oldcmd.sidemove)
+	{
+		WRITEUINT8(demo_p,cmd->sidemove);
+		oldcmd.sidemove = cmd->sidemove;
+		ziptic |= ZT_SIDE;
+	}
+
+	if (cmd->angleturn != oldcmd.angleturn)
+	{
+		WRITEINT16(demo_p,cmd->angleturn);
+		oldcmd.angleturn = cmd->angleturn;
+		ziptic |= ZT_ANGLE;
+	}
+
+	if (cmd->buttons != oldcmd.buttons)
+	{
+		WRITEUINT16(demo_p,cmd->buttons);
+		oldcmd.buttons = cmd->buttons;
+		ziptic |= ZT_BUTTONS;
+	}
+
+	if (cmd->aiming != oldcmd.aiming)
+	{
+		WRITEINT16(demo_p,cmd->aiming);
+		oldcmd.aiming = cmd->aiming;
+		ziptic |= ZT_AIMING;
+	}
+
+	*ziptic_p = ziptic;
+
+	// attention here for the ticcmd size!
+	// latest demos with mouse aiming byte in ticcmd
+	if (!(demoflags & DF_GHOST) && ziptic_p > demoend - 9)
+	{
+		G_CheckDemoStatus(); // no more space
+		return;
+	}
+}
+
+void G_GhostAddThok(void)
+{
+	if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
+		return;
+	ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_THOK;
+}
+
+void G_GhostAddSpin(void)
+{
+	if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
+		return;
+	ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_SPIN;
+}
+
+void G_GhostAddRev(void)
+{
+	if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
+		return;
+	ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_REV;
+}
+
+void G_GhostAddFlip(void)
+{
+	if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
+		return;
+	ghostext.flags |= EZT_FLIP;
+}
+
+void G_GhostAddColor(ghostcolor_t color)
+{
+	if (!demorecording || !(demoflags & DF_GHOST))
+		return;
+	if (ghostext.lastcolor == (UINT8)color)
+	{
+		ghostext.flags &= ~EZT_COLOR;
+		return;
+	}
+	ghostext.flags |= EZT_COLOR;
+	ghostext.color = (UINT8)color;
+}
+
+void G_GhostAddScale(fixed_t scale)
+{
+	if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
+		return;
+	if (ghostext.lastscale == scale)
+	{
+		ghostext.flags &= ~EZT_SCALE;
+		return;
+	}
+	ghostext.flags |= EZT_SCALE;
+	ghostext.scale = scale;
+}
+
+void G_GhostAddHit(mobj_t *victim)
+{
+	if (!demorecording || !(demoflags & DF_GHOST))
+		return;
+	ghostext.flags |= EZT_HIT;
+	ghostext.hits++;
+	ghostext.hitlist = Z_Realloc(ghostext.hitlist, ghostext.hits * sizeof(mobj_t *), PU_LEVEL, NULL);
+	ghostext.hitlist[ghostext.hits-1] = victim;
+}
+
+void G_WriteGhostTic(mobj_t *ghost)
+{
+	char ziptic = 0;
+	UINT8 *ziptic_p;
+	UINT32 i;
+	fixed_t height;
+
+	if (!demo_p)
+		return;
+	if (!(demoflags & DF_GHOST))
+		return; // No ghost data to write.
+
+	ziptic_p = demo_p++; // the ziptic, written at the end of this function
+
+	#define MAXMOM (0xFFFF<<8)
+
+	// GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic.
+	if (abs(ghost->x-oldghost.x) > MAXMOM
+	|| abs(ghost->y-oldghost.y) > MAXMOM
+	|| abs(ghost->z-oldghost.z) > MAXMOM)
+	{
+		oldghost.x = ghost->x;
+		oldghost.y = ghost->y;
+		oldghost.z = ghost->z;
+		ziptic |= GZT_XYZ;
+		WRITEFIXED(demo_p,oldghost.x);
+		WRITEFIXED(demo_p,oldghost.y);
+		WRITEFIXED(demo_p,oldghost.z);
+	}
+	else
+	{
+		// For moving normally:
+		// Store one full byte of movement, plus one byte of fractional movement.
+		INT16 momx = (INT16)((ghost->x-oldghost.x)>>8);
+		INT16 momy = (INT16)((ghost->y-oldghost.y)>>8);
+		if (momx != oldghost.momx
+		|| momy != oldghost.momy)
+		{
+			oldghost.momx = momx;
+			oldghost.momy = momy;
+			ziptic |= GZT_MOMXY;
+			WRITEINT16(demo_p,momx);
+			WRITEINT16(demo_p,momy);
+		}
+		momx = (INT16)((ghost->z-oldghost.z)>>8);
+		if (momx != oldghost.momz)
+		{
+			oldghost.momz = momx;
+			ziptic |= GZT_MOMZ;
+			WRITEINT16(demo_p,momx);
+		}
+
+		// This SHOULD set oldghost.x/y/z to match ghost->x/y/z
+		// but it keeps the fractional loss of one byte,
+		// so it will hopefully be made up for in future tics.
+		oldghost.x += oldghost.momx<<8;
+		oldghost.y += oldghost.momy<<8;
+		oldghost.z += oldghost.momz<<8;
+	}
+
+	#undef MAXMOM
+
+	// Only store the 8 most relevant bits of angle
+	// because exact values aren't too easy to discern to begin with when only 8 angles have different sprites
+	// and it does not affect this mode of movement at all anyway.
+	if (ghost->player && ghost->player->drawangle>>24 != oldghost.angle)
+	{
+		oldghost.angle = ghost->player->drawangle>>24;
+		ziptic |= GZT_ANGLE;
+		WRITEUINT8(demo_p,oldghost.angle);
+	}
+
+	// Store the sprite frame.
+	if ((ghost->frame & FF_FRAMEMASK) != oldghost.frame)
+	{
+		oldghost.frame = (ghost->frame & FF_FRAMEMASK);
+		ziptic |= GZT_FRAME;
+		WRITEUINT8(demo_p,oldghost.frame);
+	}
+
+	if (ghost->sprite == SPR_PLAY
+	&& ghost->sprite2 != oldghost.sprite2)
+	{
+		oldghost.sprite2 = ghost->sprite2;
+		ziptic |= GZT_SPR2;
+		WRITEUINT8(demo_p,oldghost.sprite2);
+	}
+
+	// Check for sprite set changes
+	if (ghost->sprite != oldghost.sprite)
+	{
+		oldghost.sprite = ghost->sprite;
+		ghostext.flags |= EZT_SPRITE;
+	}
+
+	if ((height = FixedDiv(ghost->height, ghost->scale)) != oldghost.height)
+	{
+		oldghost.height = height;
+		ghostext.flags |= EZT_HEIGHT;
+	}
+
+	if (ghostext.flags)
+	{
+		ziptic |= GZT_EXTRA;
+
+		if (ghostext.color == ghostext.lastcolor)
+			ghostext.flags &= ~EZT_COLOR;
+		if (ghostext.scale == ghostext.lastscale)
+			ghostext.flags &= ~EZT_SCALE;
+
+		WRITEUINT8(demo_p,ghostext.flags);
+		if (ghostext.flags & EZT_COLOR)
+		{
+			WRITEUINT8(demo_p,ghostext.color);
+			ghostext.lastcolor = ghostext.color;
+		}
+		if (ghostext.flags & EZT_SCALE)
+		{
+			WRITEFIXED(demo_p,ghostext.scale);
+			ghostext.lastscale = ghostext.scale;
+		}
+		if (ghostext.flags & EZT_HIT)
+		{
+			WRITEUINT16(demo_p,ghostext.hits);
+			for (i = 0; i < ghostext.hits; i++)
+			{
+				mobj_t *mo = ghostext.hitlist[i];
+				//WRITEUINT32(demo_p,UINT32_MAX); // reserved for some method of determining exactly which mobj this is. (mobjnum doesn't work here.)
+				WRITEUINT32(demo_p,mo->type);
+				WRITEUINT16(demo_p,(UINT16)mo->health);
+				WRITEFIXED(demo_p,mo->x);
+				WRITEFIXED(demo_p,mo->y);
+				WRITEFIXED(demo_p,mo->z);
+				WRITEANGLE(demo_p,mo->angle);
+			}
+			Z_Free(ghostext.hitlist);
+			ghostext.hits = 0;
+			ghostext.hitlist = NULL;
+		}
+		if (ghostext.flags & EZT_SPRITE)
+			WRITEUINT16(demo_p,oldghost.sprite);
+		if (ghostext.flags & EZT_HEIGHT)
+		{
+			height >>= FRACBITS;
+			WRITEINT16(demo_p, height);
+		}
+		ghostext.flags = 0;
+	}
+
+	if (ghost->player && ghost->player->followmobj && !(ghost->player->followmobj->sprite == SPR_NULL || (ghost->player->followmobj->flags2 & MF2_DONTDRAW))) // bloats tails runs but what can ya do
+	{
+		INT16 temp;
+		UINT8 *followtic_p = demo_p++;
+		UINT8 followtic = 0;
+
+		ziptic |= GZT_FOLLOW;
+
+		if (ghost->player->followmobj->skin)
+			followtic |= FZT_SKIN;
+
+		if (!(oldghost.flags2 & MF2_AMBUSH))
+		{
+			followtic |= FZT_SPAWNED;
+			WRITEINT16(demo_p,ghost->player->followmobj->info->height>>FRACBITS);
+			if (ghost->player->followmobj->flags2 & MF2_LINKDRAW)
+				followtic |= FZT_LINKDRAW;
+			if (ghost->player->followmobj->colorized)
+				followtic |= FZT_COLORIZED;
+			if (followtic & FZT_SKIN)
+				WRITEUINT8(demo_p,(UINT8)(((skin_t *)(ghost->player->followmobj->skin))-skins));
+			oldghost.flags2 |= MF2_AMBUSH;
+		}
+
+		if (ghost->player->followmobj->scale != ghost->scale)
+		{
+			followtic |= FZT_SCALE;
+			WRITEFIXED(demo_p,ghost->player->followmobj->scale);
+		}
+
+		temp = (INT16)((ghost->player->followmobj->x-ghost->x)>>8);
+		WRITEINT16(demo_p,temp);
+		temp = (INT16)((ghost->player->followmobj->y-ghost->y)>>8);
+		WRITEINT16(demo_p,temp);
+		temp = (INT16)((ghost->player->followmobj->z-ghost->z)>>8);
+		WRITEINT16(demo_p,temp);
+		if (followtic & FZT_SKIN)
+			WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
+		WRITEUINT16(demo_p,ghost->player->followmobj->sprite);
+		WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK));
+		WRITEUINT8(demo_p,ghost->player->followmobj->color);
+
+		*followtic_p = followtic;
+	}
+	else
+		oldghost.flags2 &= ~MF2_AMBUSH;
+
+	*ziptic_p = ziptic;
+
+	// attention here for the ticcmd size!
+	// latest demos with mouse aiming byte in ticcmd
+	if (demo_p >= demoend - (13 + 9 + 9))
+	{
+		G_CheckDemoStatus(); // no more space
+		return;
+	}
+}
+
+// Uses ghost data to do consistency checks on your position.
+// This fixes desynchronising demos when fighting eggman.
+void G_ConsGhostTic(void)
+{
+	UINT8 ziptic;
+	UINT16 px,py,pz,gx,gy,gz;
+	mobj_t *testmo;
+
+	if (!demo_p || !demo_start)
+		return;
+	if (!(demoflags & DF_GHOST))
+		return; // No ghost data to use.
+
+	testmo = players[0].mo;
+
+	// Grab ghost data.
+	ziptic = READUINT8(demo_p);
+	if (ziptic & GZT_XYZ)
+	{
+		oldghost.x = READFIXED(demo_p);
+		oldghost.y = READFIXED(demo_p);
+		oldghost.z = READFIXED(demo_p);
+	}
+	else
+	{
+		if (ziptic & GZT_MOMXY)
+		{
+			oldghost.momx = READINT16(demo_p)<<8;
+			oldghost.momy = READINT16(demo_p)<<8;
+		}
+		if (ziptic & GZT_MOMZ)
+			oldghost.momz = READINT16(demo_p)<<8;
+		oldghost.x += oldghost.momx;
+		oldghost.y += oldghost.momy;
+		oldghost.z += oldghost.momz;
+	}
+	if (ziptic & GZT_ANGLE)
+		demo_p++;
+	if (ziptic & GZT_FRAME)
+		demo_p++;
+	if (ziptic & GZT_SPR2)
+		demo_p++;
+
+	if (ziptic & GZT_EXTRA)
+	{ // But wait, there's more!
+		UINT8 xziptic = READUINT8(demo_p);
+		if (xziptic & EZT_COLOR)
+			demo_p++;
+		if (xziptic & EZT_SCALE)
+			demo_p += sizeof(fixed_t);
+		if (xziptic & EZT_HIT)
+		{ // Resync mob damage.
+			UINT16 i, count = READUINT16(demo_p);
+			thinker_t *th;
+			mobj_t *mobj;
+
+			UINT32 type;
+			UINT16 health;
+			fixed_t x;
+			fixed_t y;
+			fixed_t z;
+
+			for (i = 0; i < count; i++)
+			{
+				//demo_p += 4; // reserved.
+				type = READUINT32(demo_p);
+				health = READUINT16(demo_p);
+				x = READFIXED(demo_p);
+				y = READFIXED(demo_p);
+				z = READFIXED(demo_p);
+				demo_p += sizeof(angle_t); // angle, unnecessary for cons.
+
+				mobj = NULL;
+				for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
+				{
+					if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
+						continue;
+					mobj = (mobj_t *)th;
+					if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z)
+						break;
+				}
+				if (th != &thlist[THINK_MOBJ] && mobj->health != health) // Wasn't damaged?! This is desync! Fix it!
+				{
+					if (demosynced)
+						CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
+					demosynced = false;
+					P_DamageMobj(mobj, players[0].mo, players[0].mo, 1, 0);
+				}
+			}
+		}
+		if (xziptic & EZT_SPRITE)
+			demo_p += sizeof(UINT16);
+		if (xziptic & EZT_HEIGHT)
+			demo_p += sizeof(INT16);
+	}
+
+	if (ziptic & GZT_FOLLOW)
+	{ // Even more...
+		UINT8 followtic = READUINT8(demo_p);
+		if (followtic & FZT_SPAWNED)
+		{
+			demo_p += sizeof(INT16);
+			if (followtic & FZT_SKIN)
+				demo_p++;
+		}
+		if (followtic & FZT_SCALE)
+			demo_p += sizeof(fixed_t);
+		demo_p += sizeof(INT16);
+		demo_p += sizeof(INT16);
+		demo_p += sizeof(INT16);
+		if (followtic & FZT_SKIN)
+			demo_p++;
+		demo_p += sizeof(UINT16);
+		demo_p++;
+		demo_p++;
+	}
+
+	// Re-synchronise
+	px = testmo->x>>FRACBITS;
+	py = testmo->y>>FRACBITS;
+	pz = testmo->z>>FRACBITS;
+	gx = oldghost.x>>FRACBITS;
+	gy = oldghost.y>>FRACBITS;
+	gz = oldghost.z>>FRACBITS;
+
+	if (px != gx || py != gy || pz != gz)
+	{
+		if (demosynced)
+			CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
+		demosynced = false;
+
+		P_UnsetThingPosition(testmo);
+		testmo->x = oldghost.x;
+		testmo->y = oldghost.y;
+		P_SetThingPosition(testmo);
+		testmo->z = oldghost.z;
+	}
+
+	if (*demo_p == DEMOMARKER)
+	{
+		// end of demo data stream
+		G_CheckDemoStatus();
+		return;
+	}
+}
+
+void G_GhostTicker(void)
+{
+	demoghost *g,*p;
+	for(g = ghosts, p = NULL; g; g = g->next)
+	{
+		// Skip normal demo data.
+		UINT8 ziptic = READUINT8(g->p);
+		UINT8 xziptic = 0;
+		if (ziptic & ZT_FWD)
+			g->p++;
+		if (ziptic & ZT_SIDE)
+			g->p++;
+		if (ziptic & ZT_ANGLE)
+			g->p += 2;
+		if (ziptic & ZT_BUTTONS)
+			g->p += 2;
+		if (ziptic & ZT_AIMING)
+			g->p += 2;
+
+		// Grab ghost data.
+		ziptic = READUINT8(g->p);
+		if (ziptic & GZT_XYZ)
+		{
+			g->oldmo.x = READFIXED(g->p);
+			g->oldmo.y = READFIXED(g->p);
+			g->oldmo.z = READFIXED(g->p);
+		}
+		else
+		{
+			if (ziptic & GZT_MOMXY)
+			{
+				g->oldmo.momx = READINT16(g->p)<<8;
+				g->oldmo.momy = READINT16(g->p)<<8;
+			}
+			if (ziptic & GZT_MOMZ)
+				g->oldmo.momz = READINT16(g->p)<<8;
+			g->oldmo.x += g->oldmo.momx;
+			g->oldmo.y += g->oldmo.momy;
+			g->oldmo.z += g->oldmo.momz;
+		}
+		if (ziptic & GZT_ANGLE)
+			g->mo->angle = READUINT8(g->p)<<24;
+		if (ziptic & GZT_FRAME)
+			g->oldmo.frame = READUINT8(g->p);
+		if (ziptic & GZT_SPR2)
+			g->oldmo.sprite2 = READUINT8(g->p);
+
+		// Update ghost
+		P_UnsetThingPosition(g->mo);
+		g->mo->x = g->oldmo.x;
+		g->mo->y = g->oldmo.y;
+		g->mo->z = g->oldmo.z;
+		P_SetThingPosition(g->mo);
+		g->mo->frame = g->oldmo.frame | tr_trans30<<FF_TRANSSHIFT;
+		if (g->fadein)
+		{
+			g->mo->frame += (((--g->fadein)/6)<<FF_TRANSSHIFT); // this calc never exceeds 9 unless g->fadein is bad, and it's only set once, so...
+			g->mo->flags2 &= ~MF2_DONTDRAW;
+		}
+		g->mo->sprite2 = g->oldmo.sprite2;
+
+		if (ziptic & GZT_EXTRA)
+		{ // But wait, there's more!
+			xziptic = READUINT8(g->p);
+			if (xziptic & EZT_COLOR)
+			{
+				g->color = READUINT8(g->p);
+				switch(g->color)
+				{
+				default:
+				case GHC_RETURNSKIN:
+					g->mo->skin = g->oldmo.skin;
+					/* FALLTHRU */
+				case GHC_NORMAL: // Go back to skin color
+					g->mo->color = g->oldmo.color;
+					break;
+				// Handled below
+				case GHC_SUPER:
+				case GHC_INVINCIBLE:
+					break;
+				case GHC_FIREFLOWER: // Fireflower
+					g->mo->color = SKINCOLOR_WHITE;
+					break;
+				case GHC_NIGHTSSKIN: // not actually a colour
+					g->mo->skin = &skins[DEFAULTNIGHTSSKIN];
+					break;
+				}
+			}
+			if (xziptic & EZT_FLIP)
+				g->mo->eflags ^= MFE_VERTICALFLIP;
+			if (xziptic & EZT_SCALE)
+			{
+				g->mo->destscale = READFIXED(g->p);
+				if (g->mo->destscale != g->mo->scale)
+					P_SetScale(g->mo, g->mo->destscale);
+			}
+			if (xziptic & EZT_THOKMASK)
+			{ // Let's only spawn ONE of these per frame, thanks.
+				mobj_t *mobj;
+				INT32 type = -1;
+				if (g->mo->skin)
+				{
+					skin_t *skin = (skin_t *)g->mo->skin;
+					switch (xziptic & EZT_THOKMASK)
+					{
+					case EZT_THOK:
+						type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem;
+						break;
+					case EZT_SPIN:
+						type = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem;
+						break;
+					case EZT_REV:
+						type = skin->revitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem;
+						break;
+					}
+				}
+				if (type != MT_NULL)
+				{
+					if (type == MT_GHOST)
+					{
+						mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
+						mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
+					}
+					else
+					{
+						mobj = P_SpawnMobjFromMobj(g->mo, 0, 0, -FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
+						mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
+						mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
+						mobj->color = g->mo->color;
+						mobj->skin = g->mo->skin;
+						P_SetScale(mobj, (mobj->destscale = g->mo->scale));
+
+						if (type == MT_THOK) // spintrail-specific modification for MT_THOK
+						{
+							mobj->frame = FF_TRANS80;
+							mobj->fuse = mobj->tics;
+						}
+						mobj->tics = -1; // nope.
+					}
+					mobj->floorz = mobj->z;
+					mobj->ceilingz = mobj->z+mobj->height;
+					P_UnsetThingPosition(mobj);
+					mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
+					P_SetThingPosition(mobj);
+					if (!mobj->fuse)
+						mobj->fuse = 8;
+					P_SetTarget(&mobj->target, g->mo);
+				}
+			}
+			if (xziptic & EZT_HIT)
+			{ // Spawn hit poofs for killing things!
+				UINT16 i, count = READUINT16(g->p), health;
+				UINT32 type;
+				fixed_t x,y,z;
+				angle_t angle;
+				mobj_t *poof;
+				for (i = 0; i < count; i++)
+				{
+					//g->p += 4; // reserved
+					type = READUINT32(g->p);
+					health = READUINT16(g->p);
+					x = READFIXED(g->p);
+					y = READFIXED(g->p);
+					z = READFIXED(g->p);
+					angle = READANGLE(g->p);
+					if (!(mobjinfo[type].flags & MF_SHOOTABLE)
+					|| !(mobjinfo[type].flags & (MF_ENEMY|MF_MONITOR))
+					|| health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad.
+						continue;
+					poof = P_SpawnMobj(x, y, z, MT_GHOST);
+					poof->angle = angle;
+					poof->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
+					poof->health = 0;
+					P_SetMobjStateNF(poof, S_XPLD1);
+				}
+			}
+			if (xziptic & EZT_SPRITE)
+				g->mo->sprite = READUINT16(g->p);
+			if (xziptic & EZT_HEIGHT)
+			{
+				fixed_t temp = READINT16(g->p)<<FRACBITS;
+				g->mo->height = FixedMul(temp, g->mo->scale);
+			}
+		}
+
+		// Tick ghost colors (Super and Mario Invincibility flashing)
+		switch(g->color)
+		{
+		case GHC_SUPER: // Super (P_DoSuperStuff)
+			if (g->mo->skin)
+			{
+				skin_t *skin = (skin_t *)g->mo->skin;
+				g->mo->color = skin->supercolor;
+			}
+			else
+				g->mo->color = SKINCOLOR_SUPERGOLD1;
+			g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4);
+			break;
+		case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
+			g->mo->color = (UINT8)(SKINCOLOR_RUBY + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RUBY))); // Passes through all saturated colours
+			break;
+		default:
+			break;
+		}
+
+#define follow g->mo->tracer
+		if (ziptic & GZT_FOLLOW)
+		{ // Even more...
+			UINT8 followtic = READUINT8(g->p);
+			fixed_t temp;
+			if (followtic & FZT_SPAWNED)
+			{
+				if (follow)
+					P_RemoveMobj(follow);
+				P_SetTarget(&follow, P_SpawnMobjFromMobj(g->mo, 0, 0, 0, MT_GHOST));
+				P_SetTarget(&follow->tracer, g->mo);
+				follow->tics = -1;
+				temp = READINT16(g->p)<<FRACBITS;
+				follow->height = FixedMul(follow->scale, temp);
+
+				if (followtic & FZT_LINKDRAW)
+					follow->flags2 |= MF2_LINKDRAW;
+
+				if (followtic & FZT_COLORIZED)
+					follow->colorized = true;
+
+				if (followtic & FZT_SKIN)
+					follow->skin = &skins[READUINT8(g->p)];
+			}
+			if (follow)
+			{
+				if (followtic & FZT_SCALE)
+					follow->destscale = READFIXED(g->p);
+				else
+					follow->destscale = g->mo->destscale;
+				if (follow->destscale != follow->scale)
+					P_SetScale(follow, follow->destscale);
+
+				P_UnsetThingPosition(follow);
+				temp = READINT16(g->p)<<8;
+				follow->x = g->mo->x + temp;
+				temp = READINT16(g->p)<<8;
+				follow->y = g->mo->y + temp;
+				temp = READINT16(g->p)<<8;
+				follow->z = g->mo->z + temp;
+				P_SetThingPosition(follow);
+				if (followtic & FZT_SKIN)
+					follow->sprite2 = READUINT8(g->p);
+				else
+					follow->sprite2 = 0;
+				follow->sprite = READUINT16(g->p);
+				follow->frame = (READUINT8(g->p)) | (g->mo->frame & FF_TRANSMASK);
+				follow->angle = g->mo->angle;
+				follow->color = READUINT8(g->p);
+
+				if (!(followtic & FZT_SPAWNED))
+				{
+					if (xziptic & EZT_FLIP)
+					{
+						follow->flags2 ^= MF2_OBJECTFLIP;
+						follow->eflags ^= MFE_VERTICALFLIP;
+					}
+				}
+			}
+		}
+		else if (follow)
+		{
+			P_RemoveMobj(follow);
+			P_SetTarget(&follow, NULL);
+		}
+		// Demo ends after ghost data.
+		if (*g->p == DEMOMARKER)
+		{
+			g->mo->momx = g->mo->momy = g->mo->momz = 0;
+#if 1 // freeze frame (maybe more useful for time attackers)
+			g->mo->colorized = true;
+			if (follow)
+				follow->colorized = true;
+#else // dissapearing act
+			g->mo->fuse = TICRATE;
+			if (follow)
+				follow->fuse = TICRATE;
+#endif
+			if (p)
+				p->next = g->next;
+			else
+				ghosts = g->next;
+			Z_Free(g);
+			continue;
+		}
+		p = g;
+#undef follow
+	}
+}
+
+void G_ReadMetalTic(mobj_t *metal)
+{
+	UINT8 ziptic;
+	UINT8 xziptic = 0;
+
+	if (!metal_p)
+		return;
+
+	if (!metal->health)
+	{
+		G_StopMetalDemo();
+		return;
+	}
+
+	switch (*metal_p)
+	{
+		case METALSNICE:
+			break;
+		case METALDEATH:
+			if (metal->tracer)
+				P_RemoveMobj(metal->tracer);
+			P_KillMobj(metal, NULL, NULL, 0);
+			/* FALLTHRU */
+		case DEMOMARKER:
+		default:
+			// end of demo data stream
+			G_StopMetalDemo();
+			return;
+	}
+	metal_p++;
+
+	ziptic = READUINT8(metal_p);
+
+	// Read changes from the tic
+	if (ziptic & GZT_XYZ)
+	{
+		P_TeleportMove(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p));
+		oldmetal.x = metal->x;
+		oldmetal.y = metal->y;
+		oldmetal.z = metal->z;
+	}
+	else
+	{
+		if (ziptic & GZT_MOMXY)
+		{
+			oldmetal.momx = READINT16(metal_p)<<8;
+			oldmetal.momy = READINT16(metal_p)<<8;
+		}
+		if (ziptic & GZT_MOMZ)
+			oldmetal.momz = READINT16(metal_p)<<8;
+		oldmetal.x += oldmetal.momx;
+		oldmetal.y += oldmetal.momy;
+		oldmetal.z += oldmetal.momz;
+	}
+	if (ziptic & GZT_ANGLE)
+		metal->angle = READUINT8(metal_p)<<24;
+	if (ziptic & GZT_FRAME)
+		oldmetal.frame = READUINT32(metal_p);
+	if (ziptic & GZT_SPR2)
+		oldmetal.sprite2 = READUINT8(metal_p);
+
+	// Set movement, position, and angle
+	// oldmetal contains where you're supposed to be.
+	metal->momx = oldmetal.momx;
+	metal->momy = oldmetal.momy;
+	metal->momz = oldmetal.momz;
+	P_UnsetThingPosition(metal);
+	metal->x = oldmetal.x;
+	metal->y = oldmetal.y;
+	metal->z = oldmetal.z;
+	P_SetThingPosition(metal);
+	metal->frame = oldmetal.frame;
+	metal->sprite2 = oldmetal.sprite2;
+
+	if (ziptic & GZT_EXTRA)
+	{ // But wait, there's more!
+		xziptic = READUINT8(metal_p);
+		if (xziptic & EZT_FLIP)
+		{
+			metal->eflags ^= MFE_VERTICALFLIP;
+			metal->flags2 ^= MF2_OBJECTFLIP;
+		}
+		if (xziptic & EZT_SCALE)
+		{
+			metal->destscale = READFIXED(metal_p);
+			if (metal->destscale != metal->scale)
+				P_SetScale(metal, metal->destscale);
+		}
+		if (xziptic & EZT_THOKMASK)
+		{ // Let's only spawn ONE of these per frame, thanks.
+			mobj_t *mobj;
+			INT32 type = -1;
+			if (metal->skin)
+			{
+				skin_t *skin = (skin_t *)metal->skin;
+				switch (xziptic & EZT_THOKMASK)
+				{
+				case EZT_THOK:
+					type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem;
+					break;
+				case EZT_SPIN:
+					type = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem;
+					break;
+				case EZT_REV:
+					type = skin->revitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem;
+					break;
+				}
+			}
+			if (type != MT_NULL)
+			{
+				if (type == MT_GHOST)
+				{
+					mobj = P_SpawnGhostMobj(metal); // does a large portion of the work for us
+				}
+				else
+				{
+					mobj = P_SpawnMobjFromMobj(metal, 0, 0, -FixedDiv(FixedMul(metal->info->height, metal->scale) - metal->height,3*FRACUNIT), MT_THOK);
+					mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
+					mobj->frame = states[mobjinfo[type].spawnstate].frame;
+					mobj->angle = metal->angle;
+					mobj->color = metal->color;
+					mobj->skin = metal->skin;
+					P_SetScale(mobj, (mobj->destscale = metal->scale));
+
+					if (type == MT_THOK) // spintrail-specific modification for MT_THOK
+					{
+						mobj->frame = FF_TRANS70;
+						mobj->fuse = mobj->tics;
+					}
+					mobj->tics = -1; // nope.
+				}
+				mobj->floorz = mobj->z;
+				mobj->ceilingz = mobj->z+mobj->height;
+				P_UnsetThingPosition(mobj);
+				mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
+				P_SetThingPosition(mobj);
+				if (!mobj->fuse)
+					mobj->fuse = 8;
+				P_SetTarget(&mobj->target, metal);
+			}
+		}
+		if (xziptic & EZT_SPRITE)
+			metal->sprite = READUINT16(metal_p);
+		if (xziptic & EZT_HEIGHT)
+		{
+			fixed_t temp = READINT16(metal_p)<<FRACBITS;
+			metal->height = FixedMul(temp, metal->scale);
+		}
+	}
+
+#define follow metal->tracer
+		if (ziptic & GZT_FOLLOW)
+		{ // Even more...
+			UINT8 followtic = READUINT8(metal_p);
+			fixed_t temp;
+			if (followtic & FZT_SPAWNED)
+			{
+				if (follow)
+					P_RemoveMobj(follow);
+				P_SetTarget(&follow, P_SpawnMobjFromMobj(metal, 0, 0, 0, MT_GHOST));
+				P_SetTarget(&follow->tracer, metal);
+				follow->tics = -1;
+				temp = READINT16(metal_p)<<FRACBITS;
+				follow->height = FixedMul(follow->scale, temp);
+
+				if (followtic & FZT_LINKDRAW)
+					follow->flags2 |= MF2_LINKDRAW;
+
+				if (followtic & FZT_COLORIZED)
+					follow->colorized = true;
+
+				if (followtic & FZT_SKIN)
+					follow->skin = &skins[READUINT8(metal_p)];
+			}
+			if (follow)
+			{
+				if (followtic & FZT_SCALE)
+					follow->destscale = READFIXED(metal_p);
+				else
+					follow->destscale = metal->destscale;
+				if (follow->destscale != follow->scale)
+					P_SetScale(follow, follow->destscale);
+
+				P_UnsetThingPosition(follow);
+				temp = READINT16(metal_p)<<8;
+				follow->x = metal->x + temp;
+				temp = READINT16(metal_p)<<8;
+				follow->y = metal->y + temp;
+				temp = READINT16(metal_p)<<8;
+				follow->z = metal->z + temp;
+				P_SetThingPosition(follow);
+				if (followtic & FZT_SKIN)
+					follow->sprite2 = READUINT8(metal_p);
+				else
+					follow->sprite2 = 0;
+				follow->sprite = READUINT16(metal_p);
+				follow->frame = READUINT32(metal_p); // NOT & FF_FRAMEMASK here, so 32 bits
+				follow->angle = metal->angle;
+				follow->color = READUINT8(metal_p);
+
+				if (!(followtic & FZT_SPAWNED))
+				{
+					if (xziptic & EZT_FLIP)
+					{
+						follow->flags2 ^= MF2_OBJECTFLIP;
+						follow->eflags ^= MFE_VERTICALFLIP;
+					}
+				}
+			}
+		}
+		else if (follow)
+		{
+			P_RemoveMobj(follow);
+			P_SetTarget(&follow, NULL);
+		}
+#undef follow
+}
+
+void G_WriteMetalTic(mobj_t *metal)
+{
+	UINT8 ziptic = 0;
+	UINT8 *ziptic_p;
+	fixed_t height;
+
+	if (!demo_p) // demo_p will be NULL until the race start linedef executor is activated!
+		return;
+
+	WRITEUINT8(demo_p, METALSNICE);
+	ziptic_p = demo_p++; // the ziptic, written at the end of this function
+
+	#define MAXMOM (0xFFFF<<8)
+
+	// GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic.
+	if (abs(metal->x-oldmetal.x) > MAXMOM
+	|| abs(metal->y-oldmetal.y) > MAXMOM
+	|| abs(metal->z-oldmetal.z) > MAXMOM)
+	{
+		oldmetal.x = metal->x;
+		oldmetal.y = metal->y;
+		oldmetal.z = metal->z;
+		ziptic |= GZT_XYZ;
+		WRITEFIXED(demo_p,oldmetal.x);
+		WRITEFIXED(demo_p,oldmetal.y);
+		WRITEFIXED(demo_p,oldmetal.z);
+	}
+	else
+	{
+		// For moving normally:
+		// Store one full byte of movement, plus one byte of fractional movement.
+		INT16 momx = (INT16)((metal->x-oldmetal.x)>>8);
+		INT16 momy = (INT16)((metal->y-oldmetal.y)>>8);
+		if (momx != oldmetal.momx
+		|| momy != oldmetal.momy)
+		{
+			oldmetal.momx = momx;
+			oldmetal.momy = momy;
+			ziptic |= GZT_MOMXY;
+			WRITEINT16(demo_p,momx);
+			WRITEINT16(demo_p,momy);
+		}
+		momx = (INT16)((metal->z-oldmetal.z)>>8);
+		if (momx != oldmetal.momz)
+		{
+			oldmetal.momz = momx;
+			ziptic |= GZT_MOMZ;
+			WRITEINT16(demo_p,momx);
+		}
+
+		// This SHOULD set oldmetal.x/y/z to match metal->x/y/z
+		// but it keeps the fractional loss of one byte,
+		// so it will hopefully be made up for in future tics.
+		oldmetal.x += oldmetal.momx<<8;
+		oldmetal.y += oldmetal.momy<<8;
+		oldmetal.z += oldmetal.momz<<8;
+	}
+
+	#undef MAXMOM
+
+	// Only store the 8 most relevant bits of angle
+	// because exact values aren't too easy to discern to begin with when only 8 angles have different sprites
+	// and it does not affect movement at all anyway.
+	if (metal->player && metal->player->drawangle>>24 != oldmetal.angle)
+	{
+		oldmetal.angle = metal->player->drawangle>>24;
+		ziptic |= GZT_ANGLE;
+		WRITEUINT8(demo_p,oldmetal.angle);
+	}
+
+	// Store the sprite frame.
+	if ((metal->frame & FF_FRAMEMASK) != oldmetal.frame)
+	{
+		oldmetal.frame = metal->frame; // NOT & FF_FRAMEMASK here, so 32 bits
+		ziptic |= GZT_FRAME;
+		WRITEUINT32(demo_p,oldmetal.frame);
+	}
+
+	if (metal->sprite == SPR_PLAY
+	&& metal->sprite2 != oldmetal.sprite2)
+	{
+		oldmetal.sprite2 = metal->sprite2;
+		ziptic |= GZT_SPR2;
+		WRITEUINT8(demo_p,oldmetal.sprite2);
+	}
+
+	// Check for sprite set changes
+	if (metal->sprite != oldmetal.sprite)
+	{
+		oldmetal.sprite = metal->sprite;
+		ghostext.flags |= EZT_SPRITE;
+	}
+
+	if ((height = FixedDiv(metal->height, metal->scale)) != oldmetal.height)
+	{
+		oldmetal.height = height;
+		ghostext.flags |= EZT_HEIGHT;
+	}
+
+	if (ghostext.flags & ~(EZT_COLOR|EZT_HIT)) // these two aren't handled by metal ever
+	{
+		ziptic |= GZT_EXTRA;
+
+		if (ghostext.scale == ghostext.lastscale)
+			ghostext.flags &= ~EZT_SCALE;
+
+		WRITEUINT8(demo_p,ghostext.flags);
+		if (ghostext.flags & EZT_SCALE)
+		{
+			WRITEFIXED(demo_p,ghostext.scale);
+			ghostext.lastscale = ghostext.scale;
+		}
+		if (ghostext.flags & EZT_SPRITE)
+			WRITEUINT16(demo_p,oldmetal.sprite);
+		if (ghostext.flags & EZT_HEIGHT)
+		{
+			height >>= FRACBITS;
+			WRITEINT16(demo_p, height);
+		}
+		ghostext.flags = 0;
+	}
+
+	if (metal->player && metal->player->followmobj && !(metal->player->followmobj->sprite == SPR_NULL || (metal->player->followmobj->flags2 & MF2_DONTDRAW)))
+	{
+		INT16 temp;
+		UINT8 *followtic_p = demo_p++;
+		UINT8 followtic = 0;
+
+		ziptic |= GZT_FOLLOW;
+
+		if (metal->player->followmobj->skin)
+			followtic |= FZT_SKIN;
+
+		if (!(oldmetal.flags2 & MF2_AMBUSH))
+		{
+			followtic |= FZT_SPAWNED;
+			WRITEINT16(demo_p,metal->player->followmobj->info->height>>FRACBITS);
+			if (metal->player->followmobj->flags2 & MF2_LINKDRAW)
+				followtic |= FZT_LINKDRAW;
+			if (metal->player->followmobj->colorized)
+				followtic |= FZT_COLORIZED;
+			if (followtic & FZT_SKIN)
+				WRITEUINT8(demo_p,(UINT8)(((skin_t *)(metal->player->followmobj->skin))-skins));
+			oldmetal.flags2 |= MF2_AMBUSH;
+		}
+
+		if (metal->player->followmobj->scale != metal->scale)
+		{
+			followtic |= FZT_SCALE;
+			WRITEFIXED(demo_p,metal->player->followmobj->scale);
+		}
+
+		temp = (INT16)((metal->player->followmobj->x-metal->x)>>8);
+		WRITEINT16(demo_p,temp);
+		temp = (INT16)((metal->player->followmobj->y-metal->y)>>8);
+		WRITEINT16(demo_p,temp);
+		temp = (INT16)((metal->player->followmobj->z-metal->z)>>8);
+		WRITEINT16(demo_p,temp);
+		if (followtic & FZT_SKIN)
+			WRITEUINT8(demo_p,metal->player->followmobj->sprite2);
+		WRITEUINT16(demo_p,metal->player->followmobj->sprite);
+		WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits
+		WRITEUINT8(demo_p,metal->player->followmobj->color);
+
+		*followtic_p = followtic;
+	}
+	else
+		oldmetal.flags2 &= ~MF2_AMBUSH;
+
+	*ziptic_p = ziptic;
+
+	// attention here for the ticcmd size!
+	// latest demos with mouse aiming byte in ticcmd
+	if (demo_p >= demoend - 32)
+	{
+		G_StopMetalRecording(false); // no more space
+		return;
+	}
+}
+
+//
+// G_RecordDemo
+//
+void G_RecordDemo(const char *name)
+{
+	INT32 maxsize;
+
+	strcpy(demoname, name);
+	strcat(demoname, ".lmp");
+	maxsize = 1024*1024;
+	if (M_CheckParm("-maxdemo") && M_IsNextParm())
+		maxsize = atoi(M_GetNextParm()) * 1024;
+//	if (demobuffer)
+//		free(demobuffer);
+	demo_p = NULL;
+	demobuffer = malloc(maxsize);
+	demoend = demobuffer + maxsize;
+
+	demorecording = true;
+}
+
+void G_RecordMetal(void)
+{
+	INT32 maxsize;
+	maxsize = 1024*1024;
+	if (M_CheckParm("-maxdemo") && M_IsNextParm())
+		maxsize = atoi(M_GetNextParm()) * 1024;
+	demo_p = NULL;
+	demobuffer = malloc(maxsize);
+	demoend = demobuffer + maxsize;
+	metalrecording = true;
+}
+
+void G_BeginRecording(void)
+{
+	UINT8 i;
+	char name[16];
+	player_t *player = &players[consoleplayer];
+
+	if (demo_p)
+		return;
+	memset(name,0,sizeof(name));
+
+	demo_p = demobuffer;
+	demoflags = DF_GHOST|(modeattacking<<DF_ATTACKSHIFT);
+
+	// Setup header.
+	M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12;
+	WRITEUINT8(demo_p,VERSION);
+	WRITEUINT8(demo_p,SUBVERSION);
+	WRITEUINT16(demo_p,DEMOVERSION);
+
+	// demo checksum
+	demo_p += 16;
+
+	// game data
+	M_Memcpy(demo_p, "PLAY", 4); demo_p += 4;
+	WRITEINT16(demo_p,gamemap);
+	M_Memcpy(demo_p, mapmd5, 16); demo_p += 16;
+
+	WRITEUINT8(demo_p,demoflags);
+	switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
+	{
+	case ATTACKING_NONE: // 0
+		break;
+	case ATTACKING_RECORD: // 1
+		demotime_p = demo_p;
+		WRITEUINT32(demo_p,UINT32_MAX); // time
+		WRITEUINT32(demo_p,0); // score
+		WRITEUINT16(demo_p,0); // rings
+		break;
+	case ATTACKING_NIGHTS: // 2
+		demotime_p = demo_p;
+		WRITEUINT32(demo_p,UINT32_MAX); // time
+		WRITEUINT32(demo_p,0); // score
+		break;
+	default: // 3
+		break;
+	}
+
+	WRITEUINT32(demo_p,P_GetInitSeed());
+
+	// Name
+	for (i = 0; i < 16 && cv_playername.string[i]; i++)
+		name[i] = cv_playername.string[i];
+	for (; i < 16; i++)
+		name[i] = '\0';
+	M_Memcpy(demo_p,name,16);
+	demo_p += 16;
+
+	// Skin
+	for (i = 0; i < 16 && cv_skin.string[i]; i++)
+		name[i] = cv_skin.string[i];
+	for (; i < 16; i++)
+		name[i] = '\0';
+	M_Memcpy(demo_p,name,16);
+	demo_p += 16;
+
+	// Color
+	for (i = 0; i < 16 && cv_playercolor.string[i]; i++)
+		name[i] = cv_playercolor.string[i];
+	for (; i < 16; i++)
+		name[i] = '\0';
+	M_Memcpy(demo_p,name,16);
+	demo_p += 16;
+
+	// Stats
+	WRITEUINT8(demo_p,player->charability);
+	WRITEUINT8(demo_p,player->charability2);
+	WRITEUINT8(demo_p,player->actionspd>>FRACBITS);
+	WRITEUINT8(demo_p,player->mindash>>FRACBITS);
+	WRITEUINT8(demo_p,player->maxdash>>FRACBITS);
+	WRITEUINT8(demo_p,player->normalspeed>>FRACBITS);
+	WRITEUINT8(demo_p,player->runspeed>>FRACBITS);
+	WRITEUINT8(demo_p,player->thrustfactor);
+	WRITEUINT8(demo_p,player->accelstart);
+	WRITEUINT8(demo_p,player->acceleration);
+	WRITEUINT8(demo_p,player->height>>FRACBITS);
+	WRITEUINT8(demo_p,player->spinheight>>FRACBITS);
+	WRITEUINT8(demo_p,player->camerascale>>FRACBITS);
+	WRITEUINT8(demo_p,player->shieldscale>>FRACBITS);
+
+	// Trying to convert it back to % causes demo desync due to precision loss.
+	// Don't do it.
+	WRITEFIXED(demo_p, player->jumpfactor);
+
+	// And mobjtype_t is best with UINT32 too...
+	WRITEUINT32(demo_p, player->followitem);
+
+	// Save pflag data - see SendWeaponPref()
+	{
+		UINT8 buf = 0;
+		pflags_t pflags = 0;
+		if (cv_flipcam.value)
+		{
+			buf |= 0x01;
+			pflags |= PF_FLIPCAM;
+		}
+		if (cv_analog[0].value)
+		{
+			buf |= 0x02;
+			pflags |= PF_ANALOGMODE;
+		}
+		if (cv_directionchar[0].value)
+		{
+			buf |= 0x04;
+			pflags |= PF_DIRECTIONCHAR;
+		}
+		if (cv_autobrake.value)
+		{
+			buf |= 0x08;
+			pflags |= PF_AUTOBRAKE;
+		}
+		if (cv_usejoystick.value)
+			buf |= 0x10;
+		CV_SetValue(&cv_showinputjoy, !!(cv_usejoystick.value));
+
+		WRITEUINT8(demo_p,buf);
+		player->pflags = pflags;
+	}
+
+	// Save netvar data
+	CV_SaveNetVars(&demo_p);
+
+	memset(&oldcmd,0,sizeof(oldcmd));
+	memset(&oldghost,0,sizeof(oldghost));
+	memset(&ghostext,0,sizeof(ghostext));
+	ghostext.lastcolor = ghostext.color = GHC_NORMAL;
+	ghostext.lastscale = ghostext.scale = FRACUNIT;
+
+	if (player->mo)
+	{
+		oldghost.x = player->mo->x;
+		oldghost.y = player->mo->y;
+		oldghost.z = player->mo->z;
+		oldghost.angle = player->mo->angle>>24;
+
+		// preticker started us gravity flipped
+		if (player->mo->eflags & MFE_VERTICALFLIP)
+			ghostext.flags |= EZT_FLIP;
+	}
+}
+
+void G_BeginMetal(void)
+{
+	mobj_t *mo = players[consoleplayer].mo;
+
+#if 0
+	if (demo_p)
+		return;
+#endif
+
+	demo_p = demobuffer;
+
+	// Write header.
+	M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12;
+	WRITEUINT8(demo_p,VERSION);
+	WRITEUINT8(demo_p,SUBVERSION);
+	WRITEUINT16(demo_p,DEMOVERSION);
+
+	// demo checksum
+	demo_p += 16;
+
+	M_Memcpy(demo_p, "METL", 4); demo_p += 4;
+
+	memset(&ghostext,0,sizeof(ghostext));
+	ghostext.lastscale = ghostext.scale = FRACUNIT;
+
+	// Set up our memory.
+	memset(&oldmetal,0,sizeof(oldmetal));
+	oldmetal.x = mo->x;
+	oldmetal.y = mo->y;
+	oldmetal.z = mo->z;
+	oldmetal.angle = mo->angle>>24;
+}
+
+void G_SetDemoTime(UINT32 ptime, UINT32 pscore, UINT16 prings)
+{
+	if (!demorecording || !demotime_p)
+		return;
+	if (demoflags & DF_RECORDATTACK)
+	{
+		WRITEUINT32(demotime_p, ptime);
+		WRITEUINT32(demotime_p, pscore);
+		WRITEUINT16(demotime_p, prings);
+		demotime_p = NULL;
+	}
+	else if (demoflags & DF_NIGHTSATTACK)
+	{
+		WRITEUINT32(demotime_p, ptime);
+		WRITEUINT32(demotime_p, pscore);
+		demotime_p = NULL;
+	}
+}
+
+// Returns bitfield:
+// 1 == new demo has lower time
+// 2 == new demo has higher score
+// 4 == new demo has higher rings
+UINT8 G_CmpDemoTime(char *oldname, char *newname)
+{
+	UINT8 *buffer,*p;
+	UINT8 flags;
+	UINT32 oldtime, newtime, oldscore, newscore;
+	UINT16 oldrings, newrings, oldversion;
+	size_t bufsize ATTRUNUSED;
+	UINT8 c;
+	UINT16 s ATTRUNUSED;
+	UINT8 aflags = 0;
+
+	// load the new file
+	FIL_DefaultExtension(newname, ".lmp");
+	bufsize = FIL_ReadFile(newname, &buffer);
+	I_Assert(bufsize != 0);
+	p = buffer;
+
+	// read demo header
+	I_Assert(!memcmp(p, DEMOHEADER, 12));
+	p += 12; // DEMOHEADER
+	c = READUINT8(p); // VERSION
+	I_Assert(c == VERSION);
+	c = READUINT8(p); // SUBVERSION
+	I_Assert(c == SUBVERSION);
+	s = READUINT16(p);
+	I_Assert(s == DEMOVERSION);
+	p += 16; // demo checksum
+	I_Assert(!memcmp(p, "PLAY", 4));
+	p += 4; // PLAY
+	p += 2; // gamemap
+	p += 16; // map md5
+	flags = READUINT8(p); // demoflags
+
+	aflags = flags & (DF_RECORDATTACK|DF_NIGHTSATTACK);
+	I_Assert(aflags);
+	if (flags & DF_RECORDATTACK)
+	{
+		newtime = READUINT32(p);
+		newscore = READUINT32(p);
+		newrings = READUINT16(p);
+	}
+	else if (flags & DF_NIGHTSATTACK)
+	{
+		newtime = READUINT32(p);
+		newscore = READUINT32(p);
+		newrings = 0;
+	}
+	else // appease compiler
+		return 0;
+
+	Z_Free(buffer);
+
+	// load old file
+	FIL_DefaultExtension(oldname, ".lmp");
+	if (!FIL_ReadFile(oldname, &buffer))
+	{
+		CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), oldname);
+		return UINT8_MAX;
+	}
+	p = buffer;
+
+	// read demo header
+	if (memcmp(p, DEMOHEADER, 12))
+	{
+		CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
+		Z_Free(buffer);
+		return UINT8_MAX;
+	} p += 12; // DEMOHEADER
+	p++; // VERSION
+	p++; // SUBVERSION
+	oldversion = READUINT16(p);
+	switch(oldversion) // demoversion
+	{
+	case DEMOVERSION: // latest always supported
+		break;
+	// too old, cannot support.
+	default:
+		CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
+		Z_Free(buffer);
+		return UINT8_MAX;
+	}
+	p += 16; // demo checksum
+	if (memcmp(p, "PLAY", 4))
+	{
+		CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
+		Z_Free(buffer);
+		return UINT8_MAX;
+	} p += 4; // "PLAY"
+	if (oldversion <= 0x0008)
+		p++; // gamemap
+	else
+		p += 2; // gamemap
+	p += 16; // mapmd5
+	flags = READUINT8(p);
+	if (!(flags & aflags))
+	{
+		CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname);
+		Z_Free(buffer);
+		return UINT8_MAX;
+	}
+	if (flags & DF_RECORDATTACK)
+	{
+		oldtime = READUINT32(p);
+		oldscore = READUINT32(p);
+		oldrings = READUINT16(p);
+	}
+	else if (flags & DF_NIGHTSATTACK)
+	{
+		oldtime = READUINT32(p);
+		oldscore = READUINT32(p);
+		oldrings = 0;
+	}
+	else // appease compiler
+		return UINT8_MAX;
+
+	Z_Free(buffer);
+
+	c = 0;
+	if (newtime < oldtime
+	|| (newtime == oldtime && (newscore > oldscore || newrings > oldrings)))
+		c |= 1; // Better time
+	if (newscore > oldscore
+	|| (newscore == oldscore && newtime < oldtime))
+		c |= 1<<1; // Better score
+	if (newrings > oldrings
+	|| (newrings == oldrings && newtime < oldtime))
+		c |= 1<<2; // Better rings
+	return c;
+}
+
+//
+// G_PlayDemo
+//
+void G_DeferedPlayDemo(const char *name)
+{
+	COM_BufAddText("playdemo \"");
+	COM_BufAddText(name);
+	COM_BufAddText("\"\n");
+}
+
+//
+// Start a demo from a .LMP file or from a wad resource
+//
+void G_DoPlayDemo(char *defdemoname)
+{
+	UINT8 i;
+	lumpnum_t l;
+	char skin[17],color[17],*n,*pdemoname;
+	UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration;
+	pflags_t pflags;
+	UINT32 randseed, followitem;
+	fixed_t camerascale,shieldscale,actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor,height,spinheight;
+	char msg[1024];
+
+	skin[16] = '\0';
+	color[16] = '\0';
+
+	n = defdemoname+strlen(defdemoname);
+	while (*n != '/' && *n != '\\' && n != defdemoname)
+		n--;
+	if (n != defdemoname)
+		n++;
+	pdemoname = ZZ_Alloc(strlen(n)+1);
+	strcpy(pdemoname,n);
+
+	// Internal if no extension, external if one exists
+	if (FIL_CheckExtension(defdemoname))
+	{
+		//FIL_DefaultExtension(defdemoname, ".lmp");
+		if (!FIL_ReadFile(defdemoname, &demobuffer))
+		{
+			snprintf(msg, 1024, M_GetText("Failed to read file '%s'.\n"), defdemoname);
+			CONS_Alert(CONS_ERROR, "%s", msg);
+			gameaction = ga_nothing;
+			M_StartMessage(msg, NULL, MM_NOTHING);
+			return;
+		}
+		demo_p = demobuffer;
+	}
+	// load demo resource from WAD
+	else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
+	{
+		snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname);
+		CONS_Alert(CONS_ERROR, "%s", msg);
+		gameaction = ga_nothing;
+		M_StartMessage(msg, NULL, MM_NOTHING);
+		return;
+	}
+	else // it's an internal demo
+		demobuffer = demo_p = W_CacheLumpNum(l, PU_STATIC);
+
+	// read demo header
+	gameaction = ga_nothing;
+	demoplayback = true;
+	if (memcmp(demo_p, DEMOHEADER, 12))
+	{
+		snprintf(msg, 1024, M_GetText("%s is not a SRB2 replay file.\n"), pdemoname);
+		CONS_Alert(CONS_ERROR, "%s", msg);
+		M_StartMessage(msg, NULL, MM_NOTHING);
+		Z_Free(pdemoname);
+		Z_Free(demobuffer);
+		demoplayback = false;
+		titledemo = false;
+		return;
+	}
+	demo_p += 12; // DEMOHEADER
+
+	version = READUINT8(demo_p);
+	subversion = READUINT8(demo_p);
+	demoversion = READUINT16(demo_p);
+	switch(demoversion)
+	{
+	case DEMOVERSION: // latest always supported
+		break;
+	// too old, cannot support.
+	default:
+		snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname);
+		CONS_Alert(CONS_ERROR, "%s", msg);
+		M_StartMessage(msg, NULL, MM_NOTHING);
+		Z_Free(pdemoname);
+		Z_Free(demobuffer);
+		demoplayback = false;
+		titledemo = false;
+		return;
+	}
+	demo_p += 16; // demo checksum
+	if (memcmp(demo_p, "PLAY", 4))
+	{
+		snprintf(msg, 1024, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemoname);
+		CONS_Alert(CONS_ERROR, "%s", msg);
+		M_StartMessage(msg, NULL, MM_NOTHING);
+		Z_Free(pdemoname);
+		Z_Free(demobuffer);
+		demoplayback = false;
+		titledemo = false;
+		return;
+	}
+	demo_p += 4; // "PLAY"
+	gamemap = READINT16(demo_p);
+	demo_p += 16; // mapmd5
+
+	demoflags = READUINT8(demo_p);
+	modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT;
+	CON_ToggleOff();
+
+	hu_demoscore = 0;
+	hu_demotime = UINT32_MAX;
+	hu_demorings = 0;
+
+	switch (modeattacking)
+	{
+	case ATTACKING_NONE: // 0
+		break;
+	case ATTACKING_RECORD: // 1
+		hu_demotime  = READUINT32(demo_p);
+		hu_demoscore = READUINT32(demo_p);
+		hu_demorings = READUINT16(demo_p);
+		break;
+	case ATTACKING_NIGHTS: // 2
+		hu_demotime  = READUINT32(demo_p);
+		hu_demoscore = READUINT32(demo_p);
+		break;
+	default: // 3
+		modeattacking = ATTACKING_NONE;
+		break;
+	}
+
+	// Random seed
+	randseed = READUINT32(demo_p);
+
+	// Player name
+	M_Memcpy(player_names[0],demo_p,16);
+	demo_p += 16;
+
+	// Skin
+	M_Memcpy(skin,demo_p,16);
+	demo_p += 16;
+
+	// Color
+	M_Memcpy(color,demo_p,16);
+	demo_p += 16;
+
+	charability = READUINT8(demo_p);
+	charability2 = READUINT8(demo_p);
+	actionspd = (fixed_t)READUINT8(demo_p)<<FRACBITS;
+	mindash = (fixed_t)READUINT8(demo_p)<<FRACBITS;
+	maxdash = (fixed_t)READUINT8(demo_p)<<FRACBITS;
+	normalspeed = (fixed_t)READUINT8(demo_p)<<FRACBITS;
+	runspeed = (fixed_t)READUINT8(demo_p)<<FRACBITS;
+	thrustfactor = READUINT8(demo_p);
+	accelstart = READUINT8(demo_p);
+	acceleration = READUINT8(demo_p);
+	height = (fixed_t)READUINT8(demo_p)<<FRACBITS;
+	spinheight = (fixed_t)READUINT8(demo_p)<<FRACBITS;
+	camerascale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
+	shieldscale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
+	jumpfactor = READFIXED(demo_p);
+	followitem = READUINT32(demo_p);
+
+	// pflag data
+	{
+		UINT8 buf = READUINT8(demo_p);
+		pflags = 0;
+		if (buf & 0x01)
+			pflags |= PF_FLIPCAM;
+		if (buf & 0x02)
+			pflags |= PF_ANALOGMODE;
+		if (buf & 0x04)
+			pflags |= PF_DIRECTIONCHAR;
+		if (buf & 0x08)
+			pflags |= PF_AUTOBRAKE;
+		CV_SetValue(&cv_showinputjoy, !!(buf & 0x10));
+	}
+
+	// net var data
+	CV_LoadNetVars(&demo_p);
+
+	// Sigh ... it's an empty demo.
+	if (*demo_p == DEMOMARKER)
+	{
+		snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname);
+		CONS_Alert(CONS_ERROR, "%s", msg);
+		M_StartMessage(msg, NULL, MM_NOTHING);
+		Z_Free(pdemoname);
+		Z_Free(demobuffer);
+		demoplayback = false;
+		titledemo = false;
+		return;
+	}
+
+	Z_Free(pdemoname);
+
+	memset(&oldcmd,0,sizeof(oldcmd));
+	memset(&oldghost,0,sizeof(oldghost));
+
+	if (VERSION != version || SUBVERSION != subversion)
+		CONS_Alert(CONS_WARNING, M_GetText("Demo version does not match game version. Desyncs may occur.\n"));
+
+	// didn't start recording right away.
+	demo_start = false;
+
+	// Set skin
+	SetPlayerSkin(0, skin);
+
+#ifdef HAVE_BLUA
+	LUAh_MapChange(gamemap);
+#endif
+	displayplayer = consoleplayer = 0;
+	memset(playeringame,0,sizeof(playeringame));
+	playeringame[0] = true;
+	P_SetRandSeed(randseed);
+	G_InitNew(false, G_BuildMapName(gamemap), true, true, false);
+
+	// Set color
+	for (i = 0; i < MAXSKINCOLORS; i++)
+		if (!stricmp(Color_Names[i],color))
+		{
+			players[0].skincolor = i;
+			break;
+		}
+	CV_StealthSetValue(&cv_playercolor, players[0].skincolor);
+	if (players[0].mo)
+	{
+		players[0].mo->color = players[0].skincolor;
+		oldghost.x = players[0].mo->x;
+		oldghost.y = players[0].mo->y;
+		oldghost.z = players[0].mo->z;
+	}
+
+	// Set saved attribute values
+	// No cheat checking here, because even if they ARE wrong...
+	// it would only break the replay if we clipped them.
+	players[0].camerascale = camerascale;
+	players[0].shieldscale = shieldscale;
+	players[0].charability = charability;
+	players[0].charability2 = charability2;
+	players[0].actionspd = actionspd;
+	players[0].mindash = mindash;
+	players[0].maxdash = maxdash;
+	players[0].normalspeed = normalspeed;
+	players[0].runspeed = runspeed;
+	players[0].thrustfactor = thrustfactor;
+	players[0].accelstart = accelstart;
+	players[0].acceleration = acceleration;
+	players[0].height = height;
+	players[0].spinheight = spinheight;
+	players[0].jumpfactor = jumpfactor;
+	players[0].followitem = followitem;
+	players[0].pflags = pflags;
+
+	demo_start = true;
+}
+
+void G_AddGhost(char *defdemoname)
+{
+	INT32 i;
+	lumpnum_t l;
+	char name[17],skin[17],color[17],*n,*pdemoname,md5[16];
+	demoghost *gh;
+	UINT8 flags;
+	UINT8 *buffer,*p;
+	mapthing_t *mthing;
+	UINT16 count, ghostversion;
+
+	name[16] = '\0';
+	skin[16] = '\0';
+	color[16] = '\0';
+
+	n = defdemoname+strlen(defdemoname);
+	while (*n != '/' && *n != '\\' && n != defdemoname)
+		n--;
+	if (n != defdemoname)
+		n++;
+	pdemoname = ZZ_Alloc(strlen(n)+1);
+	strcpy(pdemoname,n);
+
+	// Internal if no extension, external if one exists
+	if (FIL_CheckExtension(defdemoname))
+	{
+		//FIL_DefaultExtension(defdemoname, ".lmp");
+		if (!FIL_ReadFileTag(defdemoname, &buffer, PU_LEVEL))
+		{
+			CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), defdemoname);
+			Z_Free(pdemoname);
+			return;
+		}
+		p = buffer;
+	}
+	// load demo resource from WAD
+	else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
+	{
+		CONS_Alert(CONS_ERROR, M_GetText("Failed to read lump '%s'.\n"), defdemoname);
+		Z_Free(pdemoname);
+		return;
+	}
+	else // it's an internal demo
+		buffer = p = W_CacheLumpNum(l, PU_LEVEL);
+
+	// read demo header
+	if (memcmp(p, DEMOHEADER, 12))
+	{
+		CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Not a SRB2 replay.\n"), pdemoname);
+		Z_Free(pdemoname);
+		Z_Free(buffer);
+		return;
+	} p += 12; // DEMOHEADER
+	p++; // VERSION
+	p++; // SUBVERSION
+	ghostversion = READUINT16(p);
+	switch(ghostversion)
+	{
+	case DEMOVERSION: // latest always supported
+		break;
+	// too old, cannot support.
+	default:
+		CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname);
+		Z_Free(pdemoname);
+		Z_Free(buffer);
+		return;
+	}
+	M_Memcpy(md5, p, 16); p += 16; // demo checksum
+	for (gh = ghosts; gh; gh = gh->next)
+		if (!memcmp(md5, gh->checksum, 16)) // another ghost in the game already has this checksum?
+		{ // Don't add another one, then!
+			CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (MD5 was matched)\n", pdemoname);
+			Z_Free(pdemoname);
+			Z_Free(buffer);
+			return;
+		}
+	if (memcmp(p, "PLAY", 4))
+	{
+		CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo format unacceptable.\n"), pdemoname);
+		Z_Free(pdemoname);
+		Z_Free(buffer);
+		return;
+	} p += 4; // "PLAY"
+	if (ghostversion <= 0x0008)
+		p++; // gamemap
+	else
+		p += 2; // gamemap
+	p += 16; // mapmd5 (possibly check for consistency?)
+	flags = READUINT8(p);
+	if (!(flags & DF_GHOST))
+	{
+		CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname);
+		Z_Free(pdemoname);
+		Z_Free(buffer);
+		return;
+	}
+	switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
+	{
+	case ATTACKING_NONE: // 0
+		break;
+	case ATTACKING_RECORD: // 1
+		p += 10; // demo time, score, and rings
+		break;
+	case ATTACKING_NIGHTS: // 2
+		p += 8; // demo time left, score
+		break;
+	default: // 3
+		break;
+	}
+
+	p += 4; // random seed
+
+	// Player name (TODO: Display this somehow if it doesn't match cv_playername!)
+	M_Memcpy(name, p,16);
+	p += 16;
+
+	// Skin
+	M_Memcpy(skin, p,16);
+	p += 16;
+
+	// Color
+	M_Memcpy(color, p,16);
+	p += 16;
+
+	// Ghosts do not have a player structure to put this in.
+	p++; // charability
+	p++; // charability2
+	p++; // actionspd
+	p++; // mindash
+	p++; // maxdash
+	p++; // normalspeed
+	p++; // runspeed
+	p++; // thrustfactor
+	p++; // accelstart
+	p++; // acceleration
+	p++; // height
+	p++; // spinheight
+	p++; // camerascale
+	p++; // shieldscale
+	p += 4; // jumpfactor
+	p += 4; // followitem
+
+	p++; // pflag data
+
+	// net var data
+	count = READUINT16(p);
+	while (count--)
+	{
+		p += 2;
+		SKIPSTRING(p);
+		p++;
+	}
+
+	if (*p == DEMOMARKER)
+	{
+		CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), pdemoname);
+		Z_Free(pdemoname);
+		Z_Free(buffer);
+		return;
+	}
+
+	gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL);
+	gh->next = ghosts;
+	gh->buffer = buffer;
+	M_Memcpy(gh->checksum, md5, 16);
+	gh->p = p;
+
+	ghosts = gh;
+
+	gh->version = ghostversion;
+	mthing = playerstarts[0];
+	I_Assert(mthing);
+	{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
+		fixed_t z,f,c;
+		fixed_t offset = mthing->z << FRACBITS;
+		gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST);
+		gh->mo->angle = FixedAngle(mthing->angle << FRACBITS);
+		f = gh->mo->floorz;
+		c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height;
+		if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP))
+		{
+			z = c - offset;
+			if (z < f)
+				z = f;
+		}
+		else
+		{
+			z = f + offset;
+			if (z > c)
+				z = c;
+		}
+		gh->mo->z = z;
+	}
+
+	gh->oldmo.x = gh->mo->x;
+	gh->oldmo.y = gh->mo->y;
+	gh->oldmo.z = gh->mo->z;
+
+	// Set skin
+	gh->mo->skin = &skins[0];
+	for (i = 0; i < numskins; i++)
+		if (!stricmp(skins[i].name,skin))
+		{
+			gh->mo->skin = &skins[i];
+			break;
+		}
+	gh->oldmo.skin = gh->mo->skin;
+
+	// Set color
+	gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor;
+	for (i = 0; i < MAXSKINCOLORS; i++)
+		if (!stricmp(Color_Names[i],color))
+		{
+			gh->mo->color = (UINT8)i;
+			break;
+		}
+	gh->oldmo.color = gh->mo->color;
+
+	gh->mo->state = states+S_PLAY_STND;
+	gh->mo->sprite = gh->mo->state->sprite;
+	gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK);
+	//gh->mo->frame = tr_trans30<<FF_TRANSSHIFT;
+	gh->mo->flags2 |= MF2_DONTDRAW;
+	gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible
+	gh->mo->tics = -1;
+
+	CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname);
+	Z_Free(pdemoname);
+}
+
+//
+// G_TimeDemo
+// NOTE: name is a full filename for external demos
+//
+static INT32 restorecv_vidwait;
+
+void G_TimeDemo(const char *name)
+{
+	nodrawers = M_CheckParm("-nodraw");
+	noblit = M_CheckParm("-noblit");
+	restorecv_vidwait = cv_vidwait.value;
+	if (cv_vidwait.value)
+		CV_Set(&cv_vidwait, "0");
+	timingdemo = true;
+	singletics = true;
+	framecount = 0;
+	demostarttime = I_GetTime();
+	G_DeferedPlayDemo(name);
+}
+
+void G_DoPlayMetal(void)
+{
+	lumpnum_t l;
+	mobj_t *mo = NULL;
+	thinker_t *th;
+
+	// it's an internal demo
+	if ((l = W_CheckNumForName(va("%sMS",G_BuildMapName(gamemap)))) == LUMPERROR)
+	{
+		CONS_Alert(CONS_WARNING, M_GetText("No bot recording for this map.\n"));
+		return;
+	}
+	else
+		metalbuffer = metal_p = W_CacheLumpNum(l, PU_STATIC);
+
+	// find metal sonic
+	for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
+	{
+		if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
+			continue;
+
+		mo = (mobj_t *)th;
+		if (mo->type != MT_METALSONIC_RACE)
+			continue;
+
+		break;
+	}
+	if (th == &thlist[THINK_MOBJ])
+	{
+		CONS_Alert(CONS_ERROR, M_GetText("Failed to find bot entity.\n"));
+		Z_Free(metalbuffer);
+		return;
+	}
+
+	// read demo header
+    metal_p += 12; // DEMOHEADER
+	metal_p++; // VERSION
+	metal_p++; // SUBVERSION
+	metalversion = READUINT16(metal_p);
+	switch(metalversion)
+	{
+	case DEMOVERSION: // latest always supported
+		break;
+	// too old, cannot support.
+	default:
+		CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, format version incompatible.\n"));
+		Z_Free(metalbuffer);
+		return;
+	}
+	metal_p += 16; // demo checksum
+	if (memcmp(metal_p, "METL", 4))
+	{
+		CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, wasn't recorded in Metal format.\n"));
+		Z_Free(metalbuffer);
+		return;
+	} metal_p += 4; // "METL"
+
+	// read initial tic
+	memset(&oldmetal,0,sizeof(oldmetal));
+	oldmetal.x = mo->x;
+	oldmetal.y = mo->y;
+	oldmetal.z = mo->z;
+	metalplayback = mo;
+}
+
+void G_DoneLevelLoad(void)
+{
+	CONS_Printf(M_GetText("Loaded level in %f sec\n"), (double)(I_GetTime() - demostarttime) / TICRATE);
+	framecount = 0;
+	demostarttime = I_GetTime();
+}
+
+/*
+===================
+=
+= G_CheckDemoStatus
+=
+= Called after a death or level completion to allow demos to be cleaned up
+= Returns true if a new demo loop action will take place
+===================
+*/
+
+// Stops metal sonic's demo. Separate from other functions because metal + replays can coexist
+void G_StopMetalDemo(void)
+{
+
+	// Metal Sonic finishing doesn't end the game, dammit.
+	Z_Free(metalbuffer);
+	metalbuffer = NULL;
+	metalplayback = NULL;
+	metal_p = NULL;
+}
+
+// Stops metal sonic recording.
+ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill)
+{
+	boolean saved = false;
+	if (demo_p)
+	{
+		UINT8 *p = demobuffer+16; // checksum position
+		if (kill)
+			WRITEUINT8(demo_p, METALDEATH); // add the metal death marker
+		else
+			WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
+#ifdef NOMD5
+		{
+			UINT8 i;
+			for (i = 0; i < 16; i++, p++)
+				*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
+		}
+#else
+		md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file.
+#endif
+		saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file.
+	}
+	free(demobuffer);
+	metalrecording = false;
+	if (saved)
+		I_Error("Saved to %sMS.LMP", G_BuildMapName(gamemap));
+	I_Error("Failed to save demo!");
+}
+
+// reset engine variable set for the demos
+// called from stopdemo command, map command, and g_checkdemoStatus.
+void G_StopDemo(void)
+{
+	Z_Free(demobuffer);
+	demobuffer = NULL;
+	demoplayback = false;
+	titledemo = false;
+	timingdemo = false;
+	singletics = false;
+
+	if (gamestate == GS_INTERMISSION)
+		Y_EndIntermission(); // cleanup
+
+	G_SetGamestate(GS_NULL);
+	wipegamestate = GS_NULL;
+	SV_StopServer();
+	SV_ResetServer();
+}
+
+boolean G_CheckDemoStatus(void)
+{
+	boolean saved;
+
+	while (ghosts)
+	{
+		demoghost *next = ghosts->next;
+		Z_Free(ghosts);
+		ghosts = next;
+	}
+	ghosts = NULL;
+
+
+	// DO NOT end metal sonic demos here
+
+	if (timingdemo)
+	{
+		INT32 demotime;
+		double f1, f2;
+		demotime = I_GetTime() - demostarttime;
+		if (!demotime)
+			return true;
+		G_StopDemo();
+		timingdemo = false;
+		f1 = (double)demotime;
+		f2 = (double)framecount*TICRATE;
+
+		CONS_Printf(M_GetText("timed %u gametics in %d realtics - %u frames\n%f seconds, %f avg fps\n"),
+			leveltime,demotime,(UINT32)framecount,f1/TICRATE,f2/f1);
+
+		// CSV-readable timedemo results, for external parsing
+		if (timedemo_csv)
+		{
+			FILE *f;
+			const char *csvpath = va("%s"PATHSEP"%s", srb2home, "timedemo.csv");
+			const char *header = "id,demoname,seconds,avgfps,leveltime,demotime,framecount,ticrate,rendermode,vidmode,vidwidth,vidheight,procbits\n";
+			const char *rowformat = "\"%s\",\"%s\",%f,%f,%u,%d,%u,%u,%u,%u,%u,%u,%u\n";
+			boolean headerrow = !FIL_FileExists(csvpath);
+			UINT8 procbits = 0;
+
+			// Bitness
+			if (sizeof(void*) == 4)
+				procbits = 32;
+			else if (sizeof(void*) == 8)
+				procbits = 64;
+
+			f = fopen(csvpath, "a+");
+
+			if (f)
+			{
+				if (headerrow)
+					fputs(header, f);
+				fprintf(f, rowformat,
+					timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits);
+				fclose(f);
+				CONS_Printf("Timedemo results saved to '%s'\n", csvpath);
+			}
+			else
+			{
+				// Just print the CSV output to console
+				CON_LogMessage(header);
+				CONS_Printf(rowformat,
+					timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits);
+			}
+		}
+
+		if (restorecv_vidwait != cv_vidwait.value)
+			CV_SetValue(&cv_vidwait, restorecv_vidwait);
+		D_AdvanceDemo();
+		return true;
+	}
+
+	if (demoplayback)
+	{
+		if (singledemo)
+			I_Quit();
+		G_StopDemo();
+
+		if (modeattacking)
+			M_EndModeAttackRun();
+		else
+			D_AdvanceDemo();
+
+		return true;
+	}
+
+	if (demorecording)
+	{
+		UINT8 *p = demobuffer+16; // checksum position
+#ifdef NOMD5
+		UINT8 i;
+		WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
+		for (i = 0; i < 16; i++, p++)
+			*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
+#else
+		WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
+		md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file.
+#endif
+		saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file.
+		free(demobuffer);
+		demorecording = false;
+
+		if (modeattacking != ATTACKING_RECORD)
+		{
+			if (saved)
+				CONS_Printf(M_GetText("Demo %s recorded\n"), demoname);
+			else
+				CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname);
+		}
+		return true;
+	}
+
+	return false;
+}
diff --git a/src/g_demo.h b/src/g_demo.h
new file mode 100644
index 000000000..89be6e343
--- /dev/null
+++ b/src/g_demo.h
@@ -0,0 +1,85 @@
+// SONIC ROBO BLAST 2
+//-----------------------------------------------------------------------------
+// Copyright (C) 1993-1996 by id Software, Inc.
+// Copyright (C) 1998-2000 by DooM Legacy Team.
+// Copyright (C) 1999-2020 by Sonic Team Junior.
+//
+// This program is free software distributed under the
+// terms of the GNU General Public License, version 2.
+// See the 'LICENSE' file for more details.
+//-----------------------------------------------------------------------------
+/// \file  g_demo.h
+/// \brief Demo recording and playback
+
+#ifndef __G_DEMO__
+#define __G_DEMO__
+
+#include "doomdef.h"
+#include "doomstat.h"
+#include "d_event.h"
+
+// ======================================
+// DEMO playback/recording related stuff.
+// ======================================
+
+// demoplaying back and demo recording
+extern boolean demoplayback, titledemo, demorecording, timingdemo;
+extern tic_t demostarttime;
+
+// Quit after playing a demo from cmdline.
+extern boolean singledemo;
+extern boolean demo_start;
+extern boolean demosynced;
+
+extern mobj_t *metalplayback;
+
+// Only called by startup code.
+void G_RecordDemo(const char *name);
+void G_RecordMetal(void);
+void G_BeginRecording(void);
+void G_BeginMetal(void);
+
+// Only called by shutdown code.
+void G_SetDemoTime(UINT32 ptime, UINT32 pscore, UINT16 prings);
+UINT8 G_CmpDemoTime(char *oldname, char *newname);
+
+typedef enum
+{
+	GHC_NORMAL = 0,
+	GHC_SUPER,
+	GHC_FIREFLOWER,
+	GHC_INVINCIBLE,
+	GHC_NIGHTSSKIN, // not actually a colour
+	GHC_RETURNSKIN // ditto
+} ghostcolor_t;
+
+// Record/playback tics
+void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
+void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
+void G_GhostAddThok(void);
+void G_GhostAddSpin(void);
+void G_GhostAddRev(void);
+void G_GhostAddColor(ghostcolor_t color);
+void G_GhostAddFlip(void);
+void G_GhostAddScale(fixed_t scale);
+void G_GhostAddHit(mobj_t *victim);
+void G_WriteGhostTic(mobj_t *ghost);
+void G_ConsGhostTic(void);
+void G_GhostTicker(void);
+void G_ReadMetalTic(mobj_t *metal);
+void G_WriteMetalTic(mobj_t *metal);
+void G_SaveMetal(UINT8 **buffer);
+void G_LoadMetal(UINT8 **buffer);
+
+void G_DeferedPlayDemo(const char *demo);
+void G_DoPlayDemo(char *defdemoname);
+void G_TimeDemo(const char *name);
+void G_AddGhost(char *defdemoname);
+void G_DoPlayMetal(void);
+void G_DoneLevelLoad(void);
+void G_StopMetalDemo(void);
+ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill);
+void G_StopDemo(void);
+boolean G_CheckDemoStatus(void);
+
+#endif // __G_DEMO__
diff --git a/src/g_game.c b/src/g_game.c
index 58f7795b6..fb70e2995 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -27,6 +27,7 @@
 #include "r_main.h"
 #include "s_sound.h"
 #include "g_game.h"
+#include "g_demo.h"
 #include "m_cheat.h"
 #include "m_misc.h"
 #include "m_menu.h"
@@ -41,11 +42,9 @@
 #include "r_skins.h"
 #include "y_inter.h"
 #include "v_video.h"
-#include "dehacked.h" // get_number (for ghost thok)
 #include "lua_hook.h"
 #include "b_bot.h"
 #include "m_cond.h" // condition sets
-#include "md5.h" // demo checksums
 
 #ifdef HAVE_BLUA
 #include "lua_hud.h"
@@ -105,11 +104,6 @@ UINT8  numDemos      = 0;
 UINT32 demoDelayTime = 15*TICRATE;
 UINT32 demoIdleTime  = 3*TICRATE;
 
-boolean timingdemo; // if true, exit with report on completion
-boolean nodrawers; // for comparative timing purposes
-boolean noblit; // for comparative timing purposes
-tic_t demostarttime; // for comparative timing purposes
-
 boolean netgame; // only true if packets are broadcast
 boolean multiplayer;
 boolean playeringame[MAXPLAYERS];
@@ -256,57 +250,12 @@ UINT32 timesBeaten;
 UINT32 timesBeatenWithEmeralds;
 UINT32 timesBeatenUltimate;
 
-static char demoname[64];
-boolean demorecording;
-boolean demoplayback;
-boolean titledemo; // Title Screen demo can be cancelled by any key
-static UINT8 *demobuffer = NULL;
-static UINT8 *demo_p, *demotime_p;
-static UINT8 *demoend;
-static UINT8 demoflags;
-static UINT16 demoversion;
-boolean singledemo; // quit after playing a demo from cmdline
-boolean demo_start; // don't start playing demo right away
-boolean demosynced = true; // console warning message
-
-boolean metalrecording; // recording as metal sonic
-mobj_t *metalplayback;
-static UINT8 *metalbuffer = NULL;
-static UINT8 *metal_p;
-static UINT16 metalversion;
-
 typedef struct joystickvector2_s
 {
 	INT32 xaxis;
 	INT32 yaxis;
 } joystickvector2_t;
 
-// extra data stuff (events registered this frame while recording)
-static struct {
-	UINT8 flags; // EZT flags
-
-	// EZT_COLOR
-	UINT8 color, lastcolor;
-
-	// EZT_SCALE
-	fixed_t scale, lastscale;
-
-	// EZT_HIT
-	UINT16 hits;
-	mobj_t **hitlist;
-} ghostext;
-
-// Your naming conventions are stupid and useless.
-// There is no conflict here.
-typedef struct demoghost {
-	UINT8 checksum[16];
-	UINT8 *buffer, *p, color, fadein;
-	UINT16 version;
-	mobj_t oldmo, *mo;
-	struct demoghost *next;
-} demoghost;
-demoghost *ghosts = NULL;
-
 boolean precache = true; // if true, load all graphics at start
 
 INT16 prevmap, nextmap;
@@ -1102,8 +1051,6 @@ static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvect
 	}
 }
 
-
-
 //
 // G_BuildTiccmd
 // Builds a ticcmd from all of the available inputs
@@ -1723,6 +1670,25 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
 	}
 }
 
+ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
+{
+	return M_Memcpy(dest, src, n*sizeof(*src));
+}
+
+ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
+{
+	size_t i;
+	for (i = 0; i < n; i++)
+	{
+		dest[i].forwardmove = src[i].forwardmove;
+		dest[i].sidemove = src[i].sidemove;
+		dest[i].angleturn = SHORT(src[i].angleturn);
+		dest[i].aiming = (INT16)SHORT(src[i].aiming);
+		dest[i].buttons = (UINT16)SHORT(src[i].buttons);
+	}
+	return dest;
+}
+
 // User has designated that they want
 // analog ON, so tell the game to stop
 // fudging with it.
@@ -4933,2432 +4899,6 @@ INT32 G_FindMapByNameOrCode(const char *mapname, char **realmapnamep)
 	return newmapnum;
 }
 
-//
-// DEMO RECORDING
-//
-
-#define DEMOVERSION 0x000c
-#define DEMOHEADER  "\xF0" "SRB2Replay" "\x0F"
-
-#define DF_GHOST        0x01 // This demo contains ghost data too!
-#define DF_RECORDATTACK 0x02 // This demo is from record attack and contains its final completion time, score, and rings!
-#define DF_NIGHTSATTACK 0x04 // This demo is from NiGHTS attack and contains its time left, score, and mares!
-#define DF_ATTACKMASK   0x06 // This demo is from ??? attack and contains ???
-#define DF_ATTACKSHIFT  1
-
-// For demos
-#define ZT_FWD     0x01
-#define ZT_SIDE    0x02
-#define ZT_ANGLE   0x04
-#define ZT_BUTTONS 0x08
-#define ZT_AIMING  0x10
-#define DEMOMARKER 0x80 // demoend
-#define METALDEATH 0x44
-#define METALSNICE 0x69
-
-static ticcmd_t oldcmd;
-
-// For Metal Sonic and time attack ghosts
-#define GZT_XYZ    0x01
-#define GZT_MOMXY  0x02
-#define GZT_MOMZ   0x04
-#define GZT_ANGLE  0x08
-#define GZT_FRAME  0x10 // Animation frame
-#define GZT_SPR2   0x20 // Player animations
-#define GZT_EXTRA  0x40
-#define GZT_FOLLOW 0x80 // Followmobj
-
-// GZT_EXTRA flags
-#define EZT_THOK   0x01 // Spawned a thok object
-#define EZT_SPIN   0x02 // Because one type of thok object apparently wasn't enough
-#define EZT_REV    0x03 // And two types wasn't enough either yet
-#define EZT_THOKMASK 0x03
-#define EZT_COLOR  0x04 // Changed color (Super transformation, Mario fireflowers/invulnerability, etc.)
-#define EZT_FLIP   0x08 // Reversed gravity
-#define EZT_SCALE  0x10 // Changed size
-#define EZT_HIT    0x20 // Damaged a mobj
-#define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever)
-#define EZT_HEIGHT 0x80 // Changed height
-
-// GZT_FOLLOW flags
-#define FZT_SPAWNED 0x01 // just been spawned
-#define FZT_SKIN 0x02 // has skin
-#define FZT_LINKDRAW 0x04 // has linkdraw (combine with spawned only)
-#define FZT_COLORIZED 0x08 // colorized (ditto)
-#define FZT_SCALE 0x10 // different scale to object
-// spare FZT slots 0x20 to 0x80
-
-static mobj_t oldmetal, oldghost;
-
-void G_SaveMetal(UINT8 **buffer)
-{
-	I_Assert(buffer != NULL && *buffer != NULL);
-
-	WRITEUINT32(*buffer, metal_p - metalbuffer);
-}
-
-void G_LoadMetal(UINT8 **buffer)
-{
-	I_Assert(buffer != NULL && *buffer != NULL);
-
-	G_DoPlayMetal();
-	metal_p = metalbuffer + READUINT32(*buffer);
-}
-
-ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
-{
-	return M_Memcpy(dest, src, n*sizeof(*src));
-}
-
-ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
-{
-	size_t i;
-	for (i = 0; i < n; i++)
-	{
-		dest[i].forwardmove = src[i].forwardmove;
-		dest[i].sidemove = src[i].sidemove;
-		dest[i].angleturn = SHORT(src[i].angleturn);
-		dest[i].aiming = (INT16)SHORT(src[i].aiming);
-		dest[i].buttons = (UINT16)SHORT(src[i].buttons);
-	}
-	return dest;
-}
-
-void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
-{
-	UINT8 ziptic;
-	(void)playernum;
-
-	if (!demo_p || !demo_start)
-		return;
-	ziptic = READUINT8(demo_p);
-
-	if (ziptic & ZT_FWD)
-		oldcmd.forwardmove = READSINT8(demo_p);
-	if (ziptic & ZT_SIDE)
-		oldcmd.sidemove = READSINT8(demo_p);
-	if (ziptic & ZT_ANGLE)
-		oldcmd.angleturn = READINT16(demo_p);
-	if (ziptic & ZT_BUTTONS)
-		oldcmd.buttons = (oldcmd.buttons & (BT_CAMLEFT|BT_CAMRIGHT)) | (READUINT16(demo_p) & ~(BT_CAMLEFT|BT_CAMRIGHT));
-	if (ziptic & ZT_AIMING)
-		oldcmd.aiming = READINT16(demo_p);
-
-	G_CopyTiccmd(cmd, &oldcmd, 1);
-
-	if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER)
-	{
-		// end of demo data stream
-		G_CheckDemoStatus();
-		return;
-	}
-}
-
-void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum)
-{
-	char ziptic = 0;
-	UINT8 *ziptic_p;
-	(void)playernum;
-
-	if (!demo_p)
-		return;
-	ziptic_p = demo_p++; // the ziptic, written at the end of this function
-
-	if (cmd->forwardmove != oldcmd.forwardmove)
-	{
-		WRITEUINT8(demo_p,cmd->forwardmove);
-		oldcmd.forwardmove = cmd->forwardmove;
-		ziptic |= ZT_FWD;
-	}
-
-	if (cmd->sidemove != oldcmd.sidemove)
-	{
-		WRITEUINT8(demo_p,cmd->sidemove);
-		oldcmd.sidemove = cmd->sidemove;
-		ziptic |= ZT_SIDE;
-	}
-
-	if (cmd->angleturn != oldcmd.angleturn)
-	{
-		WRITEINT16(demo_p,cmd->angleturn);
-		oldcmd.angleturn = cmd->angleturn;
-		ziptic |= ZT_ANGLE;
-	}
-
-	if (cmd->buttons != oldcmd.buttons)
-	{
-		WRITEUINT16(demo_p,cmd->buttons);
-		oldcmd.buttons = cmd->buttons;
-		ziptic |= ZT_BUTTONS;
-	}
-
-	if (cmd->aiming != oldcmd.aiming)
-	{
-		WRITEINT16(demo_p,cmd->aiming);
-		oldcmd.aiming = cmd->aiming;
-		ziptic |= ZT_AIMING;
-	}
-
-	*ziptic_p = ziptic;
-
-	// attention here for the ticcmd size!
-	// latest demos with mouse aiming byte in ticcmd
-	if (!(demoflags & DF_GHOST) && ziptic_p > demoend - 9)
-	{
-		G_CheckDemoStatus(); // no more space
-		return;
-	}
-}
-
-void G_GhostAddThok(void)
-{
-	if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
-		return;
-	ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_THOK;
-}
-
-void G_GhostAddSpin(void)
-{
-	if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
-		return;
-	ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_SPIN;
-}
-
-void G_GhostAddRev(void)
-{
-	if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
-		return;
-	ghostext.flags = (ghostext.flags & ~EZT_THOKMASK) | EZT_REV;
-}
-
-void G_GhostAddFlip(void)
-{
-	if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
-		return;
-	ghostext.flags |= EZT_FLIP;
-}
-
-void G_GhostAddColor(ghostcolor_t color)
-{
-	if (!demorecording || !(demoflags & DF_GHOST))
-		return;
-	if (ghostext.lastcolor == (UINT8)color)
-	{
-		ghostext.flags &= ~EZT_COLOR;
-		return;
-	}
-	ghostext.flags |= EZT_COLOR;
-	ghostext.color = (UINT8)color;
-}
-
-void G_GhostAddScale(fixed_t scale)
-{
-	if (!metalrecording && (!demorecording || !(demoflags & DF_GHOST)))
-		return;
-	if (ghostext.lastscale == scale)
-	{
-		ghostext.flags &= ~EZT_SCALE;
-		return;
-	}
-	ghostext.flags |= EZT_SCALE;
-	ghostext.scale = scale;
-}
-
-void G_GhostAddHit(mobj_t *victim)
-{
-	if (!demorecording || !(demoflags & DF_GHOST))
-		return;
-	ghostext.flags |= EZT_HIT;
-	ghostext.hits++;
-	ghostext.hitlist = Z_Realloc(ghostext.hitlist, ghostext.hits * sizeof(mobj_t *), PU_LEVEL, NULL);
-	ghostext.hitlist[ghostext.hits-1] = victim;
-}
-
-void G_WriteGhostTic(mobj_t *ghost)
-{
-	char ziptic = 0;
-	UINT8 *ziptic_p;
-	UINT32 i;
-	fixed_t height;
-
-	if (!demo_p)
-		return;
-	if (!(demoflags & DF_GHOST))
-		return; // No ghost data to write.
-
-	ziptic_p = demo_p++; // the ziptic, written at the end of this function
-
-	#define MAXMOM (0xFFFF<<8)
-
-	// GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic.
-	if (abs(ghost->x-oldghost.x) > MAXMOM
-	|| abs(ghost->y-oldghost.y) > MAXMOM
-	|| abs(ghost->z-oldghost.z) > MAXMOM)
-	{
-		oldghost.x = ghost->x;
-		oldghost.y = ghost->y;
-		oldghost.z = ghost->z;
-		ziptic |= GZT_XYZ;
-		WRITEFIXED(demo_p,oldghost.x);
-		WRITEFIXED(demo_p,oldghost.y);
-		WRITEFIXED(demo_p,oldghost.z);
-	}
-	else
-	{
-		// For moving normally:
-		// Store one full byte of movement, plus one byte of fractional movement.
-		INT16 momx = (INT16)((ghost->x-oldghost.x)>>8);
-		INT16 momy = (INT16)((ghost->y-oldghost.y)>>8);
-		if (momx != oldghost.momx
-		|| momy != oldghost.momy)
-		{
-			oldghost.momx = momx;
-			oldghost.momy = momy;
-			ziptic |= GZT_MOMXY;
-			WRITEINT16(demo_p,momx);
-			WRITEINT16(demo_p,momy);
-		}
-		momx = (INT16)((ghost->z-oldghost.z)>>8);
-		if (momx != oldghost.momz)
-		{
-			oldghost.momz = momx;
-			ziptic |= GZT_MOMZ;
-			WRITEINT16(demo_p,momx);
-		}
-
-		// This SHOULD set oldghost.x/y/z to match ghost->x/y/z
-		// but it keeps the fractional loss of one byte,
-		// so it will hopefully be made up for in future tics.
-		oldghost.x += oldghost.momx<<8;
-		oldghost.y += oldghost.momy<<8;
-		oldghost.z += oldghost.momz<<8;
-	}
-
-	#undef MAXMOM
-
-	// Only store the 8 most relevant bits of angle
-	// because exact values aren't too easy to discern to begin with when only 8 angles have different sprites
-	// and it does not affect this mode of movement at all anyway.
-	if (ghost->player && ghost->player->drawangle>>24 != oldghost.angle)
-	{
-		oldghost.angle = ghost->player->drawangle>>24;
-		ziptic |= GZT_ANGLE;
-		WRITEUINT8(demo_p,oldghost.angle);
-	}
-
-	// Store the sprite frame.
-	if ((ghost->frame & FF_FRAMEMASK) != oldghost.frame)
-	{
-		oldghost.frame = (ghost->frame & FF_FRAMEMASK);
-		ziptic |= GZT_FRAME;
-		WRITEUINT8(demo_p,oldghost.frame);
-	}
-
-	if (ghost->sprite == SPR_PLAY
-	&& ghost->sprite2 != oldghost.sprite2)
-	{
-		oldghost.sprite2 = ghost->sprite2;
-		ziptic |= GZT_SPR2;
-		WRITEUINT8(demo_p,oldghost.sprite2);
-	}
-
-	// Check for sprite set changes
-	if (ghost->sprite != oldghost.sprite)
-	{
-		oldghost.sprite = ghost->sprite;
-		ghostext.flags |= EZT_SPRITE;
-	}
-
-	if ((height = FixedDiv(ghost->height, ghost->scale)) != oldghost.height)
-	{
-		oldghost.height = height;
-		ghostext.flags |= EZT_HEIGHT;
-	}
-
-	if (ghostext.flags)
-	{
-		ziptic |= GZT_EXTRA;
-
-		if (ghostext.color == ghostext.lastcolor)
-			ghostext.flags &= ~EZT_COLOR;
-		if (ghostext.scale == ghostext.lastscale)
-			ghostext.flags &= ~EZT_SCALE;
-
-		WRITEUINT8(demo_p,ghostext.flags);
-		if (ghostext.flags & EZT_COLOR)
-		{
-			WRITEUINT8(demo_p,ghostext.color);
-			ghostext.lastcolor = ghostext.color;
-		}
-		if (ghostext.flags & EZT_SCALE)
-		{
-			WRITEFIXED(demo_p,ghostext.scale);
-			ghostext.lastscale = ghostext.scale;
-		}
-		if (ghostext.flags & EZT_HIT)
-		{
-			WRITEUINT16(demo_p,ghostext.hits);
-			for (i = 0; i < ghostext.hits; i++)
-			{
-				mobj_t *mo = ghostext.hitlist[i];
-				//WRITEUINT32(demo_p,UINT32_MAX); // reserved for some method of determining exactly which mobj this is. (mobjnum doesn't work here.)
-				WRITEUINT32(demo_p,mo->type);
-				WRITEUINT16(demo_p,(UINT16)mo->health);
-				WRITEFIXED(demo_p,mo->x);
-				WRITEFIXED(demo_p,mo->y);
-				WRITEFIXED(demo_p,mo->z);
-				WRITEANGLE(demo_p,mo->angle);
-			}
-			Z_Free(ghostext.hitlist);
-			ghostext.hits = 0;
-			ghostext.hitlist = NULL;
-		}
-		if (ghostext.flags & EZT_SPRITE)
-			WRITEUINT16(demo_p,oldghost.sprite);
-		if (ghostext.flags & EZT_HEIGHT)
-		{
-			height >>= FRACBITS;
-			WRITEINT16(demo_p, height);
-		}
-		ghostext.flags = 0;
-	}
-
-	if (ghost->player && ghost->player->followmobj && !(ghost->player->followmobj->sprite == SPR_NULL || (ghost->player->followmobj->flags2 & MF2_DONTDRAW))) // bloats tails runs but what can ya do
-	{
-		INT16 temp;
-		UINT8 *followtic_p = demo_p++;
-		UINT8 followtic = 0;
-
-		ziptic |= GZT_FOLLOW;
-
-		if (ghost->player->followmobj->skin)
-			followtic |= FZT_SKIN;
-
-		if (!(oldghost.flags2 & MF2_AMBUSH))
-		{
-			followtic |= FZT_SPAWNED;
-			WRITEINT16(demo_p,ghost->player->followmobj->info->height>>FRACBITS);
-			if (ghost->player->followmobj->flags2 & MF2_LINKDRAW)
-				followtic |= FZT_LINKDRAW;
-			if (ghost->player->followmobj->colorized)
-				followtic |= FZT_COLORIZED;
-			if (followtic & FZT_SKIN)
-				WRITEUINT8(demo_p,(UINT8)(((skin_t *)(ghost->player->followmobj->skin))-skins));
-			oldghost.flags2 |= MF2_AMBUSH;
-		}
-
-		if (ghost->player->followmobj->scale != ghost->scale)
-		{
-			followtic |= FZT_SCALE;
-			WRITEFIXED(demo_p,ghost->player->followmobj->scale);
-		}
-
-		temp = (INT16)((ghost->player->followmobj->x-ghost->x)>>8);
-		WRITEINT16(demo_p,temp);
-		temp = (INT16)((ghost->player->followmobj->y-ghost->y)>>8);
-		WRITEINT16(demo_p,temp);
-		temp = (INT16)((ghost->player->followmobj->z-ghost->z)>>8);
-		WRITEINT16(demo_p,temp);
-		if (followtic & FZT_SKIN)
-			WRITEUINT8(demo_p,ghost->player->followmobj->sprite2);
-		WRITEUINT16(demo_p,ghost->player->followmobj->sprite);
-		WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK));
-		WRITEUINT8(demo_p,ghost->player->followmobj->color);
-
-		*followtic_p = followtic;
-	}
-	else
-		oldghost.flags2 &= ~MF2_AMBUSH;
-
-	*ziptic_p = ziptic;
-
-	// attention here for the ticcmd size!
-	// latest demos with mouse aiming byte in ticcmd
-	if (demo_p >= demoend - (13 + 9 + 9))
-	{
-		G_CheckDemoStatus(); // no more space
-		return;
-	}
-}
-
-// Uses ghost data to do consistency checks on your position.
-// This fixes desynchronising demos when fighting eggman.
-void G_ConsGhostTic(void)
-{
-	UINT8 ziptic;
-	UINT16 px,py,pz,gx,gy,gz;
-	mobj_t *testmo;
-
-	if (!demo_p || !demo_start)
-		return;
-	if (!(demoflags & DF_GHOST))
-		return; // No ghost data to use.
-
-	testmo = players[0].mo;
-
-	// Grab ghost data.
-	ziptic = READUINT8(demo_p);
-	if (ziptic & GZT_XYZ)
-	{
-		oldghost.x = READFIXED(demo_p);
-		oldghost.y = READFIXED(demo_p);
-		oldghost.z = READFIXED(demo_p);
-	}
-	else
-	{
-		if (ziptic & GZT_MOMXY)
-		{
-			oldghost.momx = READINT16(demo_p)<<8;
-			oldghost.momy = READINT16(demo_p)<<8;
-		}
-		if (ziptic & GZT_MOMZ)
-			oldghost.momz = READINT16(demo_p)<<8;
-		oldghost.x += oldghost.momx;
-		oldghost.y += oldghost.momy;
-		oldghost.z += oldghost.momz;
-	}
-	if (ziptic & GZT_ANGLE)
-		demo_p++;
-	if (ziptic & GZT_FRAME)
-		demo_p++;
-	if (ziptic & GZT_SPR2)
-		demo_p++;
-
-	if (ziptic & GZT_EXTRA)
-	{ // But wait, there's more!
-		UINT8 xziptic = READUINT8(demo_p);
-		if (xziptic & EZT_COLOR)
-			demo_p++;
-		if (xziptic & EZT_SCALE)
-			demo_p += sizeof(fixed_t);
-		if (xziptic & EZT_HIT)
-		{ // Resync mob damage.
-			UINT16 i, count = READUINT16(demo_p);
-			thinker_t *th;
-			mobj_t *mobj;
-
-			UINT32 type;
-			UINT16 health;
-			fixed_t x;
-			fixed_t y;
-			fixed_t z;
-
-			for (i = 0; i < count; i++)
-			{
-				//demo_p += 4; // reserved.
-				type = READUINT32(demo_p);
-				health = READUINT16(demo_p);
-				x = READFIXED(demo_p);
-				y = READFIXED(demo_p);
-				z = READFIXED(demo_p);
-				demo_p += sizeof(angle_t); // angle, unnecessary for cons.
-
-				mobj = NULL;
-				for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
-				{
-					if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
-						continue;
-					mobj = (mobj_t *)th;
-					if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z)
-						break;
-				}
-				if (th != &thlist[THINK_MOBJ] && mobj->health != health) // Wasn't damaged?! This is desync! Fix it!
-				{
-					if (demosynced)
-						CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
-					demosynced = false;
-					P_DamageMobj(mobj, players[0].mo, players[0].mo, 1, 0);
-				}
-			}
-		}
-		if (xziptic & EZT_SPRITE)
-			demo_p += sizeof(UINT16);
-		if (xziptic & EZT_HEIGHT)
-			demo_p += sizeof(INT16);
-	}
-
-	if (ziptic & GZT_FOLLOW)
-	{ // Even more...
-		UINT8 followtic = READUINT8(demo_p);
-		if (followtic & FZT_SPAWNED)
-		{
-			demo_p += sizeof(INT16);
-			if (followtic & FZT_SKIN)
-				demo_p++;
-		}
-		if (followtic & FZT_SCALE)
-			demo_p += sizeof(fixed_t);
-		demo_p += sizeof(INT16);
-		demo_p += sizeof(INT16);
-		demo_p += sizeof(INT16);
-		if (followtic & FZT_SKIN)
-			demo_p++;
-		demo_p += sizeof(UINT16);
-		demo_p++;
-		demo_p++;
-	}
-
-	// Re-synchronise
-	px = testmo->x>>FRACBITS;
-	py = testmo->y>>FRACBITS;
-	pz = testmo->z>>FRACBITS;
-	gx = oldghost.x>>FRACBITS;
-	gy = oldghost.y>>FRACBITS;
-	gz = oldghost.z>>FRACBITS;
-
-	if (px != gx || py != gy || pz != gz)
-	{
-		if (demosynced)
-			CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n"));
-		demosynced = false;
-
-		P_UnsetThingPosition(testmo);
-		testmo->x = oldghost.x;
-		testmo->y = oldghost.y;
-		P_SetThingPosition(testmo);
-		testmo->z = oldghost.z;
-	}
-
-	if (*demo_p == DEMOMARKER)
-	{
-		// end of demo data stream
-		G_CheckDemoStatus();
-		return;
-	}
-}
-
-void G_GhostTicker(void)
-{
-	demoghost *g,*p;
-	for(g = ghosts, p = NULL; g; g = g->next)
-	{
-		// Skip normal demo data.
-		UINT8 ziptic = READUINT8(g->p);
-		UINT8 xziptic = 0;
-		if (ziptic & ZT_FWD)
-			g->p++;
-		if (ziptic & ZT_SIDE)
-			g->p++;
-		if (ziptic & ZT_ANGLE)
-			g->p += 2;
-		if (ziptic & ZT_BUTTONS)
-			g->p += 2;
-		if (ziptic & ZT_AIMING)
-			g->p += 2;
-
-		// Grab ghost data.
-		ziptic = READUINT8(g->p);
-		if (ziptic & GZT_XYZ)
-		{
-			g->oldmo.x = READFIXED(g->p);
-			g->oldmo.y = READFIXED(g->p);
-			g->oldmo.z = READFIXED(g->p);
-		}
-		else
-		{
-			if (ziptic & GZT_MOMXY)
-			{
-				g->oldmo.momx = READINT16(g->p)<<8;
-				g->oldmo.momy = READINT16(g->p)<<8;
-			}
-			if (ziptic & GZT_MOMZ)
-				g->oldmo.momz = READINT16(g->p)<<8;
-			g->oldmo.x += g->oldmo.momx;
-			g->oldmo.y += g->oldmo.momy;
-			g->oldmo.z += g->oldmo.momz;
-		}
-		if (ziptic & GZT_ANGLE)
-			g->mo->angle = READUINT8(g->p)<<24;
-		if (ziptic & GZT_FRAME)
-			g->oldmo.frame = READUINT8(g->p);
-		if (ziptic & GZT_SPR2)
-			g->oldmo.sprite2 = READUINT8(g->p);
-
-		// Update ghost
-		P_UnsetThingPosition(g->mo);
-		g->mo->x = g->oldmo.x;
-		g->mo->y = g->oldmo.y;
-		g->mo->z = g->oldmo.z;
-		P_SetThingPosition(g->mo);
-		g->mo->frame = g->oldmo.frame | tr_trans30<<FF_TRANSSHIFT;
-		if (g->fadein)
-		{
-			g->mo->frame += (((--g->fadein)/6)<<FF_TRANSSHIFT); // this calc never exceeds 9 unless g->fadein is bad, and it's only set once, so...
-			g->mo->flags2 &= ~MF2_DONTDRAW;
-		}
-		g->mo->sprite2 = g->oldmo.sprite2;
-
-		if (ziptic & GZT_EXTRA)
-		{ // But wait, there's more!
-			xziptic = READUINT8(g->p);
-			if (xziptic & EZT_COLOR)
-			{
-				g->color = READUINT8(g->p);
-				switch(g->color)
-				{
-				default:
-				case GHC_RETURNSKIN:
-					g->mo->skin = g->oldmo.skin;
-					/* FALLTHRU */
-				case GHC_NORMAL: // Go back to skin color
-					g->mo->color = g->oldmo.color;
-					break;
-				// Handled below
-				case GHC_SUPER:
-				case GHC_INVINCIBLE:
-					break;
-				case GHC_FIREFLOWER: // Fireflower
-					g->mo->color = SKINCOLOR_WHITE;
-					break;
-				case GHC_NIGHTSSKIN: // not actually a colour
-					g->mo->skin = &skins[DEFAULTNIGHTSSKIN];
-					break;
-				}
-			}
-			if (xziptic & EZT_FLIP)
-				g->mo->eflags ^= MFE_VERTICALFLIP;
-			if (xziptic & EZT_SCALE)
-			{
-				g->mo->destscale = READFIXED(g->p);
-				if (g->mo->destscale != g->mo->scale)
-					P_SetScale(g->mo, g->mo->destscale);
-			}
-			if (xziptic & EZT_THOKMASK)
-			{ // Let's only spawn ONE of these per frame, thanks.
-				mobj_t *mobj;
-				INT32 type = -1;
-				if (g->mo->skin)
-				{
-					skin_t *skin = (skin_t *)g->mo->skin;
-					switch (xziptic & EZT_THOKMASK)
-					{
-					case EZT_THOK:
-						type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem;
-						break;
-					case EZT_SPIN:
-						type = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem;
-						break;
-					case EZT_REV:
-						type = skin->revitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem;
-						break;
-					}
-				}
-				if (type != MT_NULL)
-				{
-					if (type == MT_GHOST)
-					{
-						mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
-						mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
-					}
-					else
-					{
-						mobj = P_SpawnMobjFromMobj(g->mo, 0, 0, -FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
-						mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
-						mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
-						mobj->color = g->mo->color;
-						mobj->skin = g->mo->skin;
-						P_SetScale(mobj, (mobj->destscale = g->mo->scale));
-
-						if (type == MT_THOK) // spintrail-specific modification for MT_THOK
-						{
-							mobj->frame = FF_TRANS80;
-							mobj->fuse = mobj->tics;
-						}
-						mobj->tics = -1; // nope.
-					}
-					mobj->floorz = mobj->z;
-					mobj->ceilingz = mobj->z+mobj->height;
-					P_UnsetThingPosition(mobj);
-					mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
-					P_SetThingPosition(mobj);
-					if (!mobj->fuse)
-						mobj->fuse = 8;
-					P_SetTarget(&mobj->target, g->mo);
-				}
-			}
-			if (xziptic & EZT_HIT)
-			{ // Spawn hit poofs for killing things!
-				UINT16 i, count = READUINT16(g->p), health;
-				UINT32 type;
-				fixed_t x,y,z;
-				angle_t angle;
-				mobj_t *poof;
-				for (i = 0; i < count; i++)
-				{
-					//g->p += 4; // reserved
-					type = READUINT32(g->p);
-					health = READUINT16(g->p);
-					x = READFIXED(g->p);
-					y = READFIXED(g->p);
-					z = READFIXED(g->p);
-					angle = READANGLE(g->p);
-					if (!(mobjinfo[type].flags & MF_SHOOTABLE)
-					|| !(mobjinfo[type].flags & (MF_ENEMY|MF_MONITOR))
-					|| health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad.
-						continue;
-					poof = P_SpawnMobj(x, y, z, MT_GHOST);
-					poof->angle = angle;
-					poof->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
-					poof->health = 0;
-					P_SetMobjStateNF(poof, S_XPLD1);
-				}
-			}
-			if (xziptic & EZT_SPRITE)
-				g->mo->sprite = READUINT16(g->p);
-			if (xziptic & EZT_HEIGHT)
-			{
-				fixed_t temp = READINT16(g->p)<<FRACBITS;
-				g->mo->height = FixedMul(temp, g->mo->scale);
-			}
-		}
-
-		// Tick ghost colors (Super and Mario Invincibility flashing)
-		switch(g->color)
-		{
-		case GHC_SUPER: // Super (P_DoSuperStuff)
-			if (g->mo->skin)
-			{
-				skin_t *skin = (skin_t *)g->mo->skin;
-				g->mo->color = skin->supercolor;
-			}
-			else
-				g->mo->color = SKINCOLOR_SUPERGOLD1;
-			g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4);
-			break;
-		case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
-			g->mo->color = (UINT8)(SKINCOLOR_RUBY + (leveltime % (MAXSKINCOLORS - SKINCOLOR_RUBY))); // Passes through all saturated colours
-			break;
-		default:
-			break;
-		}
-
-#define follow g->mo->tracer
-		if (ziptic & GZT_FOLLOW)
-		{ // Even more...
-			UINT8 followtic = READUINT8(g->p);
-			fixed_t temp;
-			if (followtic & FZT_SPAWNED)
-			{
-				if (follow)
-					P_RemoveMobj(follow);
-				P_SetTarget(&follow, P_SpawnMobjFromMobj(g->mo, 0, 0, 0, MT_GHOST));
-				P_SetTarget(&follow->tracer, g->mo);
-				follow->tics = -1;
-				temp = READINT16(g->p)<<FRACBITS;
-				follow->height = FixedMul(follow->scale, temp);
-
-				if (followtic & FZT_LINKDRAW)
-					follow->flags2 |= MF2_LINKDRAW;
-
-				if (followtic & FZT_COLORIZED)
-					follow->colorized = true;
-
-				if (followtic & FZT_SKIN)
-					follow->skin = &skins[READUINT8(g->p)];
-			}
-			if (follow)
-			{
-				if (followtic & FZT_SCALE)
-					follow->destscale = READFIXED(g->p);
-				else
-					follow->destscale = g->mo->destscale;
-				if (follow->destscale != follow->scale)
-					P_SetScale(follow, follow->destscale);
-
-				P_UnsetThingPosition(follow);
-				temp = READINT16(g->p)<<8;
-				follow->x = g->mo->x + temp;
-				temp = READINT16(g->p)<<8;
-				follow->y = g->mo->y + temp;
-				temp = READINT16(g->p)<<8;
-				follow->z = g->mo->z + temp;
-				P_SetThingPosition(follow);
-				if (followtic & FZT_SKIN)
-					follow->sprite2 = READUINT8(g->p);
-				else
-					follow->sprite2 = 0;
-				follow->sprite = READUINT16(g->p);
-				follow->frame = (READUINT8(g->p)) | (g->mo->frame & FF_TRANSMASK);
-				follow->angle = g->mo->angle;
-				follow->color = READUINT8(g->p);
-
-				if (!(followtic & FZT_SPAWNED))
-				{
-					if (xziptic & EZT_FLIP)
-					{
-						follow->flags2 ^= MF2_OBJECTFLIP;
-						follow->eflags ^= MFE_VERTICALFLIP;
-					}
-				}
-			}
-		}
-		else if (follow)
-		{
-			P_RemoveMobj(follow);
-			P_SetTarget(&follow, NULL);
-		}
-		// Demo ends after ghost data.
-		if (*g->p == DEMOMARKER)
-		{
-			g->mo->momx = g->mo->momy = g->mo->momz = 0;
-#if 1 // freeze frame (maybe more useful for time attackers)
-			g->mo->colorized = true;
-			if (follow)
-				follow->colorized = true;
-#else // dissapearing act
-			g->mo->fuse = TICRATE;
-			if (follow)
-				follow->fuse = TICRATE;
-#endif
-			if (p)
-				p->next = g->next;
-			else
-				ghosts = g->next;
-			Z_Free(g);
-			continue;
-		}
-		p = g;
-#undef follow
-	}
-}
-
-void G_ReadMetalTic(mobj_t *metal)
-{
-	UINT8 ziptic;
-	UINT8 xziptic = 0;
-
-	if (!metal_p)
-		return;
-
-	if (!metal->health)
-	{
-		G_StopMetalDemo();
-		return;
-	}
-
-	switch (*metal_p)
-	{
-		case METALSNICE:
-			break;
-		case METALDEATH:
-			if (metal->tracer)
-				P_RemoveMobj(metal->tracer);
-			P_KillMobj(metal, NULL, NULL, 0);
-			/* FALLTHRU */
-		case DEMOMARKER:
-		default:
-			// end of demo data stream
-			G_StopMetalDemo();
-			return;
-	}
-	metal_p++;
-
-	ziptic = READUINT8(metal_p);
-
-	// Read changes from the tic
-	if (ziptic & GZT_XYZ)
-	{
-		P_TeleportMove(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p));
-		oldmetal.x = metal->x;
-		oldmetal.y = metal->y;
-		oldmetal.z = metal->z;
-	}
-	else
-	{
-		if (ziptic & GZT_MOMXY)
-		{
-			oldmetal.momx = READINT16(metal_p)<<8;
-			oldmetal.momy = READINT16(metal_p)<<8;
-		}
-		if (ziptic & GZT_MOMZ)
-			oldmetal.momz = READINT16(metal_p)<<8;
-		oldmetal.x += oldmetal.momx;
-		oldmetal.y += oldmetal.momy;
-		oldmetal.z += oldmetal.momz;
-	}
-	if (ziptic & GZT_ANGLE)
-		metal->angle = READUINT8(metal_p)<<24;
-	if (ziptic & GZT_FRAME)
-		oldmetal.frame = READUINT32(metal_p);
-	if (ziptic & GZT_SPR2)
-		oldmetal.sprite2 = READUINT8(metal_p);
-
-	// Set movement, position, and angle
-	// oldmetal contains where you're supposed to be.
-	metal->momx = oldmetal.momx;
-	metal->momy = oldmetal.momy;
-	metal->momz = oldmetal.momz;
-	P_UnsetThingPosition(metal);
-	metal->x = oldmetal.x;
-	metal->y = oldmetal.y;
-	metal->z = oldmetal.z;
-	P_SetThingPosition(metal);
-	metal->frame = oldmetal.frame;
-	metal->sprite2 = oldmetal.sprite2;
-
-	if (ziptic & GZT_EXTRA)
-	{ // But wait, there's more!
-		xziptic = READUINT8(metal_p);
-		if (xziptic & EZT_FLIP)
-		{
-			metal->eflags ^= MFE_VERTICALFLIP;
-			metal->flags2 ^= MF2_OBJECTFLIP;
-		}
-		if (xziptic & EZT_SCALE)
-		{
-			metal->destscale = READFIXED(metal_p);
-			if (metal->destscale != metal->scale)
-				P_SetScale(metal, metal->destscale);
-		}
-		if (xziptic & EZT_THOKMASK)
-		{ // Let's only spawn ONE of these per frame, thanks.
-			mobj_t *mobj;
-			INT32 type = -1;
-			if (metal->skin)
-			{
-				skin_t *skin = (skin_t *)metal->skin;
-				switch (xziptic & EZT_THOKMASK)
-				{
-				case EZT_THOK:
-					type = skin->thokitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].painchance : (UINT32)skin->thokitem;
-					break;
-				case EZT_SPIN:
-					type = skin->spinitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].damage : (UINT32)skin->spinitem;
-					break;
-				case EZT_REV:
-					type = skin->revitem < 0 ? (UINT32)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem;
-					break;
-				}
-			}
-			if (type != MT_NULL)
-			{
-				if (type == MT_GHOST)
-				{
-					mobj = P_SpawnGhostMobj(metal); // does a large portion of the work for us
-				}
-				else
-				{
-					mobj = P_SpawnMobjFromMobj(metal, 0, 0, -FixedDiv(FixedMul(metal->info->height, metal->scale) - metal->height,3*FRACUNIT), MT_THOK);
-					mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
-					mobj->frame = states[mobjinfo[type].spawnstate].frame;
-					mobj->angle = metal->angle;
-					mobj->color = metal->color;
-					mobj->skin = metal->skin;
-					P_SetScale(mobj, (mobj->destscale = metal->scale));
-
-					if (type == MT_THOK) // spintrail-specific modification for MT_THOK
-					{
-						mobj->frame = FF_TRANS70;
-						mobj->fuse = mobj->tics;
-					}
-					mobj->tics = -1; // nope.
-				}
-				mobj->floorz = mobj->z;
-				mobj->ceilingz = mobj->z+mobj->height;
-				P_UnsetThingPosition(mobj);
-				mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
-				P_SetThingPosition(mobj);
-				if (!mobj->fuse)
-					mobj->fuse = 8;
-				P_SetTarget(&mobj->target, metal);
-			}
-		}
-		if (xziptic & EZT_SPRITE)
-			metal->sprite = READUINT16(metal_p);
-		if (xziptic & EZT_HEIGHT)
-		{
-			fixed_t temp = READINT16(metal_p)<<FRACBITS;
-			metal->height = FixedMul(temp, metal->scale);
-		}
-	}
-
-#define follow metal->tracer
-		if (ziptic & GZT_FOLLOW)
-		{ // Even more...
-			UINT8 followtic = READUINT8(metal_p);
-			fixed_t temp;
-			if (followtic & FZT_SPAWNED)
-			{
-				if (follow)
-					P_RemoveMobj(follow);
-				P_SetTarget(&follow, P_SpawnMobjFromMobj(metal, 0, 0, 0, MT_GHOST));
-				P_SetTarget(&follow->tracer, metal);
-				follow->tics = -1;
-				temp = READINT16(metal_p)<<FRACBITS;
-				follow->height = FixedMul(follow->scale, temp);
-
-				if (followtic & FZT_LINKDRAW)
-					follow->flags2 |= MF2_LINKDRAW;
-
-				if (followtic & FZT_COLORIZED)
-					follow->colorized = true;
-
-				if (followtic & FZT_SKIN)
-					follow->skin = &skins[READUINT8(metal_p)];
-			}
-			if (follow)
-			{
-				if (followtic & FZT_SCALE)
-					follow->destscale = READFIXED(metal_p);
-				else
-					follow->destscale = metal->destscale;
-				if (follow->destscale != follow->scale)
-					P_SetScale(follow, follow->destscale);
-
-				P_UnsetThingPosition(follow);
-				temp = READINT16(metal_p)<<8;
-				follow->x = metal->x + temp;
-				temp = READINT16(metal_p)<<8;
-				follow->y = metal->y + temp;
-				temp = READINT16(metal_p)<<8;
-				follow->z = metal->z + temp;
-				P_SetThingPosition(follow);
-				if (followtic & FZT_SKIN)
-					follow->sprite2 = READUINT8(metal_p);
-				else
-					follow->sprite2 = 0;
-				follow->sprite = READUINT16(metal_p);
-				follow->frame = READUINT32(metal_p); // NOT & FF_FRAMEMASK here, so 32 bits
-				follow->angle = metal->angle;
-				follow->color = READUINT8(metal_p);
-
-				if (!(followtic & FZT_SPAWNED))
-				{
-					if (xziptic & EZT_FLIP)
-					{
-						follow->flags2 ^= MF2_OBJECTFLIP;
-						follow->eflags ^= MFE_VERTICALFLIP;
-					}
-				}
-			}
-		}
-		else if (follow)
-		{
-			P_RemoveMobj(follow);
-			P_SetTarget(&follow, NULL);
-		}
-#undef follow
-}
-
-void G_WriteMetalTic(mobj_t *metal)
-{
-	UINT8 ziptic = 0;
-	UINT8 *ziptic_p;
-	fixed_t height;
-
-	if (!demo_p) // demo_p will be NULL until the race start linedef executor is activated!
-		return;
-
-	WRITEUINT8(demo_p, METALSNICE);
-	ziptic_p = demo_p++; // the ziptic, written at the end of this function
-
-	#define MAXMOM (0xFFFF<<8)
-
-	// GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic.
-	if (abs(metal->x-oldmetal.x) > MAXMOM
-	|| abs(metal->y-oldmetal.y) > MAXMOM
-	|| abs(metal->z-oldmetal.z) > MAXMOM)
-	{
-		oldmetal.x = metal->x;
-		oldmetal.y = metal->y;
-		oldmetal.z = metal->z;
-		ziptic |= GZT_XYZ;
-		WRITEFIXED(demo_p,oldmetal.x);
-		WRITEFIXED(demo_p,oldmetal.y);
-		WRITEFIXED(demo_p,oldmetal.z);
-	}
-	else
-	{
-		// For moving normally:
-		// Store one full byte of movement, plus one byte of fractional movement.
-		INT16 momx = (INT16)((metal->x-oldmetal.x)>>8);
-		INT16 momy = (INT16)((metal->y-oldmetal.y)>>8);
-		if (momx != oldmetal.momx
-		|| momy != oldmetal.momy)
-		{
-			oldmetal.momx = momx;
-			oldmetal.momy = momy;
-			ziptic |= GZT_MOMXY;
-			WRITEINT16(demo_p,momx);
-			WRITEINT16(demo_p,momy);
-		}
-		momx = (INT16)((metal->z-oldmetal.z)>>8);
-		if (momx != oldmetal.momz)
-		{
-			oldmetal.momz = momx;
-			ziptic |= GZT_MOMZ;
-			WRITEINT16(demo_p,momx);
-		}
-
-		// This SHOULD set oldmetal.x/y/z to match metal->x/y/z
-		// but it keeps the fractional loss of one byte,
-		// so it will hopefully be made up for in future tics.
-		oldmetal.x += oldmetal.momx<<8;
-		oldmetal.y += oldmetal.momy<<8;
-		oldmetal.z += oldmetal.momz<<8;
-	}
-
-	#undef MAXMOM
-
-	// Only store the 8 most relevant bits of angle
-	// because exact values aren't too easy to discern to begin with when only 8 angles have different sprites
-	// and it does not affect movement at all anyway.
-	if (metal->player && metal->player->drawangle>>24 != oldmetal.angle)
-	{
-		oldmetal.angle = metal->player->drawangle>>24;
-		ziptic |= GZT_ANGLE;
-		WRITEUINT8(demo_p,oldmetal.angle);
-	}
-
-	// Store the sprite frame.
-	if ((metal->frame & FF_FRAMEMASK) != oldmetal.frame)
-	{
-		oldmetal.frame = metal->frame; // NOT & FF_FRAMEMASK here, so 32 bits
-		ziptic |= GZT_FRAME;
-		WRITEUINT32(demo_p,oldmetal.frame);
-	}
-
-	if (metal->sprite == SPR_PLAY
-	&& metal->sprite2 != oldmetal.sprite2)
-	{
-		oldmetal.sprite2 = metal->sprite2;
-		ziptic |= GZT_SPR2;
-		WRITEUINT8(demo_p,oldmetal.sprite2);
-	}
-
-	// Check for sprite set changes
-	if (metal->sprite != oldmetal.sprite)
-	{
-		oldmetal.sprite = metal->sprite;
-		ghostext.flags |= EZT_SPRITE;
-	}
-
-	if ((height = FixedDiv(metal->height, metal->scale)) != oldmetal.height)
-	{
-		oldmetal.height = height;
-		ghostext.flags |= EZT_HEIGHT;
-	}
-
-	if (ghostext.flags & ~(EZT_COLOR|EZT_HIT)) // these two aren't handled by metal ever
-	{
-		ziptic |= GZT_EXTRA;
-
-		if (ghostext.scale == ghostext.lastscale)
-			ghostext.flags &= ~EZT_SCALE;
-
-		WRITEUINT8(demo_p,ghostext.flags);
-		if (ghostext.flags & EZT_SCALE)
-		{
-			WRITEFIXED(demo_p,ghostext.scale);
-			ghostext.lastscale = ghostext.scale;
-		}
-		if (ghostext.flags & EZT_SPRITE)
-			WRITEUINT16(demo_p,oldmetal.sprite);
-		if (ghostext.flags & EZT_HEIGHT)
-		{
-			height >>= FRACBITS;
-			WRITEINT16(demo_p, height);
-		}
-		ghostext.flags = 0;
-	}
-
-	if (metal->player && metal->player->followmobj && !(metal->player->followmobj->sprite == SPR_NULL || (metal->player->followmobj->flags2 & MF2_DONTDRAW)))
-	{
-		INT16 temp;
-		UINT8 *followtic_p = demo_p++;
-		UINT8 followtic = 0;
-
-		ziptic |= GZT_FOLLOW;
-
-		if (metal->player->followmobj->skin)
-			followtic |= FZT_SKIN;
-
-		if (!(oldmetal.flags2 & MF2_AMBUSH))
-		{
-			followtic |= FZT_SPAWNED;
-			WRITEINT16(demo_p,metal->player->followmobj->info->height>>FRACBITS);
-			if (metal->player->followmobj->flags2 & MF2_LINKDRAW)
-				followtic |= FZT_LINKDRAW;
-			if (metal->player->followmobj->colorized)
-				followtic |= FZT_COLORIZED;
-			if (followtic & FZT_SKIN)
-				WRITEUINT8(demo_p,(UINT8)(((skin_t *)(metal->player->followmobj->skin))-skins));
-			oldmetal.flags2 |= MF2_AMBUSH;
-		}
-
-		if (metal->player->followmobj->scale != metal->scale)
-		{
-			followtic |= FZT_SCALE;
-			WRITEFIXED(demo_p,metal->player->followmobj->scale);
-		}
-
-		temp = (INT16)((metal->player->followmobj->x-metal->x)>>8);
-		WRITEINT16(demo_p,temp);
-		temp = (INT16)((metal->player->followmobj->y-metal->y)>>8);
-		WRITEINT16(demo_p,temp);
-		temp = (INT16)((metal->player->followmobj->z-metal->z)>>8);
-		WRITEINT16(demo_p,temp);
-		if (followtic & FZT_SKIN)
-			WRITEUINT8(demo_p,metal->player->followmobj->sprite2);
-		WRITEUINT16(demo_p,metal->player->followmobj->sprite);
-		WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits
-		WRITEUINT8(demo_p,metal->player->followmobj->color);
-
-		*followtic_p = followtic;
-	}
-	else
-		oldmetal.flags2 &= ~MF2_AMBUSH;
-
-	*ziptic_p = ziptic;
-
-	// attention here for the ticcmd size!
-	// latest demos with mouse aiming byte in ticcmd
-	if (demo_p >= demoend - 32)
-	{
-		G_StopMetalRecording(false); // no more space
-		return;
-	}
-}
-
-//
-// G_RecordDemo
-//
-void G_RecordDemo(const char *name)
-{
-	INT32 maxsize;
-
-	strcpy(demoname, name);
-	strcat(demoname, ".lmp");
-	maxsize = 1024*1024;
-	if (M_CheckParm("-maxdemo") && M_IsNextParm())
-		maxsize = atoi(M_GetNextParm()) * 1024;
-//	if (demobuffer)
-//		free(demobuffer);
-	demo_p = NULL;
-	demobuffer = malloc(maxsize);
-	demoend = demobuffer + maxsize;
-
-	demorecording = true;
-}
-
-void G_RecordMetal(void)
-{
-	INT32 maxsize;
-	maxsize = 1024*1024;
-	if (M_CheckParm("-maxdemo") && M_IsNextParm())
-		maxsize = atoi(M_GetNextParm()) * 1024;
-	demo_p = NULL;
-	demobuffer = malloc(maxsize);
-	demoend = demobuffer + maxsize;
-	metalrecording = true;
-}
-
-void G_BeginRecording(void)
-{
-	UINT8 i;
-	char name[16];
-	player_t *player = &players[consoleplayer];
-
-	if (demo_p)
-		return;
-	memset(name,0,sizeof(name));
-
-	demo_p = demobuffer;
-	demoflags = DF_GHOST|(modeattacking<<DF_ATTACKSHIFT);
-
-	// Setup header.
-	M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12;
-	WRITEUINT8(demo_p,VERSION);
-	WRITEUINT8(demo_p,SUBVERSION);
-	WRITEUINT16(demo_p,DEMOVERSION);
-
-	// demo checksum
-	demo_p += 16;
-
-	// game data
-	M_Memcpy(demo_p, "PLAY", 4); demo_p += 4;
-	WRITEINT16(demo_p,gamemap);
-	M_Memcpy(demo_p, mapmd5, 16); demo_p += 16;
-
-	WRITEUINT8(demo_p,demoflags);
-	switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
-	{
-	case ATTACKING_NONE: // 0
-		break;
-	case ATTACKING_RECORD: // 1
-		demotime_p = demo_p;
-		WRITEUINT32(demo_p,UINT32_MAX); // time
-		WRITEUINT32(demo_p,0); // score
-		WRITEUINT16(demo_p,0); // rings
-		break;
-	case ATTACKING_NIGHTS: // 2
-		demotime_p = demo_p;
-		WRITEUINT32(demo_p,UINT32_MAX); // time
-		WRITEUINT32(demo_p,0); // score
-		break;
-	default: // 3
-		break;
-	}
-
-	WRITEUINT32(demo_p,P_GetInitSeed());
-
-	// Name
-	for (i = 0; i < 16 && cv_playername.string[i]; i++)
-		name[i] = cv_playername.string[i];
-	for (; i < 16; i++)
-		name[i] = '\0';
-	M_Memcpy(demo_p,name,16);
-	demo_p += 16;
-
-	// Skin
-	for (i = 0; i < 16 && cv_skin.string[i]; i++)
-		name[i] = cv_skin.string[i];
-	for (; i < 16; i++)
-		name[i] = '\0';
-	M_Memcpy(demo_p,name,16);
-	demo_p += 16;
-
-	// Color
-	for (i = 0; i < 16 && cv_playercolor.string[i]; i++)
-		name[i] = cv_playercolor.string[i];
-	for (; i < 16; i++)
-		name[i] = '\0';
-	M_Memcpy(demo_p,name,16);
-	demo_p += 16;
-
-	// Stats
-	WRITEUINT8(demo_p,player->charability);
-	WRITEUINT8(demo_p,player->charability2);
-	WRITEUINT8(demo_p,player->actionspd>>FRACBITS);
-	WRITEUINT8(demo_p,player->mindash>>FRACBITS);
-	WRITEUINT8(demo_p,player->maxdash>>FRACBITS);
-	WRITEUINT8(demo_p,player->normalspeed>>FRACBITS);
-	WRITEUINT8(demo_p,player->runspeed>>FRACBITS);
-	WRITEUINT8(demo_p,player->thrustfactor);
-	WRITEUINT8(demo_p,player->accelstart);
-	WRITEUINT8(demo_p,player->acceleration);
-	WRITEUINT8(demo_p,player->height>>FRACBITS);
-	WRITEUINT8(demo_p,player->spinheight>>FRACBITS);
-	WRITEUINT8(demo_p,player->camerascale>>FRACBITS);
-	WRITEUINT8(demo_p,player->shieldscale>>FRACBITS);
-
-	// Trying to convert it back to % causes demo desync due to precision loss.
-	// Don't do it.
-	WRITEFIXED(demo_p, player->jumpfactor);
-
-	// And mobjtype_t is best with UINT32 too...
-	WRITEUINT32(demo_p, player->followitem);
-
-	// Save pflag data - see SendWeaponPref()
-	{
-		UINT8 buf = 0;
-		pflags_t pflags = 0;
-		if (cv_flipcam.value)
-		{
-			buf |= 0x01;
-			pflags |= PF_FLIPCAM;
-		}
-		if (cv_analog[0].value)
-		{
-			buf |= 0x02;
-			pflags |= PF_ANALOGMODE;
-		}
-		if (cv_directionchar[0].value)
-		{
-			buf |= 0x04;
-			pflags |= PF_DIRECTIONCHAR;
-		}
-		if (cv_autobrake.value)
-		{
-			buf |= 0x08;
-			pflags |= PF_AUTOBRAKE;
-		}
-		if (cv_usejoystick.value)
-			buf |= 0x10;
-		CV_SetValue(&cv_showinputjoy, !!(cv_usejoystick.value));
-
-		WRITEUINT8(demo_p,buf);
-		player->pflags = pflags;
-	}
-
-	// Save netvar data
-	CV_SaveNetVars(&demo_p);
-
-	memset(&oldcmd,0,sizeof(oldcmd));
-	memset(&oldghost,0,sizeof(oldghost));
-	memset(&ghostext,0,sizeof(ghostext));
-	ghostext.lastcolor = ghostext.color = GHC_NORMAL;
-	ghostext.lastscale = ghostext.scale = FRACUNIT;
-
-	if (player->mo)
-	{
-		oldghost.x = player->mo->x;
-		oldghost.y = player->mo->y;
-		oldghost.z = player->mo->z;
-		oldghost.angle = player->mo->angle>>24;
-
-		// preticker started us gravity flipped
-		if (player->mo->eflags & MFE_VERTICALFLIP)
-			ghostext.flags |= EZT_FLIP;
-	}
-}
-
-void G_BeginMetal(void)
-{
-	mobj_t *mo = players[consoleplayer].mo;
-
-#if 0
-	if (demo_p)
-		return;
-#endif
-
-	demo_p = demobuffer;
-
-	// Write header.
-	M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12;
-	WRITEUINT8(demo_p,VERSION);
-	WRITEUINT8(demo_p,SUBVERSION);
-	WRITEUINT16(demo_p,DEMOVERSION);
-
-	// demo checksum
-	demo_p += 16;
-
-	M_Memcpy(demo_p, "METL", 4); demo_p += 4;
-
-	memset(&ghostext,0,sizeof(ghostext));
-	ghostext.lastscale = ghostext.scale = FRACUNIT;
-
-	// Set up our memory.
-	memset(&oldmetal,0,sizeof(oldmetal));
-	oldmetal.x = mo->x;
-	oldmetal.y = mo->y;
-	oldmetal.z = mo->z;
-	oldmetal.angle = mo->angle>>24;
-}
-
-void G_SetDemoTime(UINT32 ptime, UINT32 pscore, UINT16 prings)
-{
-	if (!demorecording || !demotime_p)
-		return;
-	if (demoflags & DF_RECORDATTACK)
-	{
-		WRITEUINT32(demotime_p, ptime);
-		WRITEUINT32(demotime_p, pscore);
-		WRITEUINT16(demotime_p, prings);
-		demotime_p = NULL;
-	}
-	else if (demoflags & DF_NIGHTSATTACK)
-	{
-		WRITEUINT32(demotime_p, ptime);
-		WRITEUINT32(demotime_p, pscore);
-		demotime_p = NULL;
-	}
-}
-
-// Returns bitfield:
-// 1 == new demo has lower time
-// 2 == new demo has higher score
-// 4 == new demo has higher rings
-UINT8 G_CmpDemoTime(char *oldname, char *newname)
-{
-	UINT8 *buffer,*p;
-	UINT8 flags;
-	UINT32 oldtime, newtime, oldscore, newscore;
-	UINT16 oldrings, newrings, oldversion;
-	size_t bufsize ATTRUNUSED;
-	UINT8 c;
-	UINT16 s ATTRUNUSED;
-	UINT8 aflags = 0;
-
-	// load the new file
-	FIL_DefaultExtension(newname, ".lmp");
-	bufsize = FIL_ReadFile(newname, &buffer);
-	I_Assert(bufsize != 0);
-	p = buffer;
-
-	// read demo header
-	I_Assert(!memcmp(p, DEMOHEADER, 12));
-	p += 12; // DEMOHEADER
-	c = READUINT8(p); // VERSION
-	I_Assert(c == VERSION);
-	c = READUINT8(p); // SUBVERSION
-	I_Assert(c == SUBVERSION);
-	s = READUINT16(p);
-	I_Assert(s == DEMOVERSION);
-	p += 16; // demo checksum
-	I_Assert(!memcmp(p, "PLAY", 4));
-	p += 4; // PLAY
-	p += 2; // gamemap
-	p += 16; // map md5
-	flags = READUINT8(p); // demoflags
-
-	aflags = flags & (DF_RECORDATTACK|DF_NIGHTSATTACK);
-	I_Assert(aflags);
-	if (flags & DF_RECORDATTACK)
-	{
-		newtime = READUINT32(p);
-		newscore = READUINT32(p);
-		newrings = READUINT16(p);
-	}
-	else if (flags & DF_NIGHTSATTACK)
-	{
-		newtime = READUINT32(p);
-		newscore = READUINT32(p);
-		newrings = 0;
-	}
-	else // appease compiler
-		return 0;
-
-	Z_Free(buffer);
-
-	// load old file
-	FIL_DefaultExtension(oldname, ".lmp");
-	if (!FIL_ReadFile(oldname, &buffer))
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), oldname);
-		return UINT8_MAX;
-	}
-	p = buffer;
-
-	// read demo header
-	if (memcmp(p, DEMOHEADER, 12))
-	{
-		CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
-		Z_Free(buffer);
-		return UINT8_MAX;
-	} p += 12; // DEMOHEADER
-	p++; // VERSION
-	p++; // SUBVERSION
-	oldversion = READUINT16(p);
-	switch(oldversion) // demoversion
-	{
-	case DEMOVERSION: // latest always supported
-		break;
-	// too old, cannot support.
-	default:
-		CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
-		Z_Free(buffer);
-		return UINT8_MAX;
-	}
-	p += 16; // demo checksum
-	if (memcmp(p, "PLAY", 4))
-	{
-		CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
-		Z_Free(buffer);
-		return UINT8_MAX;
-	} p += 4; // "PLAY"
-	if (oldversion <= 0x0008)
-		p++; // gamemap
-	else
-		p += 2; // gamemap
-	p += 16; // mapmd5
-	flags = READUINT8(p);
-	if (!(flags & aflags))
-	{
-		CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname);
-		Z_Free(buffer);
-		return UINT8_MAX;
-	}
-	if (flags & DF_RECORDATTACK)
-	{
-		oldtime = READUINT32(p);
-		oldscore = READUINT32(p);
-		oldrings = READUINT16(p);
-	}
-	else if (flags & DF_NIGHTSATTACK)
-	{
-		oldtime = READUINT32(p);
-		oldscore = READUINT32(p);
-		oldrings = 0;
-	}
-	else // appease compiler
-		return UINT8_MAX;
-
-	Z_Free(buffer);
-
-	c = 0;
-	if (newtime < oldtime
-	|| (newtime == oldtime && (newscore > oldscore || newrings > oldrings)))
-		c |= 1; // Better time
-	if (newscore > oldscore
-	|| (newscore == oldscore && newtime < oldtime))
-		c |= 1<<1; // Better score
-	if (newrings > oldrings
-	|| (newrings == oldrings && newtime < oldtime))
-		c |= 1<<2; // Better rings
-	return c;
-}
-
-//
-// G_PlayDemo
-//
-void G_DeferedPlayDemo(const char *name)
-{
-	COM_BufAddText("playdemo \"");
-	COM_BufAddText(name);
-	COM_BufAddText("\"\n");
-}
-
-//
-// Start a demo from a .LMP file or from a wad resource
-//
-void G_DoPlayDemo(char *defdemoname)
-{
-	UINT8 i;
-	lumpnum_t l;
-	char skin[17],color[17],*n,*pdemoname;
-	UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration;
-	pflags_t pflags;
-	UINT32 randseed, followitem;
-	fixed_t camerascale,shieldscale,actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor,height,spinheight;
-	char msg[1024];
-
-	skin[16] = '\0';
-	color[16] = '\0';
-
-	n = defdemoname+strlen(defdemoname);
-	while (*n != '/' && *n != '\\' && n != defdemoname)
-		n--;
-	if (n != defdemoname)
-		n++;
-	pdemoname = ZZ_Alloc(strlen(n)+1);
-	strcpy(pdemoname,n);
-
-	// Internal if no extension, external if one exists
-	if (FIL_CheckExtension(defdemoname))
-	{
-		//FIL_DefaultExtension(defdemoname, ".lmp");
-		if (!FIL_ReadFile(defdemoname, &demobuffer))
-		{
-			snprintf(msg, 1024, M_GetText("Failed to read file '%s'.\n"), defdemoname);
-			CONS_Alert(CONS_ERROR, "%s", msg);
-			gameaction = ga_nothing;
-			M_StartMessage(msg, NULL, MM_NOTHING);
-			return;
-		}
-		demo_p = demobuffer;
-	}
-	// load demo resource from WAD
-	else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
-	{
-		snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname);
-		CONS_Alert(CONS_ERROR, "%s", msg);
-		gameaction = ga_nothing;
-		M_StartMessage(msg, NULL, MM_NOTHING);
-		return;
-	}
-	else // it's an internal demo
-		demobuffer = demo_p = W_CacheLumpNum(l, PU_STATIC);
-
-	// read demo header
-	gameaction = ga_nothing;
-	demoplayback = true;
-	if (memcmp(demo_p, DEMOHEADER, 12))
-	{
-		snprintf(msg, 1024, M_GetText("%s is not a SRB2 replay file.\n"), pdemoname);
-		CONS_Alert(CONS_ERROR, "%s", msg);
-		M_StartMessage(msg, NULL, MM_NOTHING);
-		Z_Free(pdemoname);
-		Z_Free(demobuffer);
-		demoplayback = false;
-		titledemo = false;
-		return;
-	}
-	demo_p += 12; // DEMOHEADER
-
-	version = READUINT8(demo_p);
-	subversion = READUINT8(demo_p);
-	demoversion = READUINT16(demo_p);
-	switch(demoversion)
-	{
-	case DEMOVERSION: // latest always supported
-		break;
-	// too old, cannot support.
-	default:
-		snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname);
-		CONS_Alert(CONS_ERROR, "%s", msg);
-		M_StartMessage(msg, NULL, MM_NOTHING);
-		Z_Free(pdemoname);
-		Z_Free(demobuffer);
-		demoplayback = false;
-		titledemo = false;
-		return;
-	}
-	demo_p += 16; // demo checksum
-	if (memcmp(demo_p, "PLAY", 4))
-	{
-		snprintf(msg, 1024, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemoname);
-		CONS_Alert(CONS_ERROR, "%s", msg);
-		M_StartMessage(msg, NULL, MM_NOTHING);
-		Z_Free(pdemoname);
-		Z_Free(demobuffer);
-		demoplayback = false;
-		titledemo = false;
-		return;
-	}
-	demo_p += 4; // "PLAY"
-	gamemap = READINT16(demo_p);
-	demo_p += 16; // mapmd5
-
-	demoflags = READUINT8(demo_p);
-	modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT;
-	CON_ToggleOff();
-
-	hu_demoscore = 0;
-	hu_demotime = UINT32_MAX;
-	hu_demorings = 0;
-
-	switch (modeattacking)
-	{
-	case ATTACKING_NONE: // 0
-		break;
-	case ATTACKING_RECORD: // 1
-		hu_demotime  = READUINT32(demo_p);
-		hu_demoscore = READUINT32(demo_p);
-		hu_demorings = READUINT16(demo_p);
-		break;
-	case ATTACKING_NIGHTS: // 2
-		hu_demotime  = READUINT32(demo_p);
-		hu_demoscore = READUINT32(demo_p);
-		break;
-	default: // 3
-		modeattacking = ATTACKING_NONE;
-		break;
-	}
-
-	// Random seed
-	randseed = READUINT32(demo_p);
-
-	// Player name
-	M_Memcpy(player_names[0],demo_p,16);
-	demo_p += 16;
-
-	// Skin
-	M_Memcpy(skin,demo_p,16);
-	demo_p += 16;
-
-	// Color
-	M_Memcpy(color,demo_p,16);
-	demo_p += 16;
-
-	charability = READUINT8(demo_p);
-	charability2 = READUINT8(demo_p);
-	actionspd = (fixed_t)READUINT8(demo_p)<<FRACBITS;
-	mindash = (fixed_t)READUINT8(demo_p)<<FRACBITS;
-	maxdash = (fixed_t)READUINT8(demo_p)<<FRACBITS;
-	normalspeed = (fixed_t)READUINT8(demo_p)<<FRACBITS;
-	runspeed = (fixed_t)READUINT8(demo_p)<<FRACBITS;
-	thrustfactor = READUINT8(demo_p);
-	accelstart = READUINT8(demo_p);
-	acceleration = READUINT8(demo_p);
-	height = (fixed_t)READUINT8(demo_p)<<FRACBITS;
-	spinheight = (fixed_t)READUINT8(demo_p)<<FRACBITS;
-	camerascale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
-	shieldscale = (fixed_t)READUINT8(demo_p)<<FRACBITS;
-	jumpfactor = READFIXED(demo_p);
-	followitem = READUINT32(demo_p);
-
-	// pflag data
-	{
-		UINT8 buf = READUINT8(demo_p);
-		pflags = 0;
-		if (buf & 0x01)
-			pflags |= PF_FLIPCAM;
-		if (buf & 0x02)
-			pflags |= PF_ANALOGMODE;
-		if (buf & 0x04)
-			pflags |= PF_DIRECTIONCHAR;
-		if (buf & 0x08)
-			pflags |= PF_AUTOBRAKE;
-		CV_SetValue(&cv_showinputjoy, !!(buf & 0x10));
-	}
-
-	// net var data
-	CV_LoadNetVars(&demo_p);
-
-	// Sigh ... it's an empty demo.
-	if (*demo_p == DEMOMARKER)
-	{
-		snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname);
-		CONS_Alert(CONS_ERROR, "%s", msg);
-		M_StartMessage(msg, NULL, MM_NOTHING);
-		Z_Free(pdemoname);
-		Z_Free(demobuffer);
-		demoplayback = false;
-		titledemo = false;
-		return;
-	}
-
-	Z_Free(pdemoname);
-
-	memset(&oldcmd,0,sizeof(oldcmd));
-	memset(&oldghost,0,sizeof(oldghost));
-
-	if (VERSION != version || SUBVERSION != subversion)
-		CONS_Alert(CONS_WARNING, M_GetText("Demo version does not match game version. Desyncs may occur.\n"));
-
-	// didn't start recording right away.
-	demo_start = false;
-
-	// Set skin
-	SetPlayerSkin(0, skin);
-
-#ifdef HAVE_BLUA
-	LUAh_MapChange(gamemap);
-#endif
-	displayplayer = consoleplayer = 0;
-	memset(playeringame,0,sizeof(playeringame));
-	playeringame[0] = true;
-	P_SetRandSeed(randseed);
-	G_InitNew(false, G_BuildMapName(gamemap), true, true, false);
-
-	// Set color
-	for (i = 0; i < MAXSKINCOLORS; i++)
-		if (!stricmp(Color_Names[i],color))
-		{
-			players[0].skincolor = i;
-			break;
-		}
-	CV_StealthSetValue(&cv_playercolor, players[0].skincolor);
-	if (players[0].mo)
-	{
-		players[0].mo->color = players[0].skincolor;
-		oldghost.x = players[0].mo->x;
-		oldghost.y = players[0].mo->y;
-		oldghost.z = players[0].mo->z;
-	}
-
-	// Set saved attribute values
-	// No cheat checking here, because even if they ARE wrong...
-	// it would only break the replay if we clipped them.
-	players[0].camerascale = camerascale;
-	players[0].shieldscale = shieldscale;
-	players[0].charability = charability;
-	players[0].charability2 = charability2;
-	players[0].actionspd = actionspd;
-	players[0].mindash = mindash;
-	players[0].maxdash = maxdash;
-	players[0].normalspeed = normalspeed;
-	players[0].runspeed = runspeed;
-	players[0].thrustfactor = thrustfactor;
-	players[0].accelstart = accelstart;
-	players[0].acceleration = acceleration;
-	players[0].height = height;
-	players[0].spinheight = spinheight;
-	players[0].jumpfactor = jumpfactor;
-	players[0].followitem = followitem;
-	players[0].pflags = pflags;
-
-	demo_start = true;
-}
-
-void G_AddGhost(char *defdemoname)
-{
-	INT32 i;
-	lumpnum_t l;
-	char name[17],skin[17],color[17],*n,*pdemoname,md5[16];
-	demoghost *gh;
-	UINT8 flags;
-	UINT8 *buffer,*p;
-	mapthing_t *mthing;
-	UINT16 count, ghostversion;
-
-	name[16] = '\0';
-	skin[16] = '\0';
-	color[16] = '\0';
-
-	n = defdemoname+strlen(defdemoname);
-	while (*n != '/' && *n != '\\' && n != defdemoname)
-		n--;
-	if (n != defdemoname)
-		n++;
-	pdemoname = ZZ_Alloc(strlen(n)+1);
-	strcpy(pdemoname,n);
-
-	// Internal if no extension, external if one exists
-	if (FIL_CheckExtension(defdemoname))
-	{
-		//FIL_DefaultExtension(defdemoname, ".lmp");
-		if (!FIL_ReadFileTag(defdemoname, &buffer, PU_LEVEL))
-		{
-			CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), defdemoname);
-			Z_Free(pdemoname);
-			return;
-		}
-		p = buffer;
-	}
-	// load demo resource from WAD
-	else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR)
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("Failed to read lump '%s'.\n"), defdemoname);
-		Z_Free(pdemoname);
-		return;
-	}
-	else // it's an internal demo
-		buffer = p = W_CacheLumpNum(l, PU_LEVEL);
-
-	// read demo header
-	if (memcmp(p, DEMOHEADER, 12))
-	{
-		CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Not a SRB2 replay.\n"), pdemoname);
-		Z_Free(pdemoname);
-		Z_Free(buffer);
-		return;
-	} p += 12; // DEMOHEADER
-	p++; // VERSION
-	p++; // SUBVERSION
-	ghostversion = READUINT16(p);
-	switch(ghostversion)
-	{
-	case DEMOVERSION: // latest always supported
-		break;
-	// too old, cannot support.
-	default:
-		CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname);
-		Z_Free(pdemoname);
-		Z_Free(buffer);
-		return;
-	}
-	M_Memcpy(md5, p, 16); p += 16; // demo checksum
-	for (gh = ghosts; gh; gh = gh->next)
-		if (!memcmp(md5, gh->checksum, 16)) // another ghost in the game already has this checksum?
-		{ // Don't add another one, then!
-			CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (MD5 was matched)\n", pdemoname);
-			Z_Free(pdemoname);
-			Z_Free(buffer);
-			return;
-		}
-	if (memcmp(p, "PLAY", 4))
-	{
-		CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo format unacceptable.\n"), pdemoname);
-		Z_Free(pdemoname);
-		Z_Free(buffer);
-		return;
-	} p += 4; // "PLAY"
-	if (ghostversion <= 0x0008)
-		p++; // gamemap
-	else
-		p += 2; // gamemap
-	p += 16; // mapmd5 (possibly check for consistency?)
-	flags = READUINT8(p);
-	if (!(flags & DF_GHOST))
-	{
-		CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname);
-		Z_Free(pdemoname);
-		Z_Free(buffer);
-		return;
-	}
-	switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
-	{
-	case ATTACKING_NONE: // 0
-		break;
-	case ATTACKING_RECORD: // 1
-		p += 10; // demo time, score, and rings
-		break;
-	case ATTACKING_NIGHTS: // 2
-		p += 8; // demo time left, score
-		break;
-	default: // 3
-		break;
-	}
-
-	p += 4; // random seed
-
-	// Player name (TODO: Display this somehow if it doesn't match cv_playername!)
-	M_Memcpy(name, p,16);
-	p += 16;
-
-	// Skin
-	M_Memcpy(skin, p,16);
-	p += 16;
-
-	// Color
-	M_Memcpy(color, p,16);
-	p += 16;
-
-	// Ghosts do not have a player structure to put this in.
-	p++; // charability
-	p++; // charability2
-	p++; // actionspd
-	p++; // mindash
-	p++; // maxdash
-	p++; // normalspeed
-	p++; // runspeed
-	p++; // thrustfactor
-	p++; // accelstart
-	p++; // acceleration
-	p++; // height
-	p++; // spinheight
-	p++; // camerascale
-	p++; // shieldscale
-	p += 4; // jumpfactor
-	p += 4; // followitem
-
-	p++; // pflag data
-
-	// net var data
-	count = READUINT16(p);
-	while (count--)
-	{
-		p += 2;
-		SKIPSTRING(p);
-		p++;
-	}
-
-	if (*p == DEMOMARKER)
-	{
-		CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), pdemoname);
-		Z_Free(pdemoname);
-		Z_Free(buffer);
-		return;
-	}
-
-	gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL);
-	gh->next = ghosts;
-	gh->buffer = buffer;
-	M_Memcpy(gh->checksum, md5, 16);
-	gh->p = p;
-
-	ghosts = gh;
-
-	gh->version = ghostversion;
-	mthing = playerstarts[0];
-	I_Assert(mthing);
-	{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
-		fixed_t z,f,c;
-		fixed_t offset = mthing->z << FRACBITS;
-		gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST);
-		gh->mo->angle = FixedAngle(mthing->angle << FRACBITS);
-		f = gh->mo->floorz;
-		c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height;
-		if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP))
-		{
-			z = c - offset;
-			if (z < f)
-				z = f;
-		}
-		else
-		{
-			z = f + offset;
-			if (z > c)
-				z = c;
-		}
-		gh->mo->z = z;
-	}
-
-	gh->oldmo.x = gh->mo->x;
-	gh->oldmo.y = gh->mo->y;
-	gh->oldmo.z = gh->mo->z;
-
-	// Set skin
-	gh->mo->skin = &skins[0];
-	for (i = 0; i < numskins; i++)
-		if (!stricmp(skins[i].name,skin))
-		{
-			gh->mo->skin = &skins[i];
-			break;
-		}
-	gh->oldmo.skin = gh->mo->skin;
-
-	// Set color
-	gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor;
-	for (i = 0; i < MAXSKINCOLORS; i++)
-		if (!stricmp(Color_Names[i],color))
-		{
-			gh->mo->color = (UINT8)i;
-			break;
-		}
-	gh->oldmo.color = gh->mo->color;
-
-	gh->mo->state = states+S_PLAY_STND;
-	gh->mo->sprite = gh->mo->state->sprite;
-	gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK);
-	//gh->mo->frame = tr_trans30<<FF_TRANSSHIFT;
-	gh->mo->flags2 |= MF2_DONTDRAW;
-	gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible
-	gh->mo->tics = -1;
-
-	CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname);
-	Z_Free(pdemoname);
-}
-
-//
-// G_TimeDemo
-// NOTE: name is a full filename for external demos
-//
-static INT32 restorecv_vidwait;
-
-void G_TimeDemo(const char *name)
-{
-	nodrawers = M_CheckParm("-nodraw");
-	noblit = M_CheckParm("-noblit");
-	restorecv_vidwait = cv_vidwait.value;
-	if (cv_vidwait.value)
-		CV_Set(&cv_vidwait, "0");
-	timingdemo = true;
-	singletics = true;
-	framecount = 0;
-	demostarttime = I_GetTime();
-	G_DeferedPlayDemo(name);
-}
-
-void G_DoPlayMetal(void)
-{
-	lumpnum_t l;
-	mobj_t *mo = NULL;
-	thinker_t *th;
-
-	// it's an internal demo
-	if ((l = W_CheckNumForName(va("%sMS",G_BuildMapName(gamemap)))) == LUMPERROR)
-	{
-		CONS_Alert(CONS_WARNING, M_GetText("No bot recording for this map.\n"));
-		return;
-	}
-	else
-		metalbuffer = metal_p = W_CacheLumpNum(l, PU_STATIC);
-
-	// find metal sonic
-	for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
-	{
-		if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
-			continue;
-
-		mo = (mobj_t *)th;
-		if (mo->type != MT_METALSONIC_RACE)
-			continue;
-
-		break;
-	}
-	if (th == &thlist[THINK_MOBJ])
-	{
-		CONS_Alert(CONS_ERROR, M_GetText("Failed to find bot entity.\n"));
-		Z_Free(metalbuffer);
-		return;
-	}
-
-	// read demo header
-    metal_p += 12; // DEMOHEADER
-	metal_p++; // VERSION
-	metal_p++; // SUBVERSION
-	metalversion = READUINT16(metal_p);
-	switch(metalversion)
-	{
-	case DEMOVERSION: // latest always supported
-		break;
-	// too old, cannot support.
-	default:
-		CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, format version incompatible.\n"));
-		Z_Free(metalbuffer);
-		return;
-	}
-	metal_p += 16; // demo checksum
-	if (memcmp(metal_p, "METL", 4))
-	{
-		CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, wasn't recorded in Metal format.\n"));
-		Z_Free(metalbuffer);
-		return;
-	} metal_p += 4; // "METL"
-
-	// read initial tic
-	memset(&oldmetal,0,sizeof(oldmetal));
-	oldmetal.x = mo->x;
-	oldmetal.y = mo->y;
-	oldmetal.z = mo->z;
-	metalplayback = mo;
-}
-
-void G_DoneLevelLoad(void)
-{
-	CONS_Printf(M_GetText("Loaded level in %f sec\n"), (double)(I_GetTime() - demostarttime) / TICRATE);
-	framecount = 0;
-	demostarttime = I_GetTime();
-}
-
-/*
-===================
-=
-= G_CheckDemoStatus
-=
-= Called after a death or level completion to allow demos to be cleaned up
-= Returns true if a new demo loop action will take place
-===================
-*/
-
-// Stops metal sonic's demo. Separate from other functions because metal + replays can coexist
-void G_StopMetalDemo(void)
-{
-
-	// Metal Sonic finishing doesn't end the game, dammit.
-	Z_Free(metalbuffer);
-	metalbuffer = NULL;
-	metalplayback = NULL;
-	metal_p = NULL;
-}
-
-// Stops metal sonic recording.
-ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill)
-{
-	boolean saved = false;
-	if (demo_p)
-	{
-		UINT8 *p = demobuffer+16; // checksum position
-		if (kill)
-			WRITEUINT8(demo_p, METALDEATH); // add the metal death marker
-		else
-			WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
-#ifdef NOMD5
-		{
-			UINT8 i;
-			for (i = 0; i < 16; i++, p++)
-				*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
-		}
-#else
-		md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file.
-#endif
-		saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file.
-	}
-	free(demobuffer);
-	metalrecording = false;
-	if (saved)
-		I_Error("Saved to %sMS.LMP", G_BuildMapName(gamemap));
-	I_Error("Failed to save demo!");
-}
-
-// reset engine variable set for the demos
-// called from stopdemo command, map command, and g_checkdemoStatus.
-void G_StopDemo(void)
-{
-	Z_Free(demobuffer);
-	demobuffer = NULL;
-	demoplayback = false;
-	titledemo = false;
-	timingdemo = false;
-	singletics = false;
-
-	if (gamestate == GS_INTERMISSION)
-		Y_EndIntermission(); // cleanup
-
-	G_SetGamestate(GS_NULL);
-	wipegamestate = GS_NULL;
-	SV_StopServer();
-	SV_ResetServer();
-}
-
-boolean G_CheckDemoStatus(void)
-{
-	boolean saved;
-
-	while (ghosts)
-	{
-		demoghost *next = ghosts->next;
-		Z_Free(ghosts);
-		ghosts = next;
-	}
-	ghosts = NULL;
-
-
-	// DO NOT end metal sonic demos here
-
-	if (timingdemo)
-	{
-		INT32 demotime;
-		double f1, f2;
-		demotime = I_GetTime() - demostarttime;
-		if (!demotime)
-			return true;
-		G_StopDemo();
-		timingdemo = false;
-		f1 = (double)demotime;
-		f2 = (double)framecount*TICRATE;
-
-		CONS_Printf(M_GetText("timed %u gametics in %d realtics - %u frames\n%f seconds, %f avg fps\n"),
-			leveltime,demotime,(UINT32)framecount,f1/TICRATE,f2/f1);
-
-		// CSV-readable timedemo results, for external parsing
-		if (timedemo_csv)
-		{
-			FILE *f;
-			const char *csvpath = va("%s"PATHSEP"%s", srb2home, "timedemo.csv");
-			const char *header = "id,demoname,seconds,avgfps,leveltime,demotime,framecount,ticrate,rendermode,vidmode,vidwidth,vidheight,procbits\n";
-			const char *rowformat = "\"%s\",\"%s\",%f,%f,%u,%d,%u,%u,%u,%u,%u,%u,%u\n";
-			boolean headerrow = !FIL_FileExists(csvpath);
-			UINT8 procbits = 0;
-
-			// Bitness
-			if (sizeof(void*) == 4)
-				procbits = 32;
-			else if (sizeof(void*) == 8)
-				procbits = 64;
-
-			f = fopen(csvpath, "a+");
-
-			if (f)
-			{
-				if (headerrow)
-					fputs(header, f);
-				fprintf(f, rowformat,
-					timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits);
-				fclose(f);
-				CONS_Printf("Timedemo results saved to '%s'\n", csvpath);
-			}
-			else
-			{
-				// Just print the CSV output to console
-				CON_LogMessage(header);
-				CONS_Printf(rowformat,
-					timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits);
-			}
-		}
-
-		if (restorecv_vidwait != cv_vidwait.value)
-			CV_SetValue(&cv_vidwait, restorecv_vidwait);
-		D_AdvanceDemo();
-		return true;
-	}
-
-	if (demoplayback)
-	{
-		if (singledemo)
-			I_Quit();
-		G_StopDemo();
-
-		if (modeattacking)
-			M_EndModeAttackRun();
-		else
-			D_AdvanceDemo();
-
-		return true;
-	}
-
-	if (demorecording)
-	{
-		UINT8 *p = demobuffer+16; // checksum position
-#ifdef NOMD5
-		UINT8 i;
-		WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
-		for (i = 0; i < 16; i++, p++)
-			*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
-#else
-		WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
-		md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file.
-#endif
-		saved = FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer); // finally output the file.
-		free(demobuffer);
-		demorecording = false;
-
-		if (modeattacking != ATTACKING_RECORD)
-		{
-			if (saved)
-				CONS_Printf(M_GetText("Demo %s recorded\n"), demoname);
-			else
-				CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname);
-		}
-		return true;
-	}
-
-	return false;
-}
-
 //
 // G_SetGamestate
 //
diff --git a/src/g_game.h b/src/g_game.h
index c4c40d84b..b4216a001 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -17,6 +17,7 @@
 #include "doomdef.h"
 #include "doomstat.h"
 #include "d_event.h"
+#include "g_demo.h"
 
 extern char gamedatafilename[64];
 extern char timeattackfolder[64];
@@ -31,21 +32,6 @@ extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1];
 extern player_t players[MAXPLAYERS];
 extern boolean playeringame[MAXPLAYERS];
 
-// ======================================
-// DEMO playback/recording related stuff.
-// ======================================
-
-// demoplaying back and demo recording
-extern boolean demoplayback, titledemo, demorecording, timingdemo;
-extern tic_t demostarttime;
-
-// Quit after playing a demo from cmdline.
-extern boolean singledemo;
-extern boolean demo_start;
-extern boolean demosynced;
-
-extern mobj_t *metalplayback;
-
 // gametic at level start
 extern tic_t levelstarttic;
 
@@ -173,7 +159,6 @@ void G_DoLoadLevel(boolean resetplayer);
 void G_StartTitleCard(void);
 void G_PreLevelTitleCard(void);
 boolean G_IsTitleCardAvailable(void);
-void G_DeferedPlayDemo(const char *demo);
 
 // Can be called by the startup code or M_Responder, calls P_SetupLevel.
 void G_LoadGame(UINT32 slot, INT16 mapoverride);
@@ -184,54 +169,6 @@ void G_SaveGame(UINT32 slot);
 
 void G_SaveGameOver(UINT32 slot, boolean modifylives);
 
-// Only called by startup code.
-void G_RecordDemo(const char *name);
-void G_RecordMetal(void);
-void G_BeginRecording(void);
-void G_BeginMetal(void);
-
-// Only called by shutdown code.
-void G_SetDemoTime(UINT32 ptime, UINT32 pscore, UINT16 prings);
-UINT8 G_CmpDemoTime(char *oldname, char *newname);
-
-typedef enum
-{
-	GHC_NORMAL = 0,
-	GHC_SUPER,
-	GHC_FIREFLOWER,
-	GHC_INVINCIBLE,
-	GHC_NIGHTSSKIN, // not actually a colour
-	GHC_RETURNSKIN // ditto
-} ghostcolor_t;
-
-// Record/playback tics
-void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
-void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum);
-void G_GhostAddThok(void);
-void G_GhostAddSpin(void);
-void G_GhostAddRev(void);
-void G_GhostAddColor(ghostcolor_t color);
-void G_GhostAddFlip(void);
-void G_GhostAddScale(fixed_t scale);
-void G_GhostAddHit(mobj_t *victim);
-void G_WriteGhostTic(mobj_t *ghost);
-void G_ConsGhostTic(void);
-void G_GhostTicker(void);
-void G_ReadMetalTic(mobj_t *metal);
-void G_WriteMetalTic(mobj_t *metal);
-void G_SaveMetal(UINT8 **buffer);
-void G_LoadMetal(UINT8 **buffer);
-
-void G_DoPlayDemo(char *defdemoname);
-void G_TimeDemo(const char *name);
-void G_AddGhost(char *defdemoname);
-void G_DoPlayMetal(void);
-void G_DoneLevelLoad(void);
-void G_StopMetalDemo(void);
-ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill);
-void G_StopDemo(void);
-boolean G_CheckDemoStatus(void);
-
 extern UINT32 gametypedefaultrules[NUMGAMETYPES];
 extern UINT32 gametypetol[NUMGAMETYPES];
 extern INT16 gametyperankings[NUMGAMETYPES];

From 1a142340884f9a4216a845c7482e6acd2e0aecf4 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Thu, 19 Mar 2020 20:13:39 +0000
Subject: [PATCH 128/251] update Makefile, CMakeLists.txt and MSVC project
 files

---
 src/CMakeLists.txt                   | 2 ++
 src/Makefile                         | 1 +
 src/sdl/Srb2SDL-vc10.vcxproj         | 2 ++
 src/sdl/Srb2SDL-vc10.vcxproj.filters | 6 ++++++
 4 files changed, 11 insertions(+)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index bc4a6114e..e1e7689a6 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -16,6 +16,7 @@ set(SRB2_CORE_SOURCES
 	f_finale.c
 	f_wipe.c
 	filesrch.c
+	g_demo.c
 	g_game.c
 	g_input.c
 	hu_stuff.c
@@ -71,6 +72,7 @@ set(SRB2_CORE_HEADERS
 	f_finale.h
 	fastcmp.h
 	filesrch.h
+	g_demo.h
 	g_game.h
 	g_input.h
 	g_state.h
diff --git a/src/Makefile b/src/Makefile
index 701f2cfda..43cf48905 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -424,6 +424,7 @@ OBJS:=$(i_main_o) \
 		$(OBJDIR)/z_zone.o   \
 		$(OBJDIR)/f_finale.o \
 		$(OBJDIR)/f_wipe.o   \
+		$(OBJDIR)/g_demo.o   \
 		$(OBJDIR)/g_game.o   \
 		$(OBJDIR)/g_input.o  \
 		$(OBJDIR)/am_map.o   \
diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj
index 7e260f4c0..6335b3028 100644
--- a/src/sdl/Srb2SDL-vc10.vcxproj
+++ b/src/sdl/Srb2SDL-vc10.vcxproj
@@ -213,6 +213,7 @@
     <ClInclude Include="..\fastcmp.h" />
     <ClInclude Include="..\filesrch.h" />
     <ClInclude Include="..\f_finale.h" />
+    <ClInclude Include="..\g_demo.h" />
     <ClInclude Include="..\g_game.h" />
     <ClInclude Include="..\g_input.h" />
     <ClInclude Include="..\g_state.h" />
@@ -364,6 +365,7 @@
     <ClCompile Include="..\filesrch.c" />
     <ClCompile Include="..\f_finale.c" />
     <ClCompile Include="..\f_wipe.c" />
+    <ClCompile Include="..\g_demo.c" />
     <ClCompile Include="..\g_game.c" />
     <ClCompile Include="..\g_input.c" />
     <ClCompile Include="..\hardware\hw3sound.c" />
diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters
index 21820551a..a226e8397 100644
--- a/src/sdl/Srb2SDL-vc10.vcxproj.filters
+++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters
@@ -180,6 +180,9 @@
     <ClInclude Include="..\f_finale.h">
       <Filter>F_Frame</Filter>
     </ClInclude>
+    <ClInclude Include="..\g_demo.h">
+      <Filter>G_Game</Filter>
+    </ClInclude>
     <ClInclude Include="..\g_game.h">
       <Filter>G_Game</Filter>
     </ClInclude>
@@ -600,6 +603,9 @@
     <ClCompile Include="..\f_wipe.c">
       <Filter>F_Frame</Filter>
     </ClCompile>
+    <ClCompile Include="..\g_demo.c">
+      <Filter>G_Game</Filter>
+    </ClCompile>
     <ClCompile Include="..\g_game.c">
       <Filter>G_Game</Filter>
     </ClCompile>

From dd76be16cbe6cfe075376fff1b358e1e57d305b2 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Thu, 19 Mar 2020 20:42:51 +0000
Subject: [PATCH 129/251] Create G_FreeGhosts, for the benefit of
 G_DeferedInitNew (assuming it actually needs to do `ghosts = NULL;` at all)

---
 src/g_demo.c | 21 +++++++++++++--------
 src/g_demo.h |  1 +
 src/g_game.c |  2 +-
 3 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/src/g_demo.c b/src/g_demo.c
index 22cd34ad5..9adafae54 100644
--- a/src/g_demo.c
+++ b/src/g_demo.c
@@ -2223,6 +2223,18 @@ void G_AddGhost(char *defdemoname)
 	Z_Free(pdemoname);
 }
 
+// Clean up all ghosts
+void G_FreeGhosts(void)
+{
+	while (ghosts)
+	{
+		demoghost *next = ghosts->next;
+		Z_Free(ghosts);
+		ghosts = next;
+	}
+	ghosts = NULL;
+}
+
 //
 // G_TimeDemo
 // NOTE: name is a full filename for external demos
@@ -2389,14 +2401,7 @@ boolean G_CheckDemoStatus(void)
 {
 	boolean saved;
 
-	while (ghosts)
-	{
-		demoghost *next = ghosts->next;
-		Z_Free(ghosts);
-		ghosts = next;
-	}
-	ghosts = NULL;
-
+	G_FreeGhosts();
 
 	// DO NOT end metal sonic demos here
 
diff --git a/src/g_demo.h b/src/g_demo.h
index 89be6e343..df25042c4 100644
--- a/src/g_demo.h
+++ b/src/g_demo.h
@@ -75,6 +75,7 @@ void G_DeferedPlayDemo(const char *demo);
 void G_DoPlayDemo(char *defdemoname);
 void G_TimeDemo(const char *name);
 void G_AddGhost(char *defdemoname);
+void G_FreeGhosts(void);
 void G_DoPlayMetal(void);
 void G_DoneLevelLoad(void);
 void G_StopMetalDemo(void);
diff --git a/src/g_game.c b/src/g_game.c
index fb70e2995..e22961b9a 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -4490,7 +4490,7 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, b
 
 	if (demoplayback)
 		COM_BufAddText("stopdemo\n");
-	ghosts = NULL;
+	G_FreeGhosts(); // TODO: do we actually need to do this?
 
 	// this leave the actual game if needed
 	SV_StartSinglePlayerServer();

From 6610150bfeb11796cacad3d6453ab98030f1cd4b Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Thu, 19 Mar 2020 20:43:56 +0000
Subject: [PATCH 130/251] We definitely don't need these files to compile!

---
 src/g_demo.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/g_demo.c b/src/g_demo.c
index 9adafae54..c589482b6 100644
--- a/src/g_demo.c
+++ b/src/g_demo.c
@@ -16,14 +16,12 @@
 #include "d_main.h"
 #include "d_player.h"
 #include "d_clisrv.h"
-//#include "f_finale.h"
 #include "p_setup.h"
 #include "i_system.h"
 #include "m_random.h"
 #include "p_local.h"
 #include "r_draw.h"
 #include "r_main.h"
-//#include "s_sound.h"
 #include "g_game.h"
 #include "g_demo.h"
 #include "m_cheat.h"

From 4236ae7c083f388d0c184c165a724ade3560f242 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Thu, 19 Mar 2020 21:10:23 +0000
Subject: [PATCH 131/251] We don't need m_cheat.h either in g_demo.c

---
 src/g_demo.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/g_demo.c b/src/g_demo.c
index c589482b6..199f7d68e 100644
--- a/src/g_demo.c
+++ b/src/g_demo.c
@@ -24,7 +24,6 @@
 #include "r_main.h"
 #include "g_game.h"
 #include "g_demo.h"
-#include "m_cheat.h"
 #include "m_misc.h"
 #include "m_menu.h"
 #include "m_argv.h"

From 5eaa73b6ac8194a17a6af54f46fd7a2b7be46746 Mon Sep 17 00:00:00 2001
From: Jaime Passos <lazymyuutsu@gmail.com>
Date: Thu, 19 Mar 2020 19:09:34 -0300
Subject: [PATCH 132/251] Fix lib_setSpriteInfo indexes being off-by-one

---
 src/lua_infolib.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index 6760b4203..d099b24a9 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -389,10 +389,7 @@ static int lib_setSpriteInfo(lua_State *L)
 		lua_Integer i = 0;
 		const char *str = NULL;
 		if (lua_isnumber(L, 2))
-		{
 			i = lua_tointeger(L, 2);
-			i++; // shift index in case of missing rotsprite support
-		}
 		else
 			str = luaL_checkstring(L, 2);
 

From 78ec210896d2afffccbb17557510923f3ab8723f Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Thu, 19 Mar 2020 18:55:10 -0500
Subject: [PATCH 133/251] hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

---
 src/m_menu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index 3ebaedca2..6047bada9 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -5405,9 +5405,10 @@ static void M_HandleLevelPlatter(INT32 choice)
 		case KEY_LEFTARROW:
 			if (levellistmode == LLM_CREATESERVER && !lsrow)
 			{
+				INT32 startinggametype = cv_newgametype.value;
 				do
 					CV_AddValue(&cv_newgametype, -1);
-				while (!M_GametypeHasLevels(cv_newgametype.value));
+				while (cv_newgametype.value != startinggametype && !M_GametypeHasLevels(cv_newgametype.value));
 				S_StartSound(NULL,sfx_menu1);
 				lscol = 0;
 

From 892a8dd6e7832d2f3139b7315946b953d2ce3daf Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Fri, 20 Mar 2020 18:55:29 +0100
Subject: [PATCH 134/251] Make SRB2 flat like Earth

---
 src/am_map.c            |  33 +---
 src/dehacked.c          |   3 +-
 src/doomdef.h           |   5 -
 src/hardware/hw_main.c  | 305 ++----------------------------
 src/hardware/hw_trick.c |   4 -
 src/lua_baselib.c       |   6 -
 src/lua_libs.h          |   2 -
 src/lua_maplib.c        |  26 ---
 src/lua_mobjlib.c       |   8 -
 src/lua_script.c        |  10 -
 src/m_cheat.c           |  24 ---
 src/p_enemy.c           |   5 -
 src/p_floor.c           |   4 -
 src/p_local.h           |   4 -
 src/p_map.c             |  85 +--------
 src/p_maputl.c          |  28 ---
 src/p_maputl.h          |   2 -
 src/p_mobj.c            | 208 +++++---------------
 src/p_mobj.h            |   2 -
 src/p_saveg.c           |  26 +--
 src/p_setup.c           |   6 -
 src/p_sight.c           |  24 ---
 src/p_slopes.c          |   5 -
 src/p_slopes.h          |   3 -
 src/p_spec.c            |  10 +-
 src/p_user.c            |  93 +--------
 src/r_bsp.c             | 136 +++-----------
 src/r_defs.h            |  10 -
 src/r_draw.c            |   2 -
 src/r_draw.h            |   6 -
 src/r_draw8.c           |   2 -
 src/r_draw8_npo2.c      |   5 -
 src/r_main.c            |   2 -
 src/r_plane.c           |  40 +---
 src/r_plane.h           |   9 +-
 src/r_segs.c            | 407 +++-------------------------------------
 src/r_things.c          |  29 +--
 src/screen.c            |   4 -
 src/screen.h            |   2 -
 39 files changed, 153 insertions(+), 1432 deletions(-)

diff --git a/src/am_map.c b/src/am_map.c
index 234df1abd..cdbaaf80a 100644
--- a/src/am_map.c
+++ b/src/am_map.c
@@ -920,10 +920,8 @@ static inline void AM_drawWalls(void)
 {
 	size_t i;
 	static mline_t l;
-#ifdef ESLOPE
 	fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
 	fixed_t backf1 = 0, backf2 = 0, backc1 = 0, backc2 = 0; // back floor ceiling ends
-#endif
 
 	for (i = 0; i < numlines; i++)
 	{
@@ -931,7 +929,7 @@ static inline void AM_drawWalls(void)
 		l.a.y = lines[i].v1->y >> FRACTOMAPBITS;
 		l.b.x = lines[i].v2->x >> FRACTOMAPBITS;
 		l.b.y = lines[i].v2->y >> FRACTOMAPBITS;
-#ifdef ESLOPE
+
 #define SLOPEPARAMS(slope, end1, end2, normalheight) \
 		if (slope) { \
 			end1 = P_GetZAt(slope, lines[i].v1->x, lines[i].v1->y); \
@@ -946,7 +944,6 @@ static inline void AM_drawWalls(void)
 			SLOPEPARAMS(lines[i].backsector->c_slope, backc1,  backc2,  lines[i].backsector->ceilingheight)
 		}
 #undef SLOPEPARAMS
-#endif
 
 		if (!lines[i].backsector) // 1-sided
 		{
@@ -955,19 +952,11 @@ static inline void AM_drawWalls(void)
 			else
 				AM_drawMline(&l, WALLCOLORS);
 		}
-#ifdef ESLOPE
 		else if ((backf1 == backc1 && backf2 == backc2) // Back is thok barrier
 				 || (frontf1 == frontc1 && frontf2 == frontc2)) // Front is thok barrier
 		{
 			if (backf1 == backc1 && backf2 == backc2
 				&& frontf1 == frontc1 && frontf2 == frontc2) // BOTH are thok barriers
-#else
-		else if (lines[i].backsector->floorheight == lines[i].backsector->ceilingheight // Back is thok barrier
-				 || lines[i].frontsector->floorheight == lines[i].frontsector->ceilingheight) // Front is thok barrier
-		{
-			if (lines[i].backsector->floorheight == lines[i].backsector->ceilingheight
-				&& lines[i].frontsector->floorheight == lines[i].frontsector->ceilingheight) // BOTH are thok barriers
-#endif
 			{
 				if (lines[i].flags & ML_NOCLIMB)
 					AM_drawMline(&l, NOCLIMBTSWALLCOLORS);
@@ -985,20 +974,10 @@ static inline void AM_drawWalls(void)
 		else
 		{
 			if (lines[i].flags & ML_NOCLIMB) {
-#ifdef ESLOPE
 				if (backf1 != frontf1 || backf2 != frontf2) {
-#else
-				if (lines[i].backsector->floorheight
-						!= lines[i].frontsector->floorheight) {
-#endif
 					AM_drawMline(&l, NOCLIMBFDWALLCOLORS); // floor level change
 				}
-#ifdef ESLOPE
 				else if (backc1 != frontc1 || backc2 != frontc2) {
-#else
-				else if (lines[i].backsector->ceilingheight
-						!= lines[i].frontsector->ceilingheight) {
-#endif
 					AM_drawMline(&l, NOCLIMBCDWALLCOLORS); // ceiling level change
 				}
 				else
@@ -1006,20 +985,10 @@ static inline void AM_drawWalls(void)
 			}
 			else
 			{
-#ifdef ESLOPE
 				if (backf1 != frontf1 || backf2 != frontf2) {
-#else
-				if (lines[i].backsector->floorheight
-						!= lines[i].frontsector->floorheight) {
-#endif
 					AM_drawMline(&l, FDWALLCOLORS); // floor level change
 				}
-#ifdef ESLOPE
 				else if (backc1 != frontc1 || backc2 != frontc2) {
-#else
-				else if (lines[i].backsector->ceilingheight
-						!= lines[i].frontsector->ceilingheight) {
-#endif
 					AM_drawMline(&l, CDWALLCOLORS); // ceiling level change
 				}
 				else
diff --git a/src/dehacked.c b/src/dehacked.c
index 588b78142..c6cd0b9e5 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -9678,11 +9678,10 @@ struct {
 	// Node flags
 	{"NF_SUBSECTOR",NF_SUBSECTOR}, // Indicate a leaf.
 #endif
-#ifdef ESLOPE
+
 	// Slope flags
 	{"SL_NOPHYSICS",SL_NOPHYSICS},
 	{"SL_DYNAMIC",SL_DYNAMIC},
-#endif
 
 	// Angles
 	{"ANG1",ANG1},
diff --git a/src/doomdef.h b/src/doomdef.h
index 71c885019..2ed66aecc 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -562,14 +562,9 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
 // None of these that are disabled in the normal build are guaranteed to work perfectly
 // Compile them at your own risk!
 
-/// Kalaron/Eternity Engine slope code (SRB2CB ported)
-#define ESLOPE
-
-#ifdef ESLOPE
 /// Backwards compatibility with SRB2CB's slope linedef types.
 ///	\note	A simple shim that prints a warning.
 #define ESLOPE_TYPESHIM
-#endif
 
 ///	Allows the use of devmode in multiplayer. AKA "fishcake"
 //#define NETGAME_DEVMODE
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index efed9b602..c56f0ec06 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -42,9 +42,7 @@
 #include "../m_cheat.h"
 #include "../f_finale.h"
 #include "../r_things.h" // R_GetShadowZ
-#ifdef ESLOPE
 #include "../p_slopes.h"
-#endif
 #include "hw_md2.h"
 
 #ifdef NEWCLIP
@@ -486,9 +484,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 	angle_t angle = 0;
 	FSurfaceInfo    Surf;
 	fixed_t tempxsow, tempytow;
-#ifdef ESLOPE
 	pslope_t *slope = NULL;
-#endif
 
 	static FOutVector *planeVerts = NULL;
 	static UINT16 numAllocedPlaneVerts = 0;
@@ -499,7 +495,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 	if (!xsub->planepoly)
 		return;
 
-#ifdef ESLOPE
 	// Get the slope pointer to simplify future code
 	if (FOFsector)
 	{
@@ -519,7 +514,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 	// Set fixedheight to the slope's height from our viewpoint, if we have a slope
 	if (slope)
 		fixedheight = P_GetZAt(slope, viewx, viewy);
-#endif
 
 	height = FIXED_TO_FLOAT(fixedheight);
 
@@ -669,13 +663,11 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 		v3d->y = height;
 		v3d->z = pv->y;
 
-#ifdef ESLOPE
 		if (slope)
 		{
 			fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED(pv->x), FLOAT_TO_FIXED(pv->y));
 			v3d->y = FIXED_TO_FLOAT(fixedheight);
 		}
-#endif
 	}
 
 	// only useful for flat coloured triangles
@@ -693,10 +685,8 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 	{
 		sector_t *psector = gr_frontsector;
 
-#ifdef ESLOPE
 		if (slope)
 			fixedheight = P_GetZAt(slope, psector->soundorg.x, psector->soundorg.y);
-#endif
 
 		if (psector->ffloors)
 		{
@@ -1068,7 +1058,6 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 	float pegt, pegb, pegmul;
 	float height = 0.0f, bheight = 0.0f;
 
-#ifdef ESLOPE
 	float endrealtop, endrealbot, endtop, endbot;
 	float endpegt, endpegb, endpegmul;
 	float endheight = 0.0f, endbheight = 0.0f;
@@ -1076,7 +1065,6 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 	// compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly
 	// use this as a temp var to store P_GetZAt's return value each time
 	fixed_t temp;
-#endif
 
 	fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x);
 	fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].z); // not a typo
@@ -1095,23 +1083,18 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 	pegb = wallVerts[0].t;
 	pegmul = (pegb - pegt) / (top - bot);
 
-#ifdef ESLOPE
 	endrealtop = endtop = wallVerts[2].y;
 	endrealbot = endbot = wallVerts[1].y;
 	endpegt = wallVerts[2].t;
 	endpegb = wallVerts[1].t;
 	endpegmul = (endpegb - endpegt) / (endtop - endbot);
-#endif
 
 	for (i = 0; i < sector->numlights; i++)
 	{
-#ifdef ESLOPE
-        if (endtop < endrealbot)
-#endif
-		if (top < realbot)
+        if (endtop < endrealbot && top < realbot)
 			return;
 
-	// There's a compiler warning here if this comment isn't here because of indentation
+		// There's a compiler warning here if this comment isn't here because of indentation
 		if (!(list[i].flags & FF_NOSHADE))
 		{
 			if (pfloor && (pfloor->flags & FF_FOG))
@@ -1143,7 +1126,6 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 		else
 			solid = false;
 
-#ifdef ESLOPE
 		if (list[i].slope)
 		{
 			temp = P_GetZAt(list[i].slope, v1x, v1y);
@@ -1165,26 +1147,15 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 			else
 				bheight = endbheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight);
 		}
-#else
-		height = FIXED_TO_FLOAT(list[i].height);
-		if (solid)
-			bheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight);
-#endif
 
-#ifdef ESLOPE
-		if (endheight >= endtop)
-#endif
-		if (height >= top)
+		if (endheight >= endtop && height >= top)
 		{
 			if (solid && top > bheight)
 				top = bheight;
-#ifdef ESLOPE
 			if (solid && endtop > endbheight)
 				endtop = endbheight;
-#endif
 		}
 
-#ifdef ESLOPE
 		if (i + 1 < sector->numlights)
 		{
 			if (list[i+1].slope)
@@ -1202,21 +1173,8 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 			bheight = realbot;
 			endbheight = endrealbot;
 		}
-#else
-		if (i + 1 < sector->numlights)
-		{
-			bheight = FIXED_TO_FLOAT(list[i+1].height);
-		}
-		else
-		{
-			bheight = realbot;
-		}
-#endif
 
-#ifdef ESLOPE
-		if (endbheight >= endtop)
-#endif
-		if (bheight >= top)
+		if (endbheight >= endtop && bheight >= top)
 			continue;
 
 		//Found a break;
@@ -1225,15 +1183,12 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 		if (bot < realbot)
 			bot = realbot;
 
-#ifdef ESLOPE
 		endbot = endbheight;
 
 		if (endbot < endrealbot)
 			endbot = endrealbot;
-#endif
 		Surf->FlatColor.s.alpha = alpha;
 
-#ifdef ESLOPE
 		wallVerts[3].t = pegt + ((realtop - top) * pegmul);
 		wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul);
 		wallVerts[0].t = pegt + ((realtop - bot) * pegmul);
@@ -1244,14 +1199,6 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 		wallVerts[2].y = endtop;
 		wallVerts[0].y = bot;
 		wallVerts[1].y = endbot;
-#else
-		wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul);
-		wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul);
-
-		// set top/bottom coords
-		wallVerts[2].y = wallVerts[3].y = top;
-		wallVerts[0].y = wallVerts[1].y = bot;
-#endif
 
 		if (cutflag & FF_FOG)
 			HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture, true, lightnum, colormap);
@@ -1261,22 +1208,16 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 			HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap);
 
 		top = bot;
-#ifdef ESLOPE
 		endtop = endbot;
-#endif
 	}
 
 	bot = realbot;
-#ifdef ESLOPE
 	endbot = endrealbot;
-	if (endtop <= endrealbot)
-#endif
-	if (top <= realbot)
+	if (endtop <= endrealbot && top <= realbot)
 		return;
 
 	Surf->FlatColor.s.alpha = alpha;
 
-#ifdef ESLOPE
 	wallVerts[3].t = pegt + ((realtop - top) * pegmul);
 	wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul);
 	wallVerts[0].t = pegt + ((realtop - bot) * pegmul);
@@ -1287,14 +1228,6 @@ static void HWR_SplitWall(sector_t *sector, wallVert3D *wallVerts, INT32 texnum,
 	wallVerts[2].y = endtop;
 	wallVerts[0].y = bot;
 	wallVerts[1].y = endbot;
-#else
-    wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul);
-    wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul);
-
-    // set top/bottom coords
-    wallVerts[2].y = wallVerts[3].y = top;
-    wallVerts[0].y = wallVerts[1].y = bot;
-#endif
 
 	if (cutflag & FF_FOG)
 		HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture, true, lightnum, colormap);
@@ -1339,19 +1272,15 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 
 	fixed_t worldtop, worldbottom;
 	fixed_t worldhigh = 0, worldlow = 0;
-#ifdef ESLOPE
 	fixed_t worldtopslope, worldbottomslope;
 	fixed_t worldhighslope = 0, worldlowslope = 0;
 	fixed_t v1x, v1y, v2x, v2y;
-#endif
 
 	GLTexture_t *grTex = NULL;
 	float cliplow = 0.0f, cliphigh = 0.0f;
 	INT32 gr_midtexture;
 	fixed_t h, l; // 3D sides and 2s middle textures
-#ifdef ESLOPE
 	fixed_t hS, lS;
-#endif
 
 	FUINT lightnum = 0; // shut up compiler
 	extracolormap_t *colormap;
@@ -1370,13 +1299,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 	ve.x = ((polyvertex_t *)gr_curline->pv2)->x;
 	ve.y = ((polyvertex_t *)gr_curline->pv2)->y;
 
-#ifdef ESLOPE
 	v1x = FLOAT_TO_FIXED(vs.x);
 	v1y = FLOAT_TO_FIXED(vs.y);
 	v2x = FLOAT_TO_FIXED(ve.x);
 	v2y = FLOAT_TO_FIXED(ve.y);
-#endif
-#ifdef ESLOPE
 
 #define SLOPEPARAMS(slope, end1, end2, normalheight) \
 	if (slope) { \
@@ -1387,10 +1313,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 
 	SLOPEPARAMS(gr_frontsector->c_slope, worldtop,    worldtopslope,    gr_frontsector->ceilingheight)
 	SLOPEPARAMS(gr_frontsector->f_slope, worldbottom, worldbottomslope, gr_frontsector->floorheight)
-#else
-	worldtop    = gr_frontsector->ceilingheight;
-	worldbottom = gr_frontsector->floorheight;
-#endif
 
 	// remember vertices ordering
 	//  3--2
@@ -1440,14 +1362,9 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 		boolean bothceilingssky = false; // turned on if both back and front ceilings are sky
 		boolean bothfloorssky = false; // likewise, but for floors
 
-#ifdef ESLOPE
 		SLOPEPARAMS(gr_backsector->c_slope, worldhigh, worldhighslope, gr_backsector->ceilingheight)
 		SLOPEPARAMS(gr_backsector->f_slope, worldlow,  worldlowslope,  gr_backsector->floorheight)
 #undef SLOPEPARAMS
-#else
-		worldhigh = gr_backsector->ceilingheight;
-		worldlow  = gr_backsector->floorheight;
-#endif
 
 		// hack to allow height changes in outdoor areas
 		// This is what gets rid of the upper textures if there should be sky
@@ -1470,12 +1387,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			gr_bottomtexture = R_GetTextureNum(gr_sidedef->bottomtexture);
 
 		// check TOP TEXTURE
-		if ((
-#ifdef ESLOPE
-			worldhighslope < worldtopslope ||
-#endif
-            worldhigh < worldtop
-            ) && gr_toptexture)
+		if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gr_toptexture)
 		{
 			{
 				fixed_t texturevpegtop; // top
@@ -1485,15 +1397,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				// PEGGING
 				if (gr_linedef->flags & ML_DONTPEGTOP)
 					texturevpegtop = 0;
-#ifdef ESLOPE
 				else if (gr_linedef->flags & ML_EFFECT1)
 					texturevpegtop = worldhigh + textureheight[gr_sidedef->toptexture] - worldtop;
 				else
 					texturevpegtop = gr_backsector->ceilingheight + textureheight[gr_sidedef->toptexture] - gr_frontsector->ceilingheight;
-#else
-                else
-                    texturevpegtop = worldhigh + textureheight[gr_sidedef->toptexture] - worldtop;
-#endif
 
 				texturevpegtop += gr_sidedef->rowoffset;
 
@@ -1505,7 +1412,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
 				wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
 
-#ifdef ESLOPE
 				// Adjust t value for sloped walls
 				if (!(gr_linedef->flags & ML_EFFECT1))
 				{
@@ -1528,19 +1434,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 					wallVerts[3].t = wallVerts[0].t - (worldtop - worldhigh) * grTex->scaleY;
 					wallVerts[2].t = wallVerts[1].t - (worldtopslope - worldhighslope) * grTex->scaleY;
 				}
-#endif
 			}
 
 			// set top/bottom coords
-#ifdef ESLOPE
 			wallVerts[3].y = FIXED_TO_FLOAT(worldtop);
 			wallVerts[0].y = FIXED_TO_FLOAT(worldhigh);
 			wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope);
 			wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope);
-#else
-			wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop);
-			wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldhigh);
-#endif
 
 			if (gr_frontsector->numlights)
 				HWR_SplitWall(gr_frontsector, wallVerts, gr_toptexture, &Surf, FF_CUTLEVEL, NULL);
@@ -1552,9 +1452,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 
 		// check BOTTOM TEXTURE
 		if ((
-#ifdef ESLOPE
 			worldlowslope > worldbottomslope ||
-#endif
             worldlow > worldbottom) && gr_bottomtexture) //only if VISIBLE!!!
 		{
 			{
@@ -1563,19 +1461,12 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				grTex = HWR_GetTexture(gr_bottomtexture);
 
 				// PEGGING
-#ifdef ESLOPE
 				if (!(gr_linedef->flags & ML_DONTPEGBOTTOM))
 					texturevpegbottom = 0;
 				else if (gr_linedef->flags & ML_EFFECT1)
 					texturevpegbottom = worldbottom - worldlow;
 				else
 					texturevpegbottom = gr_frontsector->floorheight - gr_backsector->floorheight;
-#else
-				if (gr_linedef->flags & ML_DONTPEGBOTTOM)
-					texturevpegbottom = worldbottom - worldlow;
-                else
-                    texturevpegbottom = 0;
-#endif
 
 				texturevpegbottom += gr_sidedef->rowoffset;
 
@@ -1587,7 +1478,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
 				wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
 
-#ifdef ESLOPE
 				// Adjust t value for sloped walls
 				if (!(gr_linedef->flags & ML_EFFECT1))
 				{
@@ -1610,19 +1500,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 					wallVerts[0].t = (texturevpegbottom + worldlow - worldbottom) * grTex->scaleY;
 					wallVerts[1].t = (texturevpegbottom + worldlowslope - worldbottomslope) * grTex->scaleY;
 				}
-#endif
 			}
 
 			// set top/bottom coords
-#ifdef ESLOPE
 			wallVerts[3].y = FIXED_TO_FLOAT(worldlow);
 			wallVerts[0].y = FIXED_TO_FLOAT(worldbottom);
 			wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope);
 			wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope);
-#else
-			wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldlow);
-			wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom);
-#endif
 
 			if (gr_frontsector->numlights)
 				HWR_SplitWall(gr_frontsector, wallVerts, gr_bottomtexture, &Surf, FF_CUTLEVEL, NULL);
@@ -1692,16 +1576,10 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			else
 #endif
             {
-#ifdef ESLOPE
 				popentop = min(worldtop, worldhigh);
 				popenbottom = max(worldbottom, worldlow);
-#else
-				popentop = min(front->ceilingheight, back->ceilingheight);
-				popenbottom = max(front->floorheight, back->floorheight);
-#endif
 			}
 
-#ifdef ESLOPE
 			if (gr_linedef->flags & ML_EFFECT2)
 			{
 				if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
@@ -1716,9 +1594,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				}
 			}
 			else if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
-#else
-            if (gr_linedef->flags & ML_DONTPEGBOTTOM)
-#endif
 			{
 				polybottom = popenbottom + gr_sidedef->rowoffset;
 				polytop = polybottom + textureheight[gr_midtexture]*repeats;
@@ -1750,11 +1625,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 
 			{
 				// PEGGING
-#ifdef ESLOPE
 				if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3))
-#else
-				if (gr_linedef->flags & ML_DONTPEGBOTTOM)
-#endif
 					texturevpeg = textureheight[gr_sidedef->midtexture]*repeats - h + polybottom;
 				else
 					texturevpeg = polytop - h;
@@ -1773,7 +1644,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h);
 			wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l);
 
-#ifdef ESLOPE
 			// Correct to account for slopes
 			{
 				fixed_t midtextureslant;
@@ -1816,7 +1686,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				wallVerts[2].y = FIXED_TO_FLOAT(h);
 				wallVerts[1].y = FIXED_TO_FLOAT(l);
 			}
-#endif
 
 			// set alpha for transparent walls (new boom and legacy linedef types)
 			// ooops ! this do not work at all because render order we should render it in backtofront order
@@ -1918,12 +1787,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				if (gr_backsector->ceilingpic != skyflatnum) // don't cull if back sector is also sky
 				{
 					wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space
-#ifdef ESLOPE
 					wallVerts[0].y = FIXED_TO_FLOAT(worldtop);
 					wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope);
-#else
-					wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop);
-#endif
 					HWR_DrawSkyWall(wallVerts, &Surf);
 				}
 			}
@@ -1932,12 +1797,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			{
 				if (gr_backsector->floorpic != skyflatnum) // don't cull if back sector is also sky
 				{
-#ifdef ESLOPE
 					wallVerts[3].y = FIXED_TO_FLOAT(worldbottom);
 					wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope);
-#else
-					wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldbottom);
-#endif
 					wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); // draw to bottom of map space
 					HWR_DrawSkyWall(wallVerts, &Surf);
 				}
@@ -1954,12 +1815,9 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			{
 				fixed_t     texturevpeg;
 				// PEGGING
-#ifdef ESLOPE
 				if ((gr_linedef->flags & (ML_DONTPEGBOTTOM|ML_EFFECT2)) == (ML_DONTPEGBOTTOM|ML_EFFECT2))
 					texturevpeg = gr_frontsector->floorheight + textureheight[gr_sidedef->midtexture] - gr_frontsector->ceilingheight + gr_sidedef->rowoffset;
-				else
-#endif
-				if (gr_linedef->flags & ML_DONTPEGBOTTOM)
+				else if (gr_linedef->flags & ML_DONTPEGBOTTOM)
 					texturevpeg = worldbottom + textureheight[gr_sidedef->midtexture] - worldtop + gr_sidedef->rowoffset;
 				else
 					// top of texture at top
@@ -1972,7 +1830,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
 				wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
 
-#ifdef ESLOPE
 				// Texture correction for slopes
 				if (gr_linedef->flags & ML_EFFECT2) {
 					wallVerts[3].t += (gr_frontsector->ceilingheight - worldtop) * grTex->scaleY;
@@ -1986,19 +1843,14 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 					wallVerts[0].t = wallVerts[3].t - (worldbottom-worldtop) * grTex->scaleY;
 					wallVerts[1].t = wallVerts[2].t - (worldbottomslope-worldtopslope) * grTex->scaleY;
 				}
-#endif
 			}
-#ifdef ESLOPE
+
 			//Set textures properly on single sided walls that are sloped
 			wallVerts[3].y = FIXED_TO_FLOAT(worldtop);
 			wallVerts[0].y = FIXED_TO_FLOAT(worldbottom);
 			wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope);
 			wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope);
-#else
-			// set top/bottom coords
-			wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop);
-			wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom);
-#endif
+
 			// I don't think that solid walls can use translucent linedef types...
 			if (gr_frontsector->numlights)
 				HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTLEVEL, NULL);
@@ -2016,22 +1868,14 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			if (gr_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector
 			{
 				wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space
-#ifdef ESLOPE
 				wallVerts[0].y = FIXED_TO_FLOAT(worldtop);
 				wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope);
-#else
-				wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop);
-#endif
 				HWR_DrawSkyWall(wallVerts, &Surf);
 			}
 			if (gr_frontsector->floorpic == skyflatnum)
 			{
-#ifdef ESLOPE
 				wallVerts[3].y = FIXED_TO_FLOAT(worldbottom);
 				wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope);
-#else
-				wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldbottom);
-#endif
 				wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); // draw to bottom of map space
 				HWR_DrawSkyWall(wallVerts, &Surf);
 			}
@@ -2072,7 +1916,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 					texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
 				}
 
-#ifdef ESLOPE
 				h  = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight;
 				hS = *rover->t_slope ? P_GetZAt(*rover->t_slope, v2x, v2y) : *rover->topheight;
 				l  = *rover->b_slope ? P_GetZAt(*rover->b_slope, v1x, v1y) : *rover->bottomheight;
@@ -2089,19 +1932,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				wallVerts[2].y = FIXED_TO_FLOAT(hS);
 				wallVerts[0].y = FIXED_TO_FLOAT(l);
 				wallVerts[1].y = FIXED_TO_FLOAT(lS);
-#else
-				h = *rover->topheight;
-				l = *rover->bottomheight;
-				if (h > highcut)
-					h = highcut;
-				if (l < lowcut)
-					l = lowcut;
-				//Hurdler: HW code starts here
-				//FIXME: check if peging is correct
-				// set top/bottom coords
-				wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h);
-				wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l);
-#endif
 				if (rover->flags & FF_FOG)
 				{
 					wallVerts[3].t = wallVerts[2].t = 0;
@@ -2113,9 +1943,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				{
 					fixed_t texturevpeg;
 					boolean attachtobottom = false;
-#ifdef ESLOPE
 					boolean slopeskew = false; // skew FOF walls with slopes?
-#endif
 
 					// Wow, how was this missing from OpenGL for so long?
 					// ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software
@@ -2124,22 +1952,17 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 					{
 						texturevpeg = sides[newline->sidenum[0]].rowoffset;
 						attachtobottom = !!(newline->flags & ML_DONTPEGBOTTOM);
-#ifdef ESLOPE
 						slopeskew = !!(newline->flags & ML_DONTPEGTOP);
-#endif
 					}
 					else
 					{
 						texturevpeg = sides[rover->master->sidenum[0]].rowoffset;
 						attachtobottom = !!(gr_linedef->flags & ML_DONTPEGBOTTOM);
-#ifdef ESLOPE
 						slopeskew = !!(rover->master->flags & ML_DONTPEGTOP);
-#endif
 					}
 
 					grTex = HWR_GetTexture(texnum);
 
-#ifdef ESLOPE
 					if (!slopeskew) // no skewing
 					{
 						if (attachtobottom)
@@ -2164,12 +1987,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 							wallVerts[2].t = wallVerts[1].t - (hS - lS) * grTex->scaleY;
 						}
 					}
-#else
-					if (attachtobottom)
-						texturevpeg -= *rover->topheight - *rover->bottomheight;
-					wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + texturevpeg) * grTex->scaleY;
-					wallVerts[0].t = wallVerts[1].t = (*rover->topheight - l + texturevpeg) * grTex->scaleY;
-#endif
 
 					wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX;
 					wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX;
@@ -2238,7 +2055,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 					newline = rover->master->frontsector->lines[0] + linenum;
 					texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
 				}
-#ifdef ESLOPE //backsides
 				h  = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight;
 				hS = *rover->t_slope ? P_GetZAt(*rover->t_slope, v2x, v2y) : *rover->topheight;
 				l  = *rover->b_slope ? P_GetZAt(*rover->b_slope, v1x, v1y) : *rover->bottomheight;
@@ -2255,19 +2071,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				wallVerts[2].y = FIXED_TO_FLOAT(hS);
 				wallVerts[0].y = FIXED_TO_FLOAT(l);
 				wallVerts[1].y = FIXED_TO_FLOAT(lS);
-#else
-				h = *rover->topheight;
-				l = *rover->bottomheight;
-				if (h > highcut)
-					h = highcut;
-				if (l < lowcut)
-					l = lowcut;
-				//Hurdler: HW code starts here
-				//FIXME: check if peging is correct
-				// set top/bottom coords
-				wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h);
-				wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l);
-#endif
 				if (rover->flags & FF_FOG)
 				{
 					wallVerts[3].t = wallVerts[2].t = 0;
@@ -2365,7 +2168,6 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks
 
 	// GZDoom method of sloped line clipping
 
-#ifdef ESLOPE
 	if (afrontsector->f_slope || afrontsector->c_slope || abacksector->f_slope || abacksector->c_slope)
 	{
 		fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
@@ -2387,7 +2189,6 @@ static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacks
 #undef SLOPEPARAMS
 	}
 	else
-#endif
 	{
 		frontf1 = frontf2 = afrontsector->floorheight;
 		frontc1 = frontc2 = afrontsector->ceilingheight;
@@ -2928,7 +2729,6 @@ static void HWR_AddLine(seg_t * line)
 		goto clippass; // treat like wide open window instead
 	}
 
-#ifdef ESLOPE
 	if (gr_frontsector->f_slope || gr_frontsector->c_slope || gr_backsector->f_slope || gr_backsector->c_slope)
 	{
 		fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
@@ -2973,7 +2773,6 @@ static void HWR_AddLine(seg_t * line)
 				goto clippass;
 	}
 	else
-#endif
 	{
 		// if both ceilings are skies, consider it always "open"
 		// same for floors
@@ -3511,7 +3310,6 @@ static void HWR_Subsector(size_t num)
 		cullFloorHeight   = locFloorHeight   = gr_frontsector->floorheight;
 		cullCeilingHeight = locCeilingHeight = gr_frontsector->ceilingheight;
 
-#ifdef ESLOPE
 		if (gr_frontsector->f_slope)
 		{
 			cullFloorHeight = P_GetZAt(gr_frontsector->f_slope, viewx, viewy);
@@ -3523,7 +3321,6 @@ static void HWR_Subsector(size_t num)
 			cullCeilingHeight = P_GetZAt(gr_frontsector->c_slope, viewx, viewy);
 			locCeilingHeight = P_GetZAt(gr_frontsector->c_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
 		}
-#endif
 	}
 // ----- end special tricks -----
 
@@ -3615,15 +3412,13 @@ static void HWR_Subsector(size_t num)
 			fixed_t cullHeight, centerHeight;
 
             // bottom plane
-#ifdef ESLOPE
 			if (*rover->b_slope)
 			{
 				cullHeight = P_GetZAt(*rover->b_slope, viewx, viewy);
 				centerHeight = P_GetZAt(*rover->b_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
 			}
 			else
-#endif
-		    cullHeight = centerHeight = *rover->bottomheight;
+				cullHeight = centerHeight = *rover->bottomheight;
 
 			if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES))
 				continue;
@@ -3683,15 +3478,13 @@ static void HWR_Subsector(size_t num)
 			}
 
 			// top plane
-#ifdef ESLOPE
 			if (*rover->t_slope)
 			{
 				cullHeight = P_GetZAt(*rover->t_slope, viewx, viewy);
 				centerHeight = P_GetZAt(*rover->t_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y);
 			}
 			else
-#endif
-		    cullHeight = centerHeight = *rover->topheight;
+				cullHeight = centerHeight = *rover->topheight;
 
 			if (centerHeight >= locFloorHeight &&
 			    centerHeight <= locCeilingHeight &&
@@ -4263,13 +4056,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 	float realheight, heightmult;
 	const sector_t *sector = spr->mobj->subsector->sector;
 	const lightlist_t *list = sector->lightlist;
-#ifdef ESLOPE
 	float endrealtop, endrealbot, endtop, endbot;
 	float endbheight;
 	float endrealheight;
 	fixed_t temp;
 	fixed_t v1x, v1y, v2x, v2y;
-#endif
 
 	this_scale = FIXED_TO_FLOAT(spr->mobj->scale);
 
@@ -4341,10 +4132,8 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 	towbot = baseWallVerts[0].tow;
 	towmult = (towbot - towtop) / (top - bot);
 
-#ifdef ESLOPE
 	endrealtop = endtop = baseWallVerts[2].y;
 	endrealbot = endbot = baseWallVerts[1].y;
-#endif
 
 	// copy the contents of baseWallVerts into the drawn wallVerts array
 	// baseWallVerts is used to know the final shape to easily get the vertex
@@ -4384,7 +4173,6 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 	if (spr->mobj->frame & FF_FULLBRIGHT)
 		lightlevel = 255;
 
-#ifdef ESLOPE
 	for (i = 1; i < sector->numlights; i++)
 	{
 		fixed_t h = sector->lightlist[i].slope ? P_GetZAt(sector->lightlist[i].slope, spr->mobj->x, spr->mobj->y)
@@ -4397,19 +4185,10 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 			break;
 		}
 	}
-#else
-	i = R_GetPlaneLight(sector, temp, false);
-	if (!(spr->mobj->frame & FF_FULLBRIGHT))
-		lightlevel = *list[i].lightlevel;
-	colormap = *list[i].extra_colormap;
-#endif
 
 	for (i = 0; i < sector->numlights; i++)
 	{
-#ifdef ESLOPE
-		if (endtop < endrealbot)
-#endif
-		if (top < realbot)
+		if (endtop < endrealbot && top < realbot)
 			return;
 
 		// even if we aren't changing colormap or lightlevel, we still need to continue drawing down the sprite
@@ -4420,7 +4199,6 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 			colormap = *list[i].extra_colormap;
 		}
 
-#ifdef ESLOPE
 		if (i + 1 < sector->numlights)
 		{
 			if (list[i+1].slope)
@@ -4438,21 +4216,8 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 			bheight = realbot;
 			endbheight = endrealbot;
 		}
-#else
-		if (i + 1 < sector->numlights)
-		{
-			bheight = FIXED_TO_FLOAT(list[i+1].height);
-		}
-		else
-		{
-			bheight = realbot;
-		}
-#endif
 
-#ifdef ESLOPE
-		if (endbheight >= endtop)
-#endif
-		if (bheight >= top)
+		if (endbheight >= endtop && bheight >= top)
 			continue;
 
 		bot = bheight;
@@ -4460,14 +4225,11 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 		if (bot < realbot)
 			bot = realbot;
 
-#ifdef ESLOPE
 		endbot = endbheight;
 
 		if (endbot < endrealbot)
 			endbot = endrealbot;
-#endif
 
-#ifdef ESLOPE
 		wallVerts[3].tow = towtop + ((realtop - top) * towmult);
 		wallVerts[2].tow = towtop + ((endrealtop - endtop) * towmult);
 		wallVerts[0].tow = towtop + ((realtop - bot) * towmult);
@@ -4501,32 +4263,6 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 			wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
 			wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
 		}
-#else
-		wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult);
-		wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult);
-
-		wallVerts[2].y = wallVerts[3].y = top;
-		wallVerts[0].y = wallVerts[1].y = bot;
-
-		// The x and y only need to be adjusted in the case that it's not a papersprite
-		if (cv_grspritebillboarding.value
-			&& spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE))
-		{
-			// Get the x and z of the vertices so billboarding draws correctly
-			realheight = realbot - realtop;
-			heightmult = (realtop - top) / realheight;
-			wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
-			wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
-			wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
-			wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
-
-			heightmult = (realtop - bot) / realheight;
-			wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult;
-			wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult;
-			wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult;
-			wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult;
-		}
-#endif
 
 		if (colormap)
 			Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
@@ -4538,21 +4274,15 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 		HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip);
 
 		top = bot;
-#ifdef ESLOPE
 		endtop = endbot;
-#endif
 	}
 
 	bot = realbot;
-#ifdef ESLOPE
 	endbot = endrealbot;
-	if (endtop <= endrealbot)
-#endif
-	if (top <= realbot)
+	if (endtop <= endrealbot && top <= realbot)
 		return;
 
 	// If we're ever down here, somehow the above loop hasn't draw all the light levels of sprite
-#ifdef ESLOPE
 	wallVerts[3].tow = towtop + ((realtop - top) * towmult);
 	wallVerts[2].tow = towtop + ((endrealtop - endtop) * towmult);
 	wallVerts[0].tow = towtop + ((realtop - bot) * towmult);
@@ -4562,13 +4292,6 @@ static void HWR_SplitSprite(gr_vissprite_t *spr)
 	wallVerts[2].y = endtop;
 	wallVerts[0].y = bot;
 	wallVerts[1].y = endbot;
-#else
-	wallVerts[3].tow = wallVerts[2].tow = towtop + ((realtop - top) * towmult);
-	wallVerts[0].tow = wallVerts[1].tow = towtop + ((realtop - bot) * towmult);
-
-	wallVerts[2].y = wallVerts[3].y = top;
-	wallVerts[0].y = wallVerts[1].y = bot;
-#endif
 
 	if (colormap)
 		Surf.FlatColor.rgba = HWR_Lighting(lightlevel, colormap->rgba, colormap->fadergba, false, false);
diff --git a/src/hardware/hw_trick.c b/src/hardware/hw_trick.c
index 97d86b944..82d81b5b2 100644
--- a/src/hardware/hw_trick.c
+++ b/src/hardware/hw_trick.c
@@ -610,10 +610,8 @@ static boolean isCeilingFloating(sector_t *thisSector)
 		if (!adjSector) // assume floating sectors have surrounding sectors
 			return false;
 
-#ifdef ESLOPE
 		if (adjSector->c_slope) // Don't bother with slopes
 			return false;
-#endif
 
 		if (!refSector)
 		{
@@ -663,10 +661,8 @@ static boolean isFloorFloating(sector_t *thisSector)
 		if (!adjSector) // assume floating sectors have surrounding sectors
 			return false;
 
-#ifdef ESLOPE
 		if (adjSector->f_slope) // Don't bother with slopes
 			return false;
-#endif
 
 		if (!refSector)
 		{
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 4f924aa18..3379ad3aa 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -14,9 +14,7 @@
 #include "fastcmp.h"
 #include "p_local.h"
 #include "p_setup.h" // So we can have P_SetupLevelSky
-#ifdef ESLOPE
 #include "p_slopes.h" // P_GetZAt
-#endif
 #include "z_zone.h"
 #include "r_main.h"
 #include "r_draw.h"
@@ -2175,7 +2173,6 @@ static int lib_evStartCrumble(lua_State *L)
 	return 0;
 }
 
-#ifdef ESLOPE
 // P_SLOPES
 ////////////
 
@@ -2191,7 +2188,6 @@ static int lib_pGetZAt(lua_State *L)
 	lua_pushfixed(L, P_GetZAt(slope, x, y));
 	return 1;
 }
-#endif
 
 // R_DEFS
 ////////////
@@ -3222,10 +3218,8 @@ static luaL_Reg lib[] = {
 	{"EV_CrumbleChain",lib_evCrumbleChain},
 	{"EV_StartCrumble",lib_evStartCrumble},
 
-#ifdef ESLOPE
 	// p_slopes
 	{"P_GetZAt",lib_pGetZAt},
-#endif
 
 	// r_defs
 	{"R_PointToAngle",lib_rPointToAngle},
diff --git a/src/lua_libs.h b/src/lua_libs.h
index bf1e28b5d..d0334d725 100644
--- a/src/lua_libs.h
+++ b/src/lua_libs.h
@@ -43,11 +43,9 @@ extern lua_State *gL;
 #define META_SEG "SEG_T*"
 #define META_NODE "NODE_T*"
 #endif
-#ifdef ESLOPE
 #define META_SLOPE "PSLOPE_T*"
 #define META_VECTOR2 "VECTOR2_T"
 #define META_VECTOR3 "VECTOR3_T"
-#endif
 #define META_MAPHEADER "MAPHEADER_T*"
 
 #define META_CVAR "CONSVAR_T*"
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index 32150a4bc..d851c820e 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -15,9 +15,7 @@
 #include "p_local.h"
 #include "p_setup.h"
 #include "z_zone.h"
-#ifdef ESLOPE
 #include "p_slopes.h"
-#endif
 #include "r_main.h"
 
 #include "lua_script.h"
@@ -41,13 +39,9 @@ enum sector_e {
 	sector_heightsec,
 	sector_camsec,
 	sector_lines,
-#ifdef ESLOPE
 	sector_ffloors,
 	sector_fslope,
 	sector_cslope
-#else
-	sector_ffloors
-#endif
 };
 
 static const char *const sector_opt[] = {
@@ -64,10 +58,8 @@ static const char *const sector_opt[] = {
 	"camsec",
 	"lines",
 	"ffloors",
-#ifdef ESLOPE
 	"f_slope",
 	"c_slope",
-#endif
 	NULL};
 
 enum subsector_e {
@@ -180,10 +172,8 @@ enum ffloor_e {
 	ffloor_toplightlevel,
 	ffloor_bottomheight,
 	ffloor_bottompic,
-#ifdef ESLOPE
 	ffloor_tslope,
 	ffloor_bslope,
-#endif
 	ffloor_sector,
 	ffloor_flags,
 	ffloor_master,
@@ -200,10 +190,8 @@ static const char *const ffloor_opt[] = {
 	"toplightlevel",
 	"bottomheight",
 	"bottompic",
-#ifdef ESLOPE
 	"t_slope",
 	"b_slope",
-#endif
 	"sector", // secnum pushed as control sector userdata
 	"flags",
 	"master", // control linedef
@@ -289,7 +277,6 @@ static const char *const bbox_opt[] = {
 	"right",
 	NULL};
 
-#ifdef ESLOPE
 enum slope_e {
 	slope_valid = 0,
 	slope_o,
@@ -324,7 +311,6 @@ static const char *const vector_opt[] = {
 	"y",
 	"z",
 	NULL};
-#endif
 
 static const char *const array_opt[] ={"iterate",NULL};
 static const char *const valid_opt[] ={"valid",NULL};
@@ -570,14 +556,12 @@ static int sector_get(lua_State *L)
 		LUA_PushUserdata(L, sector->ffloors, META_FFLOOR);
 		lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateFFloors and sector->ffloors as upvalues for the function
 		return 1;
-#ifdef ESLOPE
 	case sector_fslope: // f_slope
 		LUA_PushUserdata(L, sector->f_slope, META_SLOPE);
 		return 1;
 	case sector_cslope: // c_slope
 		LUA_PushUserdata(L, sector->c_slope, META_SLOPE);
 		return 1;
-#endif
 	}
 	return 0;
 }
@@ -601,10 +585,8 @@ static int sector_set(lua_State *L)
 	case sector_camsec: // camsec
 	case sector_lines: // lines
 	case sector_ffloors: // ffloors
-#ifdef ESLOPE
 	case sector_fslope: // f_slope
 	case sector_cslope: // c_slope
-#endif
 	default:
 		return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]);
 	case sector_floorheight: { // floorheight
@@ -1692,14 +1674,12 @@ static int ffloor_get(lua_State *L)
 		lua_pushlstring(L, levelflat->name, i);
 		return 1;
 	}
-#ifdef ESLOPE
 	case ffloor_tslope:
 		LUA_PushUserdata(L, *ffloor->t_slope, META_SLOPE);
 		return 1;
 	case ffloor_bslope:
 		LUA_PushUserdata(L, *ffloor->b_slope, META_SLOPE);
 		return 1;
-#endif
 	case ffloor_sector:
 		LUA_PushUserdata(L, &sectors[ffloor->secnum], META_SECTOR);
 		return 1;
@@ -1739,10 +1719,8 @@ static int ffloor_set(lua_State *L)
 	switch(field)
 	{
 	case ffloor_valid: // valid
-#ifdef ESLOPE
 	case ffloor_tslope: // t_slope
 	case ffloor_bslope: // b_slope
-#endif
 	case ffloor_sector: // sector
 	case ffloor_master: // master
 	case ffloor_target: // target
@@ -1803,7 +1781,6 @@ static int ffloor_set(lua_State *L)
 	return 0;
 }
 
-#ifdef ESLOPE
 //////////////
 // pslope_t //
 //////////////
@@ -1976,7 +1953,6 @@ static int vector3_get(lua_State *L)
 
 	return 0;
 }
-#endif
 
 /////////////////////
 // mapheaderinfo[] //
@@ -2225,7 +2201,6 @@ int LUA_MapLib(lua_State *L)
 		lua_setfield(L, -2, "__index");
 	lua_pop(L, 1);
 
-#ifdef ESLOPE
 	luaL_newmetatable(L, META_SLOPE);
 		lua_pushcfunction(L, slope_get);
 		lua_setfield(L, -2, "__index");
@@ -2243,7 +2218,6 @@ int LUA_MapLib(lua_State *L)
 		lua_pushcfunction(L, vector3_get);
 		lua_setfield(L, -2, "__index");
 	lua_pop(L, 1);
-#endif
 
 	luaL_newmetatable(L, META_MAPHEADER);
 		lua_pushcfunction(L, mapheaderinfo_get);
diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c
index 4b580a2fe..81729b788 100644
--- a/src/lua_mobjlib.c
+++ b/src/lua_mobjlib.c
@@ -84,9 +84,7 @@ enum mobj_e {
 	mobj_extravalue2,
 	mobj_cusval,
 	mobj_cvmem,
-#ifdef ESLOPE
 	mobj_standingslope,
-#endif
 	mobj_colorized,
 	mobj_shadowscale
 };
@@ -152,9 +150,7 @@ static const char *const mobj_opt[] = {
 	"extravalue2",
 	"cusval",
 	"cvmem",
-#ifdef ESLOPE
 	"standingslope",
-#endif
 	"colorized",
 	"shadowscale",
 	NULL};
@@ -383,11 +379,9 @@ static int mobj_get(lua_State *L)
 	case mobj_cvmem:
 		lua_pushinteger(L, mo->cvmem);
 		break;
-#ifdef ESLOPE
 	case mobj_standingslope:
 		LUA_PushUserdata(L, mo->standingslope, META_SLOPE);
 		break;
-#endif
 	case mobj_colorized:
 		lua_pushboolean(L, mo->colorized);
 		break;
@@ -716,10 +710,8 @@ static int mobj_set(lua_State *L)
 	case mobj_cvmem:
 		mo->cvmem = luaL_checkinteger(L, 3);
 		break;
-#ifdef ESLOPE
 	case mobj_standingslope:
 		return NOSET;
-#endif
 	case mobj_colorized:
 		mo->colorized = luaL_checkboolean(L, 3);
 		break;
diff --git a/src/lua_script.c b/src/lua_script.c
index 6fa6cf57d..8c0cd5351 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -23,9 +23,7 @@
 #include "byteptr.h"
 #include "p_saveg.h"
 #include "p_local.h"
-#ifdef ESLOPE
 #include "p_slopes.h" // for P_SlopeById
-#endif
 #ifdef LUA_ALLOW_BYTECODE
 #include "d_netfil.h" // for LUA_DumpFile
 #endif
@@ -731,9 +729,7 @@ enum
 	ARCH_NODE,
 #endif
 	ARCH_FFLOOR,
-#ifdef ESLOPE
 	ARCH_SLOPE,
-#endif
 	ARCH_MAPHEADER,
 
 	ARCH_TEND=0xFF,
@@ -758,9 +754,7 @@ static const struct {
 	{META_NODE,     ARCH_NODE},
 #endif
 	{META_FFLOOR,	ARCH_FFLOOR},
-#ifdef ESLOPE
 	{META_SLOPE,    ARCH_SLOPE},
-#endif
 	{META_MAPHEADER,   ARCH_MAPHEADER},
 	{NULL,          ARCH_NULL}
 };
@@ -1015,7 +1009,6 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 			}
 			break;
 		}
-#ifdef ESLOPE
 		case ARCH_SLOPE:
 		{
 			pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex));
@@ -1027,7 +1020,6 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 			}
 			break;
 		}
-#endif
 		case ARCH_MAPHEADER:
 		{
 			mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex));
@@ -1249,11 +1241,9 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
 			LUA_PushUserdata(gL, rover, META_FFLOOR);
 		break;
 	}
-#ifdef ESLOPE
 	case ARCH_SLOPE:
 		LUA_PushUserdata(gL, P_SlopeById(READUINT16(save_p)), META_SLOPE);
 		break;
-#endif
 	case ARCH_MAPHEADER:
 		LUA_PushUserdata(gL, mapheaderinfo[READUINT16(save_p)], META_MAPHEADER);
 		break;
diff --git a/src/m_cheat.c b/src/m_cheat.c
index 93e8f2911..4a1a4fb58 100644
--- a/src/m_cheat.c
+++ b/src/m_cheat.c
@@ -1025,13 +1025,9 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling)
 
 	if (ceiling)
 	{
-#ifdef ESLOPE
 		// Truncate position to match where mapthing would be when spawned
 		// (this applies to every further P_GetZAt call as well)
 		fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->ceilingheight;
-#else
-		fixed_t cheight = sec->ceilingheight;
-#endif
 
 		if (((cheight - player->mo->z - player->mo->height)>>FRACBITS) >= (1 << (16-ZSHIFT)))
 		{
@@ -1042,11 +1038,7 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling)
 	}
 	else
 	{
-#ifdef ESLOPE
 		fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight;
-#else
-		fixed_t fheight = sec->floorheight;
-#endif
 		if (((player->mo->z - fheight)>>FRACBITS) >= (1 << (16-ZSHIFT)))
 		{
 			CONS_Printf(M_GetText("Sorry, you're too %s to place this object (max: %d %s).\n"), M_GetText("high"),
@@ -1093,20 +1085,12 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
 	mt->y = (INT16)(player->mo->y>>FRACBITS);
 	if (ceiling)
 	{
-#ifdef ESLOPE
 		fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, mt->x << FRACBITS, mt->y << FRACBITS) : sec->ceilingheight;
-#else
-		fixed_t cheight = sec->ceilingheight;
-#endif
 		mt->z = (UINT16)((cheight - player->mo->z - player->mo->height)>>FRACBITS);
 	}
 	else
 	{
-#ifdef ESLOPE
 		fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : sec->floorheight;
-#else
-		fixed_t fheight = sec->floorheight;
-#endif
 		mt->z = (UINT16)((player->mo->z - fheight)>>FRACBITS);
 	}
 	mt->angle = (INT16)(FixedInt(AngleFixed(player->mo->angle)));
@@ -1352,20 +1336,12 @@ void OP_ObjectplaceMovement(player_t *player)
 
 		if (!!(mobjinfo[op_currentthing].flags & MF_SPAWNCEILING) ^ !!(cv_opflags.value & MTF_OBJECTFLIP))
 		{
-#ifdef ESLOPE
 			fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->ceilingheight;
-#else
-			fixed_t cheight = sec->ceilingheight;
-#endif
 			op_displayflags = (UINT16)((cheight - player->mo->z - mobjinfo[op_currentthing].height)>>FRACBITS);
 		}
 		else
 		{
-#ifdef ESLOPE
 			fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight;
-#else
-			fixed_t fheight = sec->floorheight;
-#endif
 			op_displayflags = (UINT16)((player->mo->z - fheight)>>FRACBITS);
 		}
 		op_displayflags <<= ZSHIFT;
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 9dea0ecc5..09d33c537 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -6764,13 +6764,8 @@ void A_MixUp(mobj_t *actor)
 
 				P_SetThingPosition(players[i].mo);
 
-#ifdef ESLOPE
 				players[i].mo->floorz = P_GetFloorZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL);
 				players[i].mo->ceilingz = P_GetCeilingZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL);
-#else
-				players[i].mo->floorz = players[i].mo->subsector->sector->floorheight;
-				players[i].mo->ceilingz = players[i].mo->subsector->sector->ceilingheight;
-#endif
 
 				P_CheckPosition(players[i].mo, players[i].mo->x, players[i].mo->y);
 			}
diff --git a/src/p_floor.c b/src/p_floor.c
index 9c5ab9057..b8b40df3c 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -15,9 +15,7 @@
 #include "doomstat.h"
 #include "m_random.h"
 #include "p_local.h"
-#ifdef ESLOPE
 #include "p_slopes.h"
-#endif
 #include "r_state.h"
 #include "s_sound.h"
 #include "z_zone.h"
@@ -3178,12 +3176,10 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
 			if (R_PointInSubsector(a, b)->sector == sec)
 			{
 				mobj_t *spawned = NULL;
-#ifdef ESLOPE
 				if (*rover->t_slope)
 					topz = P_GetZAt(*rover->t_slope, a, b) - (spacing>>1);
 				if (*rover->b_slope)
 					bottomz = P_GetZAt(*rover->b_slope, a, b);
-#endif
 
 				for (c = topz; c > bottomz; c -= spacing)
 				{
diff --git a/src/p_local.h b/src/p_local.h
index 99c465f9b..becb045f7 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -66,9 +66,7 @@ typedef enum
 	THINK_POLYOBJ,
 	THINK_MAIN,
 	THINK_MOBJ,
-#ifdef ESLOPE
 	THINK_DYNSLOPE,
-#endif
 	THINK_PRECIP,
 	NUM_THINKERLISTS
 } thinklistnum_t; /**< Thinker lists. */
@@ -383,9 +381,7 @@ extern mobj_t *tmfloorthing, *tmhitthing, *tmthing;
 extern camera_t *mapcampointer;
 extern fixed_t tmx;
 extern fixed_t tmy;
-#ifdef ESLOPE
 extern pslope_t *tmfloorslope, *tmceilingslope;
-#endif
 
 /* cphipps 2004/08/30 */
 extern void P_MapStart(void);
diff --git a/src/p_map.c b/src/p_map.c
index 988089989..accc52836 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -27,9 +27,7 @@
 
 #include "r_splats.h"
 
-#ifdef ESLOPE
 #include "p_slopes.h"
-#endif
 
 #include "z_zone.h"
 
@@ -53,9 +51,7 @@ static fixed_t tmdropoffz, tmdrpoffceilz; // drop-off floor/ceiling heights
 mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz is from a sector
 mobj_t *tmhitthing; // the solid thing you bumped into (for collisions)
 ffloor_t *tmfloorrover, *tmceilingrover;
-#ifdef ESLOPE
 pslope_t *tmfloorslope, *tmceilingslope;
-#endif
 
 // keep track of the line that lowers the ceiling,
 // so missiles don't explode against sky hack walls
@@ -262,9 +258,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
 	if (!vertispeed && !horizspeed)
 		return false;
 
-#ifdef ESLOPE
 	object->standingslope = NULL; // Okay, now we know it's not going to be relevant - no launching off at silly angles for you.
-#endif
 
 	if (spring->eflags & MFE_VERTICALFLIP)
 		vertispeed *= -1;
@@ -439,9 +433,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
 			P_SetPlayerMobjState(object, S_PLAY_FALL);
 	}
 
-#ifdef ESLOPE
 	object->standingslope = NULL; // And again.
-#endif
 
 	final = true;
 
@@ -491,9 +483,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
 		zdist = object->z - spring->z;
 	}
 
-#ifdef ESLOPE
 	object->standingslope = NULL; // No launching off at silly angles for you.
-#endif
 
 	switch (spring->type)
 	{
@@ -1736,9 +1726,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
 				{
 					tmfloorz = thing->z + thing->height;
 					tmfloorrover = NULL;
-#ifdef ESLOPE
 					tmfloorslope = NULL;
-#endif
 				}
 				return true;
 			}
@@ -1757,18 +1745,14 @@ static boolean PIT_CheckThing(mobj_t *thing)
 
 				tmfloorz = tmceilingz = topz; // block while in air
 				tmceilingrover = NULL;
-#ifdef ESLOPE
 				tmceilingslope = NULL;
-#endif
 				tmfloorthing = thing; // needed for side collision
 			}
 			else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height)
 			{
 				tmceilingz = topz;
 				tmceilingrover = NULL;
-#ifdef ESLOPE
 				tmceilingslope = NULL;
-#endif
 				tmfloorthing = thing; // thing we may stand on
 			}
 		}
@@ -1783,9 +1767,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
 				{
 					tmceilingz = thing->z;
 					tmceilingrover = NULL;
-#ifdef ESLOPE
 					tmceilingslope = NULL;
-#endif
 				}
 				return true;
 			}
@@ -1804,18 +1786,14 @@ static boolean PIT_CheckThing(mobj_t *thing)
 
 				tmfloorz = tmceilingz = topz; // block while in air
 				tmfloorrover = NULL;
-#ifdef ESLOPE
 				tmfloorslope = NULL;
-#endif
 				tmfloorthing = thing; // needed for side collision
 			}
 			else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z)
 			{
 				tmfloorz = topz;
 				tmfloorrover = NULL;
-#ifdef ESLOPE
 				tmfloorslope = NULL;
-#endif
 				tmfloorthing = thing; // thing we may stand on
 			}
 		}
@@ -1976,18 +1954,14 @@ static boolean PIT_CheckLine(line_t *ld)
 		tmceilingz = opentop;
 		ceilingline = ld;
 		tmceilingrover = openceilingrover;
-#ifdef ESLOPE
 		tmceilingslope = opentopslope;
-#endif
 	}
 
 	if (openbottom > tmfloorz)
 	{
 		tmfloorz = openbottom;
 		tmfloorrover = openfloorrover;
-#ifdef ESLOPE
 		tmfloorslope = openbottomslope;
-#endif
 	}
 
 	if (highceiling > tmdrpoffceilz)
@@ -2068,10 +2042,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 	tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight;
 	tmfloorrover = NULL;
 	tmceilingrover = NULL;
-#ifdef ESLOPE
 	tmfloorslope = newsubsec->sector->f_slope;
 	tmceilingslope = newsubsec->sector->c_slope;
-#endif
 
 	// Check list of fake floors and see if tmfloorz/tmceilingz need to be altered.
 	if (newsubsec->sector->ffloors)
@@ -2112,9 +2084,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 						if (tmfloorz < topheight - sinklevel) {
 							tmfloorz = topheight - sinklevel;
 							tmfloorrover = rover;
-#ifdef ESLOPE
 							tmfloorslope = *rover->t_slope;
-#endif
 						}
 					}
 					else if (thing->eflags & MFE_VERTICALFLIP && thingtop <= bottomheight + sinklevel && thing->momz >= 0)
@@ -2122,9 +2092,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 						if (tmceilingz > bottomheight + sinklevel) {
 							tmceilingz = bottomheight + sinklevel;
 							tmceilingrover = rover;
-#ifdef ESLOPE
 							tmceilingslope = *rover->b_slope;
-#endif
 						}
 					}
 				}
@@ -2147,9 +2115,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 					if (tmfloorz < thing->z) {
 						tmfloorz = thing->z;
 						tmfloorrover = rover;
-#ifdef ESLOPE
 						tmfloorslope = NULL;
-#endif
 					}
 				}
 				// Quicksand blocks never change heights otherwise.
@@ -2166,9 +2132,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 			{
 				tmfloorz = tmdropoffz = topheight;
 				tmfloorrover = rover;
-#ifdef ESLOPE
 				tmfloorslope = *rover->t_slope;
-#endif
 			}
 			if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2)
 				&& !(rover->flags & FF_PLATFORM)
@@ -2176,9 +2140,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 			{
 				tmceilingz = tmdrpoffceilz = bottomheight;
 				tmceilingrover = rover;
-#ifdef ESLOPE
 				tmceilingslope = *rover->b_slope;
-#endif
 			}
 		}
 	}
@@ -2253,17 +2215,13 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 
 						if (polytop > tmfloorz && abs(delta1) < abs(delta2)) {
 							tmfloorz = tmdropoffz = polytop;
-#ifdef ESLOPE
 							tmfloorslope = NULL;
-#endif
 							tmfloorrover = NULL;
 						}
 
 						if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) {
 							tmceilingz = tmdrpoffceilz = polybottom;
-#ifdef ESLOPE
 							tmceilingslope = NULL;
-#endif
 							tmceilingrover = NULL;
 						}
 					}
@@ -2664,10 +2622,8 @@ boolean PIT_PushableMoved(mobj_t *thing)
 		line_t *oldblockline = blockingline;
 		ffloor_t *oldflrrover = tmfloorrover;
 		ffloor_t *oldceilrover = tmceilingrover;
-#ifdef ESLOPE
 		pslope_t *oldfslope = tmfloorslope;
 		pslope_t *oldcslope = tmceilingslope;
-#endif
 
 		// Move the player
 		P_TryMove(thing, thing->x+stand->momx, thing->y+stand->momy, true);
@@ -2682,10 +2638,8 @@ boolean PIT_PushableMoved(mobj_t *thing)
 		blockingline = oldblockline;
 		tmfloorrover = oldflrrover;
 		tmceilingrover = oldceilrover;
-#ifdef ESLOPE
 		tmfloorslope = oldfslope;
 		tmceilingslope = oldcslope;
-#endif
 		thing->momz = stand->momz;
 	}
 	else
@@ -2707,9 +2661,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 	fixed_t tryy = thing->y;
 	fixed_t radius = thing->radius;
 	fixed_t thingtop = thing->z + thing->height;
-#ifdef ESLOPE
 	fixed_t startingonground = P_IsObjectOnGround(thing);
-#endif
 	floatok = false;
 
 	if (radius < MAXRADIUS/2)
@@ -2795,14 +2747,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 						thing->ceilingrover = tmceilingrover;
 						thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 					}
-#ifdef ESLOPE
 					else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
 					{
 						thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
 						thing->ceilingrover = tmceilingrover;
 						thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 					}
-#endif
 				}
 				else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep)
 				{
@@ -2810,14 +2760,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 					thing->floorrover = tmfloorrover;
 					thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 				}
-#ifdef ESLOPE
 				else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
 				{
 					thing->z = thing->floorz = tmfloorz;
 					thing->floorrover = tmfloorrover;
 					thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 				}
-#endif
 			}
 
 			if (thing->eflags & MFE_VERTICALFLIP)
@@ -2881,7 +2829,6 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 	thing->floorrover = tmfloorrover;
 	thing->ceilingrover = tmceilingrover;
 
-#ifdef ESLOPE
 	if (!(thing->flags & MF_NOCLIPHEIGHT))
 	{
 		// Assign thing's standingslope if needed
@@ -2902,7 +2849,6 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 	}
 	else // don't set standingslope if you're not going to clip against it
 		thing->standingslope = NULL;
-#endif
 
 	thing->x = x;
 	thing->y = y;
@@ -3268,13 +3214,8 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
 
 	glidesector = R_PointInSubsector(player->mo->x + platx, player->mo->y + platy);
 
-#ifdef ESLOPE
 	floorz = glidesector->sector->f_slope ? P_GetZAt(glidesector->sector->f_slope, player->mo->x, player->mo->y) : glidesector->sector->floorheight;
 	ceilingz = glidesector->sector->c_slope ? P_GetZAt(glidesector->sector->c_slope, player->mo->x, player->mo->y) : glidesector->sector->ceilingheight;
-#else
-	floorz = glidesector->sector->floorheight;
-	ceilingz = glidesector->sector->ceilingheight;
-#endif
 
 	if (glidesector->sector != player->mo->subsector->sector)
 	{
@@ -3292,12 +3233,10 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
 				topheight = *rover->topheight;
 				bottomheight = *rover->bottomheight;
 
-#ifdef ESLOPE
 				if (*rover->t_slope)
 					topheight = P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y);
 				if (*rover->b_slope)
 					bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y);
-#endif
 
 				floorclimb = true;
 
@@ -3453,12 +3392,10 @@ isblocking:
 				topheight = *rover->topheight;
 				bottomheight = *rover->bottomheight;
 
-#ifdef ESLOPE
 				if (*rover->t_slope)
 					topheight = P_GetZAt(*rover->t_slope, slidemo->x, slidemo->y);
 				if (*rover->b_slope)
 					bottomheight = P_GetZAt(*rover->b_slope, slidemo->x, slidemo->y);
-#endif
 
 				if (topheight < slidemo->z)
 					continue;
@@ -3663,10 +3600,8 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
 		if (rover->master->flags & ML_BLOCKMONSTERS)
 			continue;
 
-		topheight =
-#ifdef ESLOPE
-			*rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) :
-#endif
+		topheight = *rover->t_slope ?
+			P_GetZAt(*rover->t_slope, mo->x, mo->y) :
 			*rover->topheight;
 
 		if (mo->eflags & MFE_VERTICALFLIP)
@@ -3680,10 +3615,8 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
 				continue;
 		}
 
-		bottomheight =
-#ifdef ESLOPE
-			*rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) :
-#endif
+		bottomheight = *rover->b_slope ?
+			P_GetZAt(*rover->b_slope, mo->x, mo->y) :
 			*rover->bottomheight;
 
 		if (mo->eflags & MFE_VERTICALFLIP)
@@ -4271,12 +4204,10 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
 				topheight = *rover->topheight;
 				bottomheight = *rover->bottomheight;
 
-/*#ifdef ESLOPE
-				if (rover->t_slope)
+				/*if (rover->t_slope)
 					topheight = P_GetZAt(rover->t_slope, thing->x, thing->y);
 				if (rover->b_slope)
-					bottomheight = P_GetZAt(rover->b_slope, thing->x, thing->y);
-#endif*/
+					bottomheight = P_GetZAt(rover->b_slope, thing->x, thing->y);*/
 
 				delta1 = thing->z - (bottomheight + topheight)/2;
 				delta2 = thingtop - (bottomheight + topheight)/2;
@@ -5057,10 +4988,8 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
 	sector_t *sec = R_PointInSubsector(x, y)->sector;
 	fixed_t floorz = sec->floorheight;
 
-#ifdef ESLOPE
 	if (sec->f_slope)
 		floorz = P_GetZAt(sec->f_slope, x, y);
-#endif
 
 	// Intercept the stupid 'fall through 3dfloors' bug Tails 03-17-2002
 	if (sec->ffloors)
@@ -5080,12 +5009,10 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
 			topheight = *rover->topheight;
 			bottomheight = *rover->bottomheight;
 
-#ifdef ESLOPE
 			if (*rover->t_slope)
 				topheight = P_GetZAt(*rover->t_slope, x, y);
 			if (*rover->b_slope)
 				bottomheight = P_GetZAt(*rover->b_slope, x, y);
-#endif
 
 			if (rover->flags & FF_QUICKSAND)
 			{
diff --git a/src/p_maputl.c b/src/p_maputl.c
index 69be5a70f..bfca72eda 100644
--- a/src/p_maputl.c
+++ b/src/p_maputl.c
@@ -277,9 +277,7 @@ fixed_t P_InterceptVector(divline_t *v2, divline_t *v1)
 // OPTIMIZE: keep this precalculated
 //
 fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
-#ifdef ESLOPE
 pslope_t *opentopslope, *openbottomslope;
-#endif
 ffloor_t *openfloorrover, *openceilingrover;
 
 // P_CameraLineOpening
@@ -307,24 +305,20 @@ void P_CameraLineOpening(line_t *linedef)
 	{
 		frontfloor = sectors[front->camsec].floorheight;
 		frontceiling = sectors[front->camsec].ceilingheight;
-#ifdef ESLOPE
 		if (sectors[front->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
 			frontfloor = P_GetZAt(sectors[front->camsec].f_slope, camera.x, camera.y);
 		if (sectors[front->camsec].c_slope)
 			frontceiling = P_GetZAt(sectors[front->camsec].c_slope, camera.x, camera.y);
-#endif
 
 	}
 	else if (front->heightsec >= 0)
 	{
 		frontfloor = sectors[front->heightsec].floorheight;
 		frontceiling = sectors[front->heightsec].ceilingheight;
-#ifdef ESLOPE
 		if (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
 			frontfloor = P_GetZAt(sectors[front->heightsec].f_slope, camera.x, camera.y);
 		if (sectors[front->heightsec].c_slope)
 			frontceiling = P_GetZAt(sectors[front->heightsec].c_slope, camera.x, camera.y);
-#endif
 	}
 	else
 	{
@@ -335,23 +329,19 @@ void P_CameraLineOpening(line_t *linedef)
 	{
 		backfloor = sectors[back->camsec].floorheight;
 		backceiling = sectors[back->camsec].ceilingheight;
-#ifdef ESLOPE
 		if (sectors[back->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
 			frontfloor = P_GetZAt(sectors[back->camsec].f_slope, camera.x, camera.y);
 		if (sectors[back->camsec].c_slope)
 			frontceiling = P_GetZAt(sectors[back->camsec].c_slope, camera.x, camera.y);
-#endif
 	}
 	else if (back->heightsec >= 0)
 	{
 		backfloor = sectors[back->heightsec].floorheight;
 		backceiling = sectors[back->heightsec].ceilingheight;
-#ifdef ESLOPE
 		if (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
 			frontfloor = P_GetZAt(sectors[back->heightsec].f_slope, camera.x, camera.y);
 		if (sectors[back->heightsec].c_slope)
 			frontceiling = P_GetZAt(sectors[back->heightsec].c_slope, camera.x, camera.y);
-#endif
 	}
 	else
 	{
@@ -469,9 +459,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 		openbottom = INT32_MIN;
 		highceiling = INT32_MIN;
 		lowfloor = INT32_MAX;
-#ifdef ESLOPE
 		opentopslope = openbottomslope = NULL;
-#endif
 	}
 	else
 #endif
@@ -485,17 +473,13 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 		{
 			opentop = frontheight;
 			highceiling = backheight;
-#ifdef ESLOPE
 			opentopslope = front->c_slope;
-#endif
 		}
 		else
 		{
 			opentop = backheight;
 			highceiling = frontheight;
-#ifdef ESLOPE
 			opentopslope = back->c_slope;
-#endif
 		}
 
 		frontheight = P_GetFloorZ(mobj, front, tmx, tmy, linedef);
@@ -505,17 +489,13 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 		{
 			openbottom = frontheight;
 			lowfloor = backheight;
-#ifdef ESLOPE
 			openbottomslope = front->f_slope;
-#endif
 		}
 		else
 		{
 			openbottom = backheight;
 			lowfloor = frontheight;
-#ifdef ESLOPE
 			openbottomslope = back->f_slope;
-#endif
 		}
 	}
 
@@ -647,9 +627,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 				{
 					if (bottomheight < opentop) {
 						opentop = bottomheight;
-#ifdef ESLOPE
 						opentopslope = *rover->b_slope;
-#endif
 						openceilingrover = rover;
 					}
 					else if (bottomheight < highceiling)
@@ -660,9 +638,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 				{
 					if (topheight > openbottom) {
 						openbottom = topheight;
-#ifdef ESLOPE
 						openbottomslope = *rover->t_slope;
-#endif
 						openfloorrover = rover;
 					}
 					else if (topheight > lowfloor)
@@ -693,9 +669,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 				{
 					if (bottomheight < opentop) {
 						opentop = bottomheight;
-#ifdef ESLOPE
 						opentopslope = *rover->b_slope;
-#endif
 						openceilingrover = rover;
 					}
 					else if (bottomheight < highceiling)
@@ -706,9 +680,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 				{
 					if (topheight > openbottom) {
 						openbottom = topheight;
-#ifdef ESLOPE
 						openbottomslope = *rover->t_slope;
-#endif
 						openfloorrover = rover;
 					}
 					else if (topheight > lowfloor)
diff --git a/src/p_maputl.h b/src/p_maputl.h
index bb09c3ed1..08b606833 100644
--- a/src/p_maputl.h
+++ b/src/p_maputl.h
@@ -55,9 +55,7 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y);
 boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y);
 
 extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
-#ifdef ESLOPE
 extern pslope_t *opentopslope, *openbottomslope;
-#endif
 extern ffloor_t *openfloorrover, *openceilingrover;
 
 void P_LineOpening(line_t *plinedef, mobj_t *mobj);
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 8ba1adc73..347f5fce7 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -31,9 +31,7 @@
 #include "i_video.h"
 #include "lua_hook.h"
 #include "b_bot.h"
-#ifdef ESLOPE
 #include "p_slopes.h"
-#endif
 #include "f_finale.h"
 #include "m_cond.h"
 
@@ -931,12 +929,10 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover)
 	topheight = *rover->topheight;
 	bottomheight = *rover->bottomheight;
 
-#ifdef ESLOPE
 	if (*rover->t_slope)
 		topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
 	if (*rover->b_slope)
 		bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
-#endif
 
 	if (mobj->z > topheight)
 		return false;
@@ -947,7 +943,6 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover)
 	return true;
 }
 
-#ifdef ESLOPE
 // P_GetFloorZ (and its ceiling counterpart)
 // Gets the floor height (or ceiling height) of the mobj's contact point in sector, assuming object's center if moved to [x, y]
 // If line is supplied, it's a divider line on the sector. Set it to NULL if you're not checking for collision with a line
@@ -1051,15 +1046,12 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line,
 			P_GetZAt(slope, v2.x, v2.y)
 		);
 }
-#endif
 
 fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect)
 {
-#ifdef ESLOPE
 	I_Assert(mobj != NULL);
-#endif
 	I_Assert(sector != NULL);
-#ifdef ESLOPE
+
 	if (sector->f_slope) {
 		fixed_t testx, testy;
 		pslope_t *slope = sector->f_slope;
@@ -1129,25 +1121,14 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
 
 		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
 	} else // Well, that makes it easy. Just get the floor height
-#else
-	(void)mobj;
-	(void)boundsec;
-	(void)x;
-	(void)y;
-	(void)line;
-	(void)lowest;
-	(void)perfect;
-#endif
 		return sector->floorheight;
 }
 
 fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect)
 {
-#ifdef ESLOPE
 	I_Assert(mobj != NULL);
-#endif
 	I_Assert(sector != NULL);
-#ifdef ESLOPE
+
 	if (sector->c_slope) {
 		fixed_t testx, testy;
 		pslope_t *slope = sector->c_slope;
@@ -1217,26 +1198,15 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
 
 		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
 	} else // Well, that makes it easy. Just get the ceiling height
-#else
-	(void)mobj;
-	(void)boundsec;
-	(void)x;
-	(void)y;
-	(void)line;
-	(void)lowest;
-	(void)perfect;
-#endif
 		return sector->ceilingheight;
 }
 
 // Now do the same as all above, but for cameras because apparently cameras are special?
 fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect)
 {
-#ifdef ESLOPE
 	I_Assert(mobj != NULL);
-#endif
 	I_Assert(sector != NULL);
-#ifdef ESLOPE
+
 	if (sector->f_slope) {
 		fixed_t testx, testy;
 		pslope_t *slope = sector->f_slope;
@@ -1306,25 +1276,14 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix
 
 		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
 	} else // Well, that makes it easy. Just get the floor height
-#else
-	(void)mobj;
-	(void)boundsec;
-	(void)x;
-	(void)y;
-	(void)line;
-	(void)lowest;
-	(void)perfect;
-#endif
 		return sector->floorheight;
 }
 
 fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect)
 {
-#ifdef ESLOPE
 	I_Assert(mobj != NULL);
-#endif
 	I_Assert(sector != NULL);
-#ifdef ESLOPE
+
 	if (sector->c_slope) {
 		fixed_t testx, testy;
 		pslope_t *slope = sector->c_slope;
@@ -1394,15 +1353,6 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
 
 		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
 	} else // Well, that makes it easy. Just get the ceiling height
-#else
-	(void)mobj;
-	(void)boundsec;
-	(void)x;
-	(void)y;
-	(void)line;
-	(void)lowest;
-	(void)perfect;
-#endif
 		return sector->ceilingheight;
 }
 static void P_PlayerFlip(mobj_t *mo)
@@ -1674,10 +1624,7 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
 		else if (abs(player->rmomx) < FixedMul(STOPSPEED, mo->scale)
 		    && abs(player->rmomy) < FixedMul(STOPSPEED, mo->scale)
 		    && (!(player->cmd.forwardmove && !(twodlevel || mo->flags2 & MF2_TWOD)) && !player->cmd.sidemove && !(player->pflags & PF_SPINNING))
-#ifdef ESLOPE
-			&& !(player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && (abs(player->mo->standingslope->zdelta) >= FRACUNIT/2))
-#endif
-				)
+			&& !(player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && (abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)))
 		{
 			// if in a walking frame, stop moving
 			if (player->panim == PA_WALK)
@@ -1824,11 +1771,9 @@ void P_XYMovement(mobj_t *mo)
 	fixed_t xmove, ymove;
 	fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls
 	boolean moved;
-#ifdef ESLOPE
 	pslope_t *oldslope = NULL;
 	vector3_t slopemom;
 	fixed_t predictedz = 0;
-#endif
 
 	I_Assert(mo != NULL);
 	I_Assert(!P_MobjWasRemoved(mo));
@@ -1858,7 +1803,6 @@ void P_XYMovement(mobj_t *mo)
 	oldx = mo->x;
 	oldy = mo->y;
 
-#ifdef ESLOPE
 	if (mo->flags & MF_NOCLIPHEIGHT)
 		mo->standingslope = NULL;
 
@@ -1883,7 +1827,6 @@ void P_XYMovement(mobj_t *mo)
 		}
 	} else if (P_IsObjectOnGround(mo) && !mo->momz)
 		predictedz = mo->z;
-#endif
 
 	// Pushables can break some blocks
 	if (CheckForBustableBlocks && ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse)))
@@ -1956,7 +1899,6 @@ void P_XYMovement(mobj_t *mo)
 		}
 		else if (player || mo->flags & (MF_SLIDEME|MF_PUSHABLE))
 		{ // try to slide along it
-#ifdef ESLOPE
 			// Wall transfer part 1.
 			pslope_t *transferslope = NULL;
 			fixed_t transfermomz = 0;
@@ -1966,14 +1908,12 @@ void P_XYMovement(mobj_t *mo)
 				if (((transferslope->zangle < ANGLE_180) ? transferslope->zangle : InvAngle(transferslope->zangle)) >= ANGLE_45) // Prevent some weird stuff going on on shallow slopes.
 					transfermomz = P_GetWallTransferMomZ(mo, transferslope);
 			}
-#endif
 
 			P_SlideMove(mo);
 			if (player)
 				player->powers[pw_pushing] = 3;
 			xmove = ymove = 0;
 
-#ifdef ESLOPE
 			// Wall transfer part 2.
 			if (transfermomz && transferslope) // Are we "transferring onto the wall" (really just a disguised vertical launch)?
 			{
@@ -1996,7 +1936,6 @@ void P_XYMovement(mobj_t *mo)
 					}
 				}
 			}
-#endif
 		}
 		else if (mo->type == MT_SPINFIRE)
 		{
@@ -2052,7 +1991,6 @@ void P_XYMovement(mobj_t *mo)
 	if (P_MobjWasRemoved(mo)) // MF_SPECIAL touched a player! O_o;;
 		return;
 
-#ifdef ESLOPE
 	if (moved && oldslope && !(mo->flags & MF_NOCLIPHEIGHT)) { // Check to see if we ran off
 
 		if (oldslope != mo->standingslope) { // First, compare different slopes
@@ -2098,7 +2036,6 @@ void P_XYMovement(mobj_t *mo)
 			//CONS_Printf("Launched off of flat surface running into downward slope\n");
 		}
 	}
-#endif
 
 	// Check the gravity status.
 	P_CheckGravity(mo, false);
@@ -2149,11 +2086,9 @@ void P_XYMovement(mobj_t *mo)
 	if (player && player->powers[pw_carry] == CR_NIGHTSMODE)
 		return; // no friction for NiGHTS players
 
-#ifdef ESLOPE
 	if ((mo->type == MT_BIGTUMBLEWEED || mo->type == MT_LITTLETUMBLEWEED)
 			&& (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8)) // Special exception for tumbleweeds on slopes
 		return;
-#endif
 
 	if (((!(mo->eflags & MFE_VERTICALFLIP) && mo->z > mo->floorz) || (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height < mo->ceilingz))
 		&& !(player && player->pflags & PF_SLIDING))
@@ -2421,7 +2356,6 @@ static boolean P_ZMovement(mobj_t *mo)
 	mo->z += mo->momz;
 	onground = P_IsObjectOnGround(mo);
 
-#ifdef ESLOPE
 	if (mo->standingslope)
 	{
 		if (mo->flags & MF_NOCLIPHEIGHT)
@@ -2429,7 +2363,6 @@ static boolean P_ZMovement(mobj_t *mo)
 		else if (!onground)
 			P_SlopeLaunch(mo);
 	}
-#endif
 
 	switch (mo->type)
 	{
@@ -2631,7 +2564,6 @@ static boolean P_ZMovement(mobj_t *mo)
 		else
 			mo->z = mo->floorz;
 
-#ifdef ESLOPE
 		if (!(mo->flags & MF_MISSILE) && mo->standingslope) // You're still on the ground; why are we here?
 		{
 			mo->momz = 0;
@@ -2644,7 +2576,6 @@ static boolean P_ZMovement(mobj_t *mo)
 			mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope;
 			P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope);
 		}
-#endif
 
 		// hit the floor
 		if (mo->type == MT_FIREBALL) // special case for the fireball
@@ -2744,13 +2675,11 @@ static boolean P_ZMovement(mobj_t *mo)
 							else
 								mom.y -= FixedMul(6*FRACUNIT, mo->scale);
 						}
-#ifdef ESLOPE
 						else if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8)
 						{
 							// Pop the object up a bit to encourage bounciness
 							//mom.z = P_MobjFlip(mo)*mo->scale;
 						}
-#endif
 						else
 						{
 							mom.x = mom.y = mom.z = 0;
@@ -2790,11 +2719,9 @@ static boolean P_ZMovement(mobj_t *mo)
 		else if (tmfloorthing)
 			mom.z = tmfloorthing->momz;
 
-#ifdef ESLOPE
 		if (mo->standingslope) { // MT_STEAM will never have a standingslope, see above.
 			P_QuantizeMomentumToSlope(&mom, mo->standingslope);
 		}
-#endif
 
 		mo->momx = mom.x;
 		mo->momy = mom.y;
@@ -2916,7 +2843,6 @@ static void P_PlayerZMovement(mobj_t *mo)
 	|| mo->player->playerstate == PST_REBORN)
 		return;
 
-#ifdef ESLOPE
 	if (mo->standingslope)
 	{
 		if (mo->flags & MF_NOCLIPHEIGHT)
@@ -2924,7 +2850,6 @@ static void P_PlayerZMovement(mobj_t *mo)
 		else if (!onground)
 			P_SlopeLaunch(mo);
 	}
-#endif
 
 	// clip movement
 	if (onground && !(mo->flags & MF_NOCLIPHEIGHT))
@@ -2952,12 +2877,10 @@ static void P_PlayerZMovement(mobj_t *mo)
 		if (mo->player->panim == PA_PAIN)
 			P_SetPlayerMobjState(mo, S_PLAY_WALK);
 
-#ifdef ESLOPE
 		if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) {
 			// Handle landing on slope during Z movement
 			P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope));
 		}
-#endif
 
 		if (P_MobjFlip(mo)*mo->momz < 0) // falling
 		{
@@ -3290,10 +3213,8 @@ static boolean P_SceneryZMovement(mobj_t *mo)
 //
 boolean P_CanRunOnWater(player_t *player, ffloor_t *rover)
 {
-	fixed_t topheight =
-#ifdef ESLOPE
-		*rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) :
-#endif
+	fixed_t topheight = *rover->t_slope ?
+		P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) :
 		*rover->topheight;
 
 	if (!player->powers[pw_carry] && !player->homing
@@ -3340,13 +3261,11 @@ void P_MobjCheckWater(mobj_t *mobj)
 		topheight = *rover->topheight;
 		bottomheight = *rover->bottomheight;
 
-#ifdef ESLOPE
 		if (*rover->t_slope)
 			topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
 
 		if (*rover->b_slope)
 			bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
-#endif
 
 		if (mobj->eflags & MFE_VERTICALFLIP)
 		{
@@ -3596,13 +3515,11 @@ static void P_SceneryCheckWater(mobj_t *mobj)
 			topheight = *rover->topheight;
 			bottomheight = *rover->bottomheight;
 
-#ifdef ESLOPE
 			if (*rover->t_slope)
 				topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
 
 			if (*rover->b_slope)
 				bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
-#endif
 
 			if (topheight <= mobj->z
 				|| bottomheight > (mobj->z + (mobj->height>>1)))
@@ -3647,14 +3564,12 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
 			if (!(rover->flags & FF_EXISTS))
 				continue;
 
-			if (halfheight >= (
-#ifdef ESLOPE
-					*rover->t_slope ? P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) :
-#endif
-					*rover->topheight) || halfheight <= (
-#ifdef ESLOPE
-					*rover->b_slope ? P_GetZAt(*rover->b_slope, thiscam->x, thiscam->y) :
-#endif
+			if (halfheight >= (*rover->t_slope ?
+					P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) :
+					*rover->topheight))
+				continue;
+			if (halfheight <= (*rover->b_slope ?
+					P_GetZAt(*rover->b_slope, thiscam->x, thiscam->y) :
 					*rover->bottomheight))
 				continue;
 
@@ -3683,14 +3598,12 @@ static boolean P_CameraCheckWater(camera_t *thiscam)
 			if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKOTHERS)
 				continue;
 
-			if (halfheight >= (
-#ifdef ESLOPE
-					*rover->t_slope ? P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) :
-#endif
-					*rover->topheight) || halfheight <= (
-#ifdef ESLOPE
+			if (halfheight >= (*rover->t_slope ?
+					P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) :
+					*rover->topheight))
+				continue;
+			if (halfheight <= (
 					*rover->b_slope ? P_GetZAt(*rover->b_slope, thiscam->x, thiscam->y) :
-#endif
 					*rover->bottomheight))
 				continue;
 
@@ -3880,9 +3793,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
 
 	P_MobjCheckWater(mobj);
 
-#ifdef ESLOPE
 	P_ButteredSlope(mobj);
-#endif
 
 	// momentum movement
 	mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN;
@@ -4041,10 +3952,8 @@ static void CalculatePrecipFloor(precipmobj_t *mobj)
 		mobjsecsubsec = mobj->subsector->sector;
 	else
 		return;
-	mobj->floorz =
-#ifdef ESLOPE
-				mobjsecsubsec->f_slope ? P_GetZAt(mobjsecsubsec->f_slope, mobj->x, mobj->y) :
-#endif
+	mobj->floorz = mobjsecsubsec->f_slope ?
+				P_GetZAt(mobjsecsubsec->f_slope, mobj->x, mobj->y) :
 				mobjsecsubsec->floorheight;
 	if (mobjsecsubsec->ffloors)
 	{
@@ -4060,12 +3969,10 @@ static void CalculatePrecipFloor(precipmobj_t *mobj)
 			if (!(rover->flags & FF_BLOCKOTHERS) && !(rover->flags & FF_SWIMMABLE))
 				continue;
 
-#ifdef ESLOPE
 			if (*rover->t_slope)
 				topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
 			else
-#endif
-			topheight = *rover->topheight;
+				topheight = *rover->topheight;
 
 			if (topheight > mobj->floorz)
 				mobj->floorz = topheight;
@@ -10241,7 +10148,7 @@ void P_MobjThinker(mobj_t *mobj)
 		mobj->eflags &= ~MFE_JUSTHITFLOOR;
 	}
 
-#ifdef ESLOPE // Sliding physics for slidey mobjs!
+	// Sliding physics for slidey mobjs!
 	if (mobj->type == MT_FLINGRING
 		|| mobj->type == MT_FLINGCOIN
 		|| mobj->type == MT_FLINGBLUESPHERE
@@ -10256,7 +10163,6 @@ void P_MobjThinker(mobj_t *mobj)
 		//if (mobj->standingslope) CONS_Printf("slope physics on mobj\n");
 		P_ButteredSlope(mobj);
 	}
-#endif
 
 	if (mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->health
 		&& P_CheckDeathPitCollide(mobj)) // extra pit check in case these didn't have momz
@@ -10590,15 +10496,11 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 	// Make sure scale matches destscale immediately when spawned
 	P_SetScale(mobj, mobj->destscale);
 
-	mobj->floorz =
-#ifdef ESLOPE
-				mobj->subsector->sector->f_slope ? P_GetZAt(mobj->subsector->sector->f_slope, x, y) :
-#endif
+	mobj->floorz = mobj->subsector->sector->f_slope ?
+				P_GetZAt(mobj->subsector->sector->f_slope, x, y) :
 				mobj->subsector->sector->floorheight;
-	mobj->ceilingz =
-#ifdef ESLOPE
-				mobj->subsector->sector->c_slope ? P_GetZAt(mobj->subsector->sector->c_slope, x, y) :
-#endif
+	mobj->ceilingz = mobj->subsector->sector->c_slope ?
+				P_GetZAt(mobj->subsector->sector->c_slope, x, y) :
 				mobj->subsector->sector->ceilingheight;
 
 	mobj->floorrover = NULL;
@@ -10952,15 +10854,11 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
 	// set subsector and/or block links
 	P_SetPrecipitationThingPosition(mobj);
 
-	mobj->floorz = starting_floorz =
-#ifdef ESLOPE
-				mobj->subsector->sector->f_slope ? P_GetZAt(mobj->subsector->sector->f_slope, x, y) :
-#endif
+	mobj->floorz = starting_floorz = mobj->subsector->sector->f_slope ?
+				P_GetZAt(mobj->subsector->sector->f_slope, x, y) :
 				mobj->subsector->sector->floorheight;
-	mobj->ceilingz =
-#ifdef ESLOPE
-				mobj->subsector->sector->c_slope ? P_GetZAt(mobj->subsector->sector->c_slope, x, y) :
-#endif
+	mobj->ceilingz = mobj->subsector->sector->c_slope ?
+				P_GetZAt(mobj->subsector->sector->c_slope, x, y) :
 				mobj->subsector->sector->ceilingheight;
 
 	mobj->floorrover = NULL;
@@ -11596,16 +11494,12 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
 	// set Z height
 	sector = R_PointInSubsector(x, y)->sector;
 
-	floor =
-#ifdef ESLOPE
-	sector->f_slope ? P_GetZAt(sector->f_slope, x, y) :
-#endif
-	sector->floorheight;
-	ceiling =
-#ifdef ESLOPE
-	sector->c_slope ? P_GetZAt(sector->c_slope, x, y) :
-#endif
-	sector->ceilingheight;
+	floor = sector->f_slope ?
+		P_GetZAt(sector->f_slope, x, y) :
+		sector->floorheight;
+	ceiling = sector->c_slope ?
+		P_GetZAt(sector->c_slope, x, y) :
+		sector->ceilingheight;
 	ceilingspawn = ceiling - mobjinfo[MT_PLAYER].height;
 
 	if (mthing)
@@ -11675,16 +11569,12 @@ void P_MovePlayerToStarpost(INT32 playernum)
 	P_SetThingPosition(mobj);
 	sector = R_PointInSubsector(mobj->x, mobj->y)->sector;
 
-	floor =
-#ifdef ESLOPE
-	sector->f_slope ? P_GetZAt(sector->f_slope, mobj->x, mobj->y) :
-#endif
-	sector->floorheight;
-	ceiling =
-#ifdef ESLOPE
-	sector->c_slope ? P_GetZAt(sector->c_slope, mobj->x, mobj->y) :
-#endif
-	sector->ceilingheight;
+	floor = sector->f_slope ?
+		P_GetZAt(sector->f_slope, mobj->x, mobj->y) :
+		sector->floorheight;
+	ceiling = sector->c_slope ?
+		P_GetZAt(sector->c_slope, mobj->x, mobj->y) :
+		sector->ceilingheight;
 
 	z = p->starpostz << FRACBITS;
 
@@ -11733,17 +11623,11 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x,
 
 	// Establish height.
 	if (flip)
-		return (
-#ifdef ESLOPE
-			ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) :
-#endif
-			ss->sector->ceilingheight) - offset - mobjinfo[mobjtype].height;
+		return (ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : ss->sector->ceilingheight)
+			- offset - mobjinfo[mobjtype].height;
 	else
-		return (
-#ifdef ESLOPE
-			ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) :
-#endif
-			ss->sector->floorheight) + offset;
+		return (ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : ss->sector->floorheight)
+			+ offset;
 }
 
 static fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y)
diff --git a/src/p_mobj.h b/src/p_mobj.h
index 63c91571b..5deb288e4 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -370,9 +370,7 @@ typedef struct mobj_s
 	INT32 cusval;
 	INT32 cvmem;
 
-#ifdef ESLOPE
 	struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
-#endif
 
 	boolean colorized; // Whether the mobj uses the rainbow colormap
 	fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 37d5f99ba..716904432 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -31,9 +31,7 @@
 #include "r_sky.h"
 #include "p_polyobj.h"
 #include "lua_script.h"
-#ifdef ESLOPE
 #include "p_slopes.h"
-#endif
 
 savedata_t savedata;
 UINT8 *save_p;
@@ -1252,9 +1250,7 @@ typedef enum
 	MD2_HPREV       = 1<<8,
 	MD2_FLOORROVER  = 1<<9,
 	MD2_CEILINGROVER = 1<<10,
-#ifdef ESLOPE
 	MD2_SLOPE        = 1<<11,
-#endif
 	MD2_COLORIZED    = 1<<12,
 	MD2_ROLLANGLE    = 1<<13,
 	MD2_SHADOWSCALE  = 1<<14,
@@ -1294,10 +1290,8 @@ typedef enum
 	tc_fade,
 	tc_fadecolormap,
 	tc_planedisplace,
-#ifdef ESLOPE
 	tc_dynslopeline,
 	tc_dynslopevert,
-#endif // ESLOPE
 #ifdef POLYOBJECTS
 	tc_polyrotate, // haleyjd 03/26/06: polyobjects
 	tc_polymove,
@@ -1336,13 +1330,11 @@ static inline UINT32 SavePlayer(const player_t *player)
 	return 0xFFFFFFFF;
 }
 
-#ifdef ESLOPE
 static UINT32 SaveSlope(const pslope_t *slope)
 {
 	if (slope) return (UINT32)(slope->id);
 	return 0xFFFFFFFF;
 }
-#endif // ESLOPE
 
 //
 // SaveMobjThinker
@@ -1471,10 +1463,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 		diff2 |= MD2_FLOORROVER;
 	if (mobj->ceilingrover)
 		diff2 |= MD2_CEILINGROVER;
-#ifdef ESLOPE
 	if (mobj->standingslope)
 		diff2 |= MD2_SLOPE;
-#endif
 	if (mobj->colorized)
 		diff2 |= MD2_COLORIZED;
 	if (mobj->rollangle)
@@ -1639,10 +1629,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 		WRITEUINT32(save_p, mobj->hnext->mobjnum);
 	if (diff2 & MD2_HPREV)
 		WRITEUINT32(save_p, mobj->hprev->mobjnum);
-#ifdef ESLOPE
 	if (diff2 & MD2_SLOPE)
 		WRITEUINT16(save_p, mobj->standingslope->id);
-#endif
 	if (diff2 & MD2_COLORIZED)
 		WRITEUINT8(save_p, mobj->colorized);
 	if (diff2 & MD2_ROLLANGLE)
@@ -1993,7 +1981,7 @@ static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type)
 	WRITEFIXED(save_p, ht->speed);
 	WRITEUINT8(save_p, ht->type);
 }
-#ifdef ESLOPE
+
 /// Save a dynamic slope thinker.
 static inline void SaveDynamicSlopeThinker(const thinker_t *th, const UINT8 type)
 {
@@ -2008,7 +1996,6 @@ static inline void SaveDynamicSlopeThinker(const thinker_t *th, const UINT8 type
 	WRITEMEM(save_p, ht->tags, sizeof(ht->tags));
     WRITEMEM(save_p, ht->vex, sizeof(ht->vex));
 }
-#endif // ESLOPE
 
 #ifdef POLYOBJECTS
 
@@ -2391,7 +2378,6 @@ static void P_NetArchiveThinkers(void)
 				continue;
 			}
 #endif
-#ifdef ESLOPE
 			else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine)
 			{
 				SaveDynamicSlopeThinker(th, tc_dynslopeline);
@@ -2402,7 +2388,6 @@ static void P_NetArchiveThinkers(void)
 				SaveDynamicSlopeThinker(th, tc_dynslopevert);
 				continue;
 			}
-#endif // ESLOPE
 #ifdef PARANOIA
 			else if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed) // wait garbage collection
 				I_Error("unknown thinker type %p", th->function.acp1);
@@ -2463,7 +2448,6 @@ static inline player_t *LoadPlayer(UINT32 player)
 	return &players[player];
 }
 
-#ifdef ESLOPE
 static inline pslope_t *LoadSlope(UINT32 slopeid)
 {
 	pslope_t *p = slopelist;
@@ -2475,7 +2459,6 @@ static inline pslope_t *LoadSlope(UINT32 slopeid)
 	} while ((p = p->next));
 	return NULL;
 }
-#endif // ESLOPE
 
 //
 // LoadMobjThinker
@@ -2720,10 +2703,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 		mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p);
 	if (diff2 & MD2_HPREV)
 		mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p);
-#ifdef ESLOPE
 	if (diff2 & MD2_SLOPE)
 		mobj->standingslope = P_SlopeById(READUINT16(save_p));
-#endif
 	if (diff2 & MD2_COLORIZED)
 		mobj->colorized = READUINT8(save_p);
 	if (diff2 & MD2_ROLLANGLE)
@@ -3183,7 +3164,6 @@ static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-#ifdef ESLOPE
 /// Save a dynamic slope thinker.
 static inline thinker_t* LoadDynamicSlopeThinker(actionf_p1 thinker)
 {
@@ -3198,7 +3178,6 @@ static inline thinker_t* LoadDynamicSlopeThinker(actionf_p1 thinker)
 	READMEM(save_p, ht->vex, sizeof(ht->vex));
 	return &ht->thinker;
 }
-#endif // ESLOPE
 
 #ifdef POLYOBJECTS
 
@@ -3578,7 +3557,7 @@ static void P_NetUnArchiveThinkers(void)
 					th = LoadPolyfadeThinker((actionf_p1)T_PolyObjFade);
 					break;
 #endif
-#ifdef ESLOPE
+
 				case tc_dynslopeline:
 					th = LoadDynamicSlopeThinker((actionf_p1)T_DynamicSlopeLine);
 					break;
@@ -3586,7 +3565,6 @@ static void P_NetUnArchiveThinkers(void)
 				case tc_dynslopevert:
 					th = LoadDynamicSlopeThinker((actionf_p1)T_DynamicSlopeVert);
 					break;
-#endif // ESLOPE
 
 				case tc_scroll:
 					th = LoadScrollThinker((actionf_p1)T_Scroll);
diff --git a/src/p_setup.c b/src/p_setup.c
index b3b86886f..cdf867d61 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -77,9 +77,7 @@
 #include "hardware/hw_model.h"
 #endif
 
-#ifdef ESLOPE
 #include "p_slopes.h"
-#endif
 
 #include "fastcmp.h" // textmap parsing
 
@@ -909,11 +907,9 @@ static void P_InitializeSector(sector_t *ss)
 	ss->preciplist = NULL;
 	ss->touching_preciplist = NULL;
 
-#ifdef ESLOPE
 	ss->f_slope = NULL;
 	ss->c_slope = NULL;
 	ss->hasslope = false;
-#endif
 
 	ss->spawn_lightlevel = ss->lightlevel;
 
@@ -3580,9 +3576,7 @@ boolean P_LoadLevel(boolean fromnetsave)
 	// anything that P_SpawnSlopes/P_LoadThings needs to know
 	P_InitSpecials();
 
-#ifdef ESLOPE
 	P_SpawnSlopes(fromnetsave);
-#endif
 
 	P_SpawnMapThings(!fromnetsave);
 	skyboxmo[0] = skyboxviewpnts[0];
diff --git a/src/p_sight.c b/src/p_sight.c
index 4ea14cca0..c9083b99b 100644
--- a/src/p_sight.c
+++ b/src/p_sight.c
@@ -218,9 +218,7 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
 		const vertex_t *v1,*v2;
 		fixed_t frac;
 		fixed_t frontf, backf, frontc, backc;
-#ifdef ESLOPE
 		fixed_t fracx, fracy;
-#endif
 
 		if (seg->glseg)
 			continue;
@@ -263,7 +261,6 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
 
 		front = seg->frontsector;
 		back  = seg->backsector;
-#ifdef ESLOPE
 		// calculate position at intercept
 		fracx = los->strace.x + FixedMul(los->strace.dx, frac);
 		fracy = los->strace.y + FixedMul(los->strace.dy, frac);
@@ -272,12 +269,6 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
 		frontc = (front->c_slope) ? P_GetZAt(front->c_slope, fracx, fracy) : front->ceilingheight;
 		backf  = (back->f_slope)  ? P_GetZAt(back->f_slope, fracx, fracy)  : back->floorheight;
 		backc  = (back->c_slope)  ? P_GetZAt(back->c_slope, fracx, fracy)  : back->ceilingheight;
-#else
-		frontf = front->floorheight;
-		frontc = front->ceilingheight;
-		backf  = back->floorheight;
-		backc  = back->ceilingheight;
-#endif
 		// crosses a two sided line
 		// no wall to block sight with?
 		if (frontf == backf && frontc == backc
@@ -327,13 +318,8 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
 					continue;
 				}
 
-#ifdef ESLOPE
 				topz    = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight;
 				bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight;
-#else
-				topz    = *rover->topheight;
-				bottomz = *rover->bottomheight;
-#endif
 				topslope    = FixedDiv(topz - los->sightzstart , frac);
 				bottomslope = FixedDiv(bottomz - los->sightzstart , frac);
 				if (topslope >= los->topslope && bottomslope <= los->bottomslope)
@@ -348,13 +334,8 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
 					continue;
 				}
 
-#ifdef ESLOPE
 				topz    = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight;
 				bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight;
-#else
-				topz    = *rover->topheight;
-				bottomz = *rover->bottomheight;
-#endif
 				topslope    = FixedDiv(topz - los->sightzstart , frac);
 				bottomslope = FixedDiv(bottomz - los->sightzstart , frac);
 				if (topslope >= los->topslope && bottomslope <= los->bottomslope)
@@ -487,7 +468,6 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
 				continue;
 			}
 
-#ifdef ESLOPE
 			if (*rover->t_slope)
 			{
 				topz1 = P_GetZAt(*rover->t_slope, t1->x, t1->y);
@@ -503,10 +483,6 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
 			}
 			else
 				bottomz1 = bottomz2 = *rover->bottomheight;
-#else
-			topz1 = topz2 = *rover->topheight;
-			bottomz1 = bottomz2 = *rover->bottomheight;
-#endif
 
 			// Check for blocking floors here.
 			if ((los.sightzstart < bottomz1 && t2->z >= topz2)
diff --git a/src/p_slopes.c b/src/p_slopes.c
index e275964e3..4b5838077 100644
--- a/src/p_slopes.c
+++ b/src/p_slopes.c
@@ -23,8 +23,6 @@
 #include "p_maputl.h"
 #include "w_wad.h"
 
-#ifdef ESLOPE
-
 pslope_t *slopelist = NULL;
 UINT16 slopecount = 0;
 
@@ -844,6 +842,3 @@ void P_ButteredSlope(mobj_t *mo)
 
 	P_Thrust(mo, mo->standingslope->xydirection, thrust);
 }
-
-// EOF
-#endif // #ifdef ESLOPE
diff --git a/src/p_slopes.h b/src/p_slopes.h
index f8159b884..e7c850ab8 100644
--- a/src/p_slopes.h
+++ b/src/p_slopes.h
@@ -15,8 +15,6 @@
 
 #include "m_fixed.h" // Vectors
 
-#ifdef ESLOPE
-
 extern pslope_t *slopelist;
 extern UINT16 slopecount;
 
@@ -74,5 +72,4 @@ typedef struct
 
 void T_DynamicSlopeLine (dynplanethink_t* th);
 void T_DynamicSlopeVert (dynplanethink_t* th);
-#endif // #ifdef ESLOPE
 #endif // #ifndef P_SLOPES_H__
diff --git a/src/p_spec.c b/src/p_spec.c
index 8938a51b6..cd26dcf9e 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -5788,7 +5788,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
 	fflr->topyoffs = &sec2->ceiling_yoffs;
 	fflr->topangle = &sec2->ceilingpic_angle;
 
-#ifdef ESLOPE
 	// Add slopes
 	fflr->t_slope = &sec2->c_slope;
 	fflr->b_slope = &sec2->f_slope;
@@ -5796,7 +5795,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
 	// (this fixes FOF slopes glitching initially at level load in software mode)
 	if (sec2->hasslope)
 		sec->hasslope = true;
-#endif
 
 	if ((flags & FF_SOLID) && (master->flags & ML_EFFECT1)) // Block player only
 		flags &= ~FF_BLOCKOTHERS;
@@ -6274,15 +6272,11 @@ void T_LaserFlash(laserthink_t *flash)
 
 	sourcesec = fflr->master->frontsector; // Less to type!
 
-#ifdef ESLOPE
 	top = (*fflr->t_slope) ? P_GetZAt(*fflr->t_slope, sector->soundorg.x, sector->soundorg.y)
 			: *fflr->topheight;
 	bottom = (*fflr->b_slope) ? P_GetZAt(*fflr->b_slope, sector->soundorg.x, sector->soundorg.y)
 			: *fflr->bottomheight;
 	sector->soundorg.z = (top + bottom)/2;
-#else
-	sector->soundorg.z = (*fflr->topheight + *fflr->bottomheight)/2;
-#endif
 	S_StartSound(&sector->soundorg, sfx_laser);
 
 	// Seek out objects to DESTROY! MUAHAHHAHAHAA!!!*cough*
@@ -7927,12 +7921,10 @@ void T_Disappear(disappear_t *d)
 
 					if (!(lines[d->sourceline].flags & ML_NOCLIMB))
 					{
-#ifdef ESLOPE
 						if (*rover->t_slope)
 							sectors[s].soundorg.z = P_GetZAt(*rover->t_slope, sectors[s].soundorg.x, sectors[s].soundorg.y);
 						else
-#endif
-						sectors[s].soundorg.z = *rover->topheight;
+							sectors[s].soundorg.z = *rover->topheight;
 						S_StartSound(&sectors[s].soundorg, sfx_appear);
 					}
 				}
diff --git a/src/p_user.c b/src/p_user.c
index 19b53e16f..c12bc0c59 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -2274,13 +2274,8 @@ boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space
 
 			if (GETSECSPECIAL(rover->master->frontsector->special, 1) != SPACESPECIAL)
 				continue;
-#ifdef ESLOPE
 			topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : *rover->topheight;
 			bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : *rover->bottomheight;
-#else
-			topheight = *rover->topheight;
-			bottomheight = *rover->bottomheight;
-#endif
 
 			if (mo->z + (mo->height/2) > topheight)
 				continue;
@@ -2517,13 +2512,8 @@ boolean P_InQuicksand(mobj_t *mo) // Returns true if you are in quicksand
 			if (!(rover->flags & FF_QUICKSAND))
 				continue;
 
-#ifdef ESLOPE
 			topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : *rover->topheight;
 			bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : *rover->bottomheight;
-#else
-			topheight = *rover->topheight;
-			bottomheight = *rover->bottomheight;
-#endif
 
 			if (mo->z + flipoffset > topheight)
 				continue;
@@ -2693,9 +2683,7 @@ static void P_CheckBouncySectors(player_t *player)
 	fixed_t oldx;
 	fixed_t oldy;
 	fixed_t oldz;
-#ifdef ESLOPE
 	vector3_t momentum;
-#endif
 
 	oldx = player->mo->x;
 	oldy = player->mo->y;
@@ -2750,7 +2738,6 @@ static void P_CheckBouncySectors(player_t *player)
 					{
 						fixed_t newmom;
 
-#ifdef ESLOPE
 						pslope_t *slope;
 						if (abs(oldz - topheight) < abs(oldz + player->mo->height - bottomheight)) { // Hit top
 							slope = *rover->t_slope;
@@ -2766,9 +2753,6 @@ static void P_CheckBouncySectors(player_t *player)
 							P_ReverseQuantizeMomentumToSlope(&momentum, slope);
 
 						newmom = momentum.z = -FixedMul(momentum.z,linedist)/2;
-#else
-						newmom = -FixedMul(player->mo->momz,linedist);
-#endif
 
 						if (abs(newmom) < (linedist*2))
 						{
@@ -2791,7 +2775,6 @@ static void P_CheckBouncySectors(player_t *player)
 						else if (newmom < -P_GetPlayerHeight(player)/2)
 							newmom = -P_GetPlayerHeight(player)/2;
 
-#ifdef ESLOPE
 						momentum.z = newmom*2;
 
 						if (slope)
@@ -2800,9 +2783,6 @@ static void P_CheckBouncySectors(player_t *player)
 						player->mo->momx = momentum.x;
 						player->mo->momy = momentum.y;
 						player->mo->momz = momentum.z/2;
-#else
-						player->mo->momz = newmom;
-#endif
 
 						if (player->pflags & PF_SPINNING)
 						{
@@ -2859,13 +2839,8 @@ static void P_CheckQuicksand(player_t *player)
 		if (!(rover->flags & FF_QUICKSAND))
 			continue;
 
-#ifdef ESLOPE
 		topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight;
 		bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight;
-#else
-		topheight = *rover->topheight;
-		bottomheight = *rover->bottomheight;
-#endif
 
 		if (topheight >= player->mo->z && bottomheight < player->mo->z + player->mo->height)
 		{
@@ -3199,26 +3174,21 @@ static void P_DoClimbing(player_t *player)
 		boolean thrust = false;
 		boolean boostup = false;
 		boolean skyclimber = false;
-		fixed_t floorheight, ceilingheight; // ESLOPE
+		fixed_t floorheight, ceilingheight;
 
 		if (!glidesector)
 			floorclimb = true;
 		else
 		{
-#ifdef ESLOPE
 			floorheight = glidesector->sector->f_slope ? P_GetZAt(glidesector->sector->f_slope, player->mo->x, player->mo->y)
 													   : glidesector->sector->floorheight;
 			ceilingheight = glidesector->sector->c_slope ? P_GetZAt(glidesector->sector->c_slope, player->mo->x, player->mo->y)
 														 : glidesector->sector->ceilingheight;
-#else
-			floorheight = glidesector->sector->floorheight;
-			ceilingheight = glidesector->sector->ceilingheight;
-#endif
 
 			if (glidesector->sector->ffloors)
 			{
 				ffloor_t *rover;
-				fixed_t topheight, bottomheight; // ESLOPE
+				fixed_t topheight, bottomheight;
 
 				for (rover = glidesector->sector->ffloors; rover; rover = rover->next)
 				{
@@ -3227,13 +3197,8 @@ static void P_DoClimbing(player_t *player)
 
 					floorclimb = true;
 
-#ifdef ESLOPE
 					topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight;
 					bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight;
-#else
-					topheight = *rover->topheight;
-					bottomheight = *rover->bottomheight;
-#endif
 
 					// Only supports rovers that are moving like an 'elevator', not just the top or bottom.
 					if (rover->master->frontsector->floorspeed && rover->master->frontsector->ceilspeed == 42)
@@ -3274,11 +3239,7 @@ static void P_DoClimbing(player_t *player)
 								if (roverbelow == rover)
 									continue;
 
-#ifdef ESLOPE
 								bottomheight2 = *roverbelow->b_slope ? P_GetZAt(*roverbelow->b_slope, player->mo->x, player->mo->y) : *roverbelow->bottomheight;
-#else
-								bottomheight2 = *roverbelow->bottomheight;
-#endif
 
 								if (bottomheight2 < topheight + FixedMul(16*FRACUNIT, player->mo->scale))
 									foundfof = true;
@@ -3324,11 +3285,7 @@ static void P_DoClimbing(player_t *player)
 								if (roverbelow == rover)
 									continue;
 
-#ifdef ESLOPE
 								topheight2 = *roverbelow->t_slope ? P_GetZAt(*roverbelow->t_slope, player->mo->x, player->mo->y) : *roverbelow->topheight;
-#else
-								topheight2 = *roverbelow->topheight;
-#endif
 
 								if (topheight2 > bottomheight - FixedMul(16*FRACUNIT, player->mo->scale))
 									foundfof = true;
@@ -3383,11 +3340,7 @@ static void P_DoClimbing(player_t *player)
 							if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
 								continue;
 
-#ifdef ESLOPE
 							bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight;
-#else
-							bottomheight = *rover->bottomheight;
-#endif
 
 							if (bottomheight < floorheight + FixedMul(16*FRACUNIT, player->mo->scale))
 							{
@@ -3428,11 +3381,7 @@ static void P_DoClimbing(player_t *player)
 							if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
 								continue;
 
-#ifdef ESLOPE
 							topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight;
-#else
-							topheight = *rover->topheight;
-#endif
 
 							if (topheight > ceilingheight - FixedMul(16*FRACUNIT, player->mo->scale))
 							{
@@ -3807,12 +3756,10 @@ static void P_DoTeeter(player_t *player)
 
 			ceilingheight = sec->ceilingheight;
 			floorheight = sec->floorheight;
-#ifdef ESLOPE
 			if (sec->c_slope)
 				ceilingheight = P_GetZAt(sec->c_slope, checkx, checky);
 			if (sec->f_slope)
 				floorheight = P_GetZAt(sec->f_slope, checkx, checky);
-#endif
 			highestceilingheight = (ceilingheight > highestceilingheight) ? ceilingheight : highestceilingheight;
 			lowestfloorheight = (floorheight < lowestfloorheight) ? floorheight : lowestfloorheight;
 
@@ -3823,13 +3770,8 @@ static void P_DoTeeter(player_t *player)
 			{
 				if (!(rover->flags & FF_EXISTS)) continue;
 
-#ifdef ESLOPE
 				topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight;
 				bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight;
-#else
-				topheight = *rover->topheight;
-				bottomheight = *rover->bottomheight;
-#endif
 
 				if (P_CheckSolidLava(rover))
 					;
@@ -4638,9 +4580,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
 			return;
 	}
 
-#ifdef ESLOPE
 	canstand = (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2);
-#endif
 
 	///////////////////////////////
 	// ability-specific behavior //
@@ -5903,12 +5843,10 @@ static void P_3dMovement(player_t *player)
 	controlstyle_e controlstyle;
 	boolean spin = ((onground = P_IsObjectOnGround(player->mo)) && (player->pflags & (PF_SPINNING|PF_THOKKED)) == PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH));
 	fixed_t oldMagnitude, newMagnitude;
-#ifdef ESLOPE
 	vector3_t totalthrust;
 
 	totalthrust.x = totalthrust.y = 0; // I forget if this is needed
 	totalthrust.z = FRACUNIT*P_MobjFlip(player->mo)/3; // A bit of extra push-back on slopes
-#endif // ESLOPE
 
 	// Get the old momentum; this will be needed at the end of the function! -SH
 	oldMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
@@ -6109,12 +6047,8 @@ static void P_3dMovement(player_t *player)
 
 		movepushforward = FixedMul(movepushforward, player->mo->scale);
 
-#ifdef ESLOPE
 		totalthrust.x += P_ReturnThrustX(player->mo, movepushangle, movepushforward);
 		totalthrust.y += P_ReturnThrustY(player->mo, movepushangle, movepushforward);
-#else
-		P_Thrust(player->mo, movepushangle, movepushforward);
-#endif
 	}
 	// Sideways movement
 	if (player->climbing)
@@ -6157,12 +6091,8 @@ static void P_3dMovement(player_t *player)
 
 			movepushforward = FixedMul(movepushforward, player->mo->scale);
 
-#ifdef ESLOPE
 			totalthrust.x += P_ReturnThrustX(player->mo, controldirection, movepushforward);
 			totalthrust.y += P_ReturnThrustY(player->mo, controldirection, movepushforward);
-#else
-			P_Thrust(player->mo, controldirection, movepushforward);
-#endif
 		}
 	}
 	else if (cmd->sidemove && !(player->pflags & PF_GLIDING) && !player->exiting && !P_PlayerInPain(player))
@@ -6191,15 +6121,10 @@ static void P_3dMovement(player_t *player)
 		// Finally move the player now that their speed/direction has been decided.
 		movepushside = FixedMul(movepushside, player->mo->scale);
 
-#ifdef ESLOPE
 		totalthrust.x += P_ReturnThrustX(player->mo, movepushsideangle, movepushside);
 		totalthrust.y += P_ReturnThrustY(player->mo, movepushsideangle, movepushside);
-#else
-		P_Thrust(player->mo, movepushsideangle, movepushside);
-#endif
 	}
 
-#ifdef ESLOPE
 	if ((totalthrust.x || totalthrust.y)
 		&& player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) > FRACUNIT/2) {
 		// Factor thrust to slope, but only for the part pushing up it!
@@ -6219,7 +6144,6 @@ static void P_3dMovement(player_t *player)
 
 	player->mo->momx += totalthrust.x;
 	player->mo->momy += totalthrust.y;
-#endif
 
 	// Time to ask three questions:
 	// 1) Are we over topspeed?
@@ -7832,14 +7756,13 @@ void P_ElementalFire(player_t *player, boolean cropcircle)
 			newx = player->mo->x + P_ReturnThrustX(player->mo, (travelangle + ((i&1) ? -1 : 1)*ANGLE_135), FixedMul(24*FRACUNIT, player->mo->scale));
 			newy = player->mo->y + P_ReturnThrustY(player->mo, (travelangle + ((i&1) ? -1 : 1)*ANGLE_135), FixedMul(24*FRACUNIT, player->mo->scale));
 
-#ifdef ESLOPE
 			if (player->mo->standingslope)
 			{
 				ground = P_GetZAt(player->mo->standingslope, newx, newy);
 				if (player->mo->eflags & MFE_VERTICALFLIP)
 					ground -= FixedMul(mobjinfo[MT_SPINFIRE].height, player->mo->scale);
 			}
-#endif
+
 			flame = P_SpawnMobj(newx, newy, ground, MT_SPINFIRE);
 			P_SetTarget(&flame->target, player->mo);
 			flame->angle = travelangle;
@@ -10740,13 +10663,8 @@ static void P_CalcPostImg(player_t *player)
 			if (!(rover->flags & FF_EXISTS))
 				continue;
 
-#ifdef ESLOPE
 			topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight;
 			bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight;
-#else
-			topheight = *rover->topheight;
-			bottomheight = *rover->bottomheight;
-#endif
 
 			if (pviewheight >= topheight || pviewheight <= bottomheight)
 				continue;
@@ -10768,13 +10686,8 @@ static void P_CalcPostImg(player_t *player)
 			if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKPLAYER)
 				continue;
 
-#ifdef ESLOPE
 			topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight;
 			bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight;
-#else
-			topheight = *rover->topheight;
-			bottomheight = *rover->bottomheight;
-#endif
 
 			if (pviewheight >= topheight || pviewheight <= bottomheight)
 				continue;
diff --git a/src/r_bsp.c b/src/r_bsp.c
index c0011f4b9..85113be43 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -359,10 +359,8 @@ boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
 #endif
 		back->ceilingpic == front->ceilingpic
 		&& back->floorpic == front->floorpic
-#ifdef ESLOPE
 		&& back->f_slope == front->f_slope
 		&& back->c_slope == front->c_slope
-#endif
 		&& back->lightlevel == front->lightlevel
 		&& !line->sidedef->midtexture
 		// Check offsets too!
@@ -497,7 +495,6 @@ static void R_AddLine(seg_t *line)
 	}
 
 	// Closed door.
-#ifdef ESLOPE
 	if (frontsector->f_slope || frontsector->c_slope || backsector->f_slope || backsector->c_slope)
 	{
 		fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
@@ -542,7 +539,6 @@ static void R_AddLine(seg_t *line)
 				goto clippass;
 	}
 	else
-#endif
 	{
 		// if both ceilings are skies, consider it always "open"
 		// same for floors
@@ -863,16 +859,12 @@ static void R_Subsector(size_t num)
 
 	floorcolormap = ceilingcolormap = frontsector->extra_colormap;
 
-	floorcenterz =
-#ifdef ESLOPE
-		frontsector->f_slope ? P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
-#endif
+	floorcenterz = frontsector->f_slope ?
+		P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
 		frontsector->floorheight;
 
-	ceilingcenterz =
-#ifdef ESLOPE
-		frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
-#endif
+	ceilingcenterz = frontsector->c_slope ?
+		P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
 		frontsector->ceilingheight;
 
 	// Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps.
@@ -899,34 +891,23 @@ static void R_Subsector(size_t num)
 
 	sub->sector->extra_colormap = frontsector->extra_colormap;
 
-	if (((
-#ifdef ESLOPE
-			frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) :
-#endif
-		frontsector->floorheight) < viewz || frontsector->floorpic == skyflatnum
-		|| (frontsector->heightsec != -1
-		&& sectors[frontsector->heightsec].ceilingpic == skyflatnum)))
+	if ((frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) : frontsector->floorheight) < viewz
+		|| frontsector->floorpic == skyflatnum
+		|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum))
 	{
 		floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel,
 			frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL
 #ifdef POLYOBJECTS_PLANES
 			, NULL
 #endif
-#ifdef ESLOPE
-			, frontsector->f_slope
-#endif
-			);
+			, frontsector->f_slope);
 	}
 	else
 		floorplane = NULL;
 
-	if (((
-#ifdef ESLOPE
-			frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) :
-#endif
-		frontsector->ceilingheight) > viewz || frontsector->ceilingpic == skyflatnum
-		|| (frontsector->heightsec != -1
-		&& sectors[frontsector->heightsec].floorpic == skyflatnum)))
+	if ((frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) : frontsector->ceilingheight) > viewz
+		|| frontsector->ceilingpic == skyflatnum
+		|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum))
 	{
 		ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic,
 			ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle,
@@ -934,18 +915,13 @@ static void R_Subsector(size_t num)
 #ifdef POLYOBJECTS_PLANES
 			, NULL
 #endif
-#ifdef ESLOPE
-			, frontsector->c_slope
-#endif
-			);
+			, frontsector->c_slope);
 	}
 	else
 		ceilingplane = NULL;
 
 	numffloors = 0;
-#ifdef ESLOPE
 	ffloor[numffloors].slope = NULL;
-#endif
 	ffloor[numffloors].plane = NULL;
 	ffloor[numffloors].polyobj = NULL;
 	if (frontsector->ffloors)
@@ -970,16 +946,12 @@ static void R_Subsector(size_t num)
 			ffloor[numffloors].plane = NULL;
 			ffloor[numffloors].polyobj = NULL;
 
-			heightcheck =
-#ifdef ESLOPE
-				*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) :
-#endif
+			heightcheck = *rover->b_slope ?
+				P_GetZAt(*rover->b_slope, viewx, viewy) :
 				*rover->bottomheight;
 
-			planecenterz =
-#ifdef ESLOPE
-				*rover->b_slope ? P_GetZAt(*rover->b_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
-#endif
+			planecenterz = *rover->b_slope ?
+				P_GetZAt(*rover->b_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
 				*rover->bottomheight;
 			if (planecenterz <= ceilingcenterz
 				&& planecenterz >= floorcenterz
@@ -995,18 +967,13 @@ static void R_Subsector(size_t num)
 #ifdef POLYOBJECTS_PLANES
 					, NULL
 #endif
-#ifdef ESLOPE
-					, *rover->b_slope
-#endif
-					);
+					, *rover->b_slope);
 
-#ifdef ESLOPE
 				ffloor[numffloors].slope = *rover->b_slope;
 
 				// Tell the renderer this sector has slopes in it.
 				if (ffloor[numffloors].slope)
 					frontsector->hasslope = true;
-#endif
 
 				ffloor[numffloors].height = heightcheck;
 				ffloor[numffloors].ffloor = rover;
@@ -1017,16 +984,12 @@ static void R_Subsector(size_t num)
 			ffloor[numffloors].plane = NULL;
 			ffloor[numffloors].polyobj = NULL;
 
-			heightcheck =
-#ifdef ESLOPE
-				*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) :
-#endif
+			heightcheck = *rover->t_slope ?
+				P_GetZAt(*rover->t_slope, viewx, viewy) :
 				*rover->topheight;
 
-			planecenterz =
-#ifdef ESLOPE
-				*rover->t_slope ? P_GetZAt(*rover->t_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
-#endif
+			planecenterz = *rover->t_slope ?
+				P_GetZAt(*rover->t_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
 				*rover->topheight;
 			if (planecenterz >= floorcenterz
 				&& planecenterz <= ceilingcenterz
@@ -1041,18 +1004,13 @@ static void R_Subsector(size_t num)
 #ifdef POLYOBJECTS_PLANES
 					, NULL
 #endif
-#ifdef ESLOPE
-					, *rover->t_slope
-#endif
-					);
+					, *rover->t_slope);
 
-#ifdef ESLOPE
 				ffloor[numffloors].slope = *rover->t_slope;
 
 				// Tell the renderer this sector has slopes in it.
 				if (ffloor[numffloors].slope)
 					frontsector->hasslope = true;
-#endif
 
 				ffloor[numffloors].height = heightcheck;
 				ffloor[numffloors].ffloor = rover;
@@ -1090,18 +1048,13 @@ static void R_Subsector(size_t num)
 				ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic,
 					(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floor_xoffs, polysec->floor_yoffs,
 					polysec->floorpic_angle-po->angle,
-					(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po
-#ifdef ESLOPE
-					, NULL // will ffloors be slopable eventually?
-#endif
-					);
+					(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
+					NULL); // will ffloors be slopable eventually?
 
 				ffloor[numffloors].height = polysec->floorheight;
 				ffloor[numffloors].polyobj = po;
-#ifdef ESLOPE
 				ffloor[numffloors].slope = NULL;
-#endif
-//				ffloor[numffloors].ffloor = rover;
+				//ffloor[numffloors].ffloor = rover;
 				po->visplane = ffloor[numffloors].plane;
 				numffloors++;
 			}
@@ -1118,18 +1071,13 @@ static void R_Subsector(size_t num)
 				light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
 				ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
 					(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle,
-					(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po
-#ifdef ESLOPE
-					, NULL // will ffloors be slopable eventually?
-#endif
-					);
+					(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
+					NULL); // will ffloors be slopable eventually?
 
 				ffloor[numffloors].polyobj = po;
 				ffloor[numffloors].height = polysec->ceilingheight;
-#ifdef ESLOPE
 				ffloor[numffloors].slope = NULL;
-#endif
-//				ffloor[numffloors].ffloor = rover;
+				//ffloor[numffloors].ffloor = rover;
 				po->visplane = ffloor[numffloors].plane;
 				numffloors++;
 			}
@@ -1192,11 +1140,9 @@ void R_Prep3DFloors(sector_t *sector)
 	fixed_t bestheight, maxheight;
 	INT32 count, i;
 	sector_t *sec;
-#ifdef ESLOPE
 	pslope_t *bestslope = NULL;
 	fixed_t heighttest; // I think it's better to check the Z height at the sector's center
 	                    // than assume unsloped heights are accurate indicators of order in sloped sectors. -Red
-#endif
 
 	count = 1;
 	for (rover = sector->ffloors; rover; rover = rover->next)
@@ -1219,14 +1165,10 @@ void R_Prep3DFloors(sector_t *sector)
 	else
 		memset(sector->lightlist, 0, sizeof (lightlist_t) * count);
 
-#ifdef ESLOPE
 	heighttest = sector->c_slope ? P_GetZAt(sector->c_slope, sector->soundorg.x, sector->soundorg.y) : sector->ceilingheight;
 
 	sector->lightlist[0].height = heighttest + 1;
 	sector->lightlist[0].slope = sector->c_slope;
-#else
-	sector->lightlist[0].height = sector->ceilingheight + 1;
-#endif
 	sector->lightlist[0].lightlevel = &sector->lightlevel;
 	sector->lightlist[0].caster = NULL;
 	sector->lightlist[0].extra_colormap = &sector->extra_colormap;
@@ -1244,7 +1186,6 @@ void R_Prep3DFloors(sector_t *sector)
 				&& !(rover->flags & FF_CUTLEVEL) && !(rover->flags & FF_CUTSPRITES)))
 			continue;
 
-#ifdef ESLOPE
 			heighttest = *rover->t_slope ? P_GetZAt(*rover->t_slope, sector->soundorg.x, sector->soundorg.y) : *rover->topheight;
 
 			if (heighttest > bestheight && heighttest < maxheight)
@@ -1266,21 +1207,6 @@ void R_Prep3DFloors(sector_t *sector)
 					continue;
 				}
 			}
-#else
-			if (*rover->topheight > bestheight && *rover->topheight < maxheight)
-			{
-				best = rover;
-				bestheight = *rover->topheight;
-				continue;
-			}
-			if (rover->flags & FF_DOUBLESHADOW && *rover->bottomheight > bestheight
-				&& *rover->bottomheight < maxheight)
-			{
-				best = rover;
-				bestheight = *rover->bottomheight;
-				continue;
-			}
-#endif
 		}
 		if (!best)
 		{
@@ -1291,9 +1217,7 @@ void R_Prep3DFloors(sector_t *sector)
 		sector->lightlist[i].height = maxheight = bestheight;
 		sector->lightlist[i].caster = best;
 		sector->lightlist[i].flags = best->flags;
-#ifdef ESLOPE
 		sector->lightlist[i].slope = bestslope;
-#endif
 		sec = &sectors[best->secnum];
 
 		if (best->flags & FF_NOSHADE)
@@ -1314,12 +1238,8 @@ void R_Prep3DFloors(sector_t *sector)
 
 		if (best->flags & FF_DOUBLESHADOW)
 		{
-#ifdef ESLOPE
 			heighttest = *best->b_slope ? P_GetZAt(*best->b_slope, sector->soundorg.x, sector->soundorg.y) : *best->bottomheight;
 			if (bestheight == heighttest) ///TODO: do this in a more efficient way -Red
-#else
-			if (bestheight == *best->bottomheight)
-#endif
 			{
 				sector->lightlist[i].lightlevel = sector->lightlist[best->lastlight].lightlevel;
 				sector->lightlist[i].extra_colormap =
diff --git a/src/r_defs.h b/src/r_defs.h
index e6f1e4e7c..0c6ff1d30 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -171,11 +171,9 @@ typedef struct ffloor_s
 	fixed_t *bottomyoffs;
 	angle_t *bottomangle;
 
-#ifdef ESLOPE
 	// Pointers to pointers. Yup.
 	struct pslope_s **t_slope;
 	struct pslope_s **b_slope;
-#endif
 
 	size_t secnum;
 	ffloortype_e flags;
@@ -208,9 +206,7 @@ typedef struct lightlist_s
 	extracolormap_t **extra_colormap; // pointer-to-a-pointer, so we can react to colormap changes
 	INT32 flags;
 	ffloor_t *caster;
-#ifdef ESLOPE
 	struct pslope_s *slope; // FF_DOUBLESHADOW makes me have to store this pointer here. Bluh bluh.
-#endif
 } lightlist_t;
 
 
@@ -244,7 +240,6 @@ typedef struct linechain_s
 
 
 // Slopes
-#ifdef ESLOPE
 typedef enum {
 	SL_NOPHYSICS = 1, /// This plane will have no physics applied besides the positioning.
 	SL_DYNAMIC = 1<<1, /// This plane slope will be assigned a thinker to make it dynamic.
@@ -268,7 +263,6 @@ typedef struct pslope_s
 
 	UINT8 flags; // Slope options
 } pslope_t;
-#endif
 
 typedef enum
 {
@@ -379,12 +373,10 @@ typedef struct sector_s
 	precipmobj_t *preciplist;
 	struct mprecipsecnode_s *touching_preciplist;
 
-#ifdef ESLOPE
 	// Eternity engine slope
 	pslope_t *f_slope; // floor slope
 	pslope_t *c_slope; // ceiling slope
 	boolean hasslope; // The sector, or one of its visible FOFs, contains a slope
-#endif
 
 	// for fade thinker
 	INT16 spawn_lightlevel;
@@ -668,11 +660,9 @@ typedef struct drawseg_s
 
 	UINT8 portalpass; // if > 0 and <= portalrender, do not affect sprite clipping
 
-#ifdef ESLOPE
 	fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures
 
 	vertex_t leftpos, rightpos; // Used for rendering FOF walls with slopes
-#endif
 } drawseg_t;
 
 typedef enum
diff --git a/src/r_draw.c b/src/r_draw.c
index f46f4fb13..b983db0aa 100644
--- a/src/r_draw.c
+++ b/src/r_draw.c
@@ -105,12 +105,10 @@ boolean ds_powersoftwo;
 UINT8 *ds_source; // start of a 64*64 tile image
 UINT8 *ds_transmap; // one of the translucency tables
 
-#ifdef ESLOPE
 pslope_t *ds_slope; // Current slope being used
 floatv3_t ds_su[MAXVIDHEIGHT], ds_sv[MAXVIDHEIGHT], ds_sz[MAXVIDHEIGHT]; // Vectors for... stuff?
 floatv3_t *ds_sup, *ds_svp, *ds_szp;
 float focallengthf, zeroheight;
-#endif
 
 /**	\brief Variable flat sizes
 */
diff --git a/src/r_draw.h b/src/r_draw.h
index 870d294c3..4d94f861b 100644
--- a/src/r_draw.h
+++ b/src/r_draw.h
@@ -62,7 +62,6 @@ extern boolean ds_powersoftwo;
 extern UINT8 *ds_source;
 extern UINT8 *ds_transmap;
 
-#ifdef ESLOPE
 typedef struct {
 	float x, y, z;
 } floatv3_t;
@@ -71,7 +70,6 @@ extern pslope_t *ds_slope; // Current slope being used
 extern floatv3_t ds_su[MAXVIDHEIGHT], ds_sv[MAXVIDHEIGHT], ds_sz[MAXVIDHEIGHT]; // Vectors for... stuff?
 extern floatv3_t *ds_sup, *ds_svp, *ds_szp;
 extern float focallengthf, zeroheight;
-#endif
 
 // Variable flat sizes
 extern UINT32 nflatxshift;
@@ -152,7 +150,6 @@ void R_DrawSpan_8(void);
 void R_DrawSplat_8(void);
 void R_DrawTranslucentSpan_8(void);
 void R_DrawTranslucentSplat_8(void);
-#ifdef ESLOPE
 void R_DrawTiltedSpan_8(void);
 void R_DrawTiltedTranslucentSpan_8(void);
 #ifndef NOWATER
@@ -161,7 +158,6 @@ void R_DrawTiltedTranslucentWaterSpan_8(void);
 void R_DrawTiltedSplat_8(void);
 void R_CalcTiltedLighting(fixed_t start, fixed_t end);
 extern INT32 tiltlighting[MAXVIDWIDTH];
-#endif
 #ifndef NOWATER
 void R_DrawTranslucentWaterSpan_8(void);
 extern INT32 ds_bgofs;
@@ -174,14 +170,12 @@ void R_DrawSpan_NPO2_8(void);
 void R_DrawTranslucentSpan_NPO2_8(void);
 void R_DrawSplat_NPO2_8(void);
 void R_DrawTranslucentSplat_NPO2_8(void);
-#ifdef ESLOPE
 void R_DrawTiltedSpan_NPO2_8(void);
 void R_DrawTiltedTranslucentSpan_NPO2_8(void);
 #ifndef NOWATER
 void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void);
 #endif
 void R_DrawTiltedSplat_NPO2_8(void);
-#endif
 #ifndef NOWATER
 void R_DrawTranslucentWaterSpan_NPO2_8(void);
 #endif
diff --git a/src/r_draw8.c b/src/r_draw8.c
index fe0a23770..940ea724b 100644
--- a/src/r_draw8.c
+++ b/src/r_draw8.c
@@ -620,7 +620,6 @@ void R_DrawSpan_8 (void)
 	}
 }
 
-#ifdef ESLOPE
 // R_CalcTiltedLighting
 // Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly.
 INT32 tiltlighting[MAXVIDWIDTH];
@@ -1199,7 +1198,6 @@ void R_DrawTiltedSplat_8(void)
 	}
 #endif
 }
-#endif // ESLOPE
 
 /**	\brief The R_DrawSplat_8 function
 	Just like R_DrawSpan_8, but skips transparent pixels.
diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c
index b91f492f2..020155694 100644
--- a/src/r_draw8_npo2.c
+++ b/src/r_draw8_npo2.c
@@ -61,8 +61,6 @@ void R_DrawSpan_NPO2_8 (void)
 	}
 }
 
-#ifdef ESLOPE
-
 #define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan))
 
 /**	\brief The R_DrawTiltedSpan_NPO2_8 function
@@ -661,7 +659,6 @@ void R_DrawTiltedSplat_NPO2_8(void)
 	}
 #endif
 }
-#endif // ESLOPE
 
 /**	\brief The R_DrawSplat_NPO2_8 function
 	Just like R_DrawSpan_NPO2_8, but skips transparent pixels.
@@ -846,7 +843,6 @@ void R_DrawTranslucentWaterSpan_NPO2_8(void)
 	}
 }
 
-#ifdef ESLOPE
 /**	\brief The R_DrawTiltedTranslucentWaterSpan_NPO2_8 function
 	Like DrawTiltedTranslucentSpan_NPO2, but for water
 */
@@ -1043,5 +1039,4 @@ void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void)
 	}
 #endif
 }
-#endif // ESLOPE
 #endif // NOWATER
diff --git a/src/r_main.c b/src/r_main.c
index 409a82f28..9a3d98870 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -459,9 +459,7 @@ static void R_InitTextureMapping(void)
 	focallength = FixedDiv(projection,
 		FINETANGENT(FINEANGLES/4+FIELDOFVIEW/2));
 
-#ifdef ESLOPE
 	focallengthf = FIXED_TO_FLOAT(focallength);
-#endif
 
 	for (i = 0; i < FINEANGLES/2; i++)
 	{
diff --git a/src/r_plane.c b/src/r_plane.c
index e1e45517a..ca5aa758e 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -202,7 +202,6 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
 		// Needed for ds_bgofs
 		R_PlaneRipple(currentplane, y, planeheight);
 
-#ifdef ESLOPE
 		if (currentplane->slope)
 		{
 			ds_sup = &ds_su[y];
@@ -210,7 +209,6 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
 			ds_szp = &ds_sz[y];
 		}
 		else
-#endif
 		{
 			ds_xfrac += ripple_xfrac;
 			ds_yfrac += ripple_yfrac;
@@ -227,12 +225,10 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
 	if (pindex >= MAXLIGHTZ)
 		pindex = MAXLIGHTZ - 1;
 
-#ifdef ESLOPE
 	if (currentplane->slope)
 		ds_colormap = colormaps;
 	else
-#endif
-	ds_colormap = planezlight[pindex];
+		ds_colormap = planezlight[pindex];
 
 	if (currentplane->extra_colormap)
 		ds_colormap = currentplane->extra_colormap->colormap + (ds_colormap - colormaps);
@@ -345,17 +341,12 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 #ifdef POLYOBJECTS_PLANES
 			, polyobj_t *polyobj
 #endif
-#ifdef ESLOPE
-			, pslope_t *slope
-#endif
-			)
+			, pslope_t *slope)
 {
 	visplane_t *check;
 	unsigned hash;
 
-#ifdef ESLOPE
-	if (slope); else // Don't mess with this right now if a slope is involved
-#endif
+	if (!slope) // Don't mess with this right now if a slope is involved
 	{
 		xoff += viewx;
 		yoff -= viewy;
@@ -413,10 +404,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 			&& check->viewx == viewx && check->viewy == viewy && check->viewz == viewz
 			&& check->viewangle == viewangle
 			&& check->plangle == plangle
-#ifdef ESLOPE
-			&& check->slope == slope
-#endif
-			)
+			&& check->slope == slope)
 		{
 			return check;
 		}
@@ -441,9 +429,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 #ifdef POLYOBJECTS_PLANES
 	check->polyobj = polyobj;
 #endif
-#ifdef ESLOPE
 	check->slope = slope;
-#endif
 
 	memset(check->top, 0xff, sizeof (check->top));
 	memset(check->bottom, 0x00, sizeof (check->bottom));
@@ -513,9 +499,7 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop)
 #ifdef POLYOBJECTS_PLANES
 		new_pl->polyobj = pl->polyobj;
 #endif
-#ifdef ESLOPE
 		new_pl->slope = pl->slope;
-#endif
 		pl = new_pl;
 		pl->minx = start;
 		pl->maxx = stop;
@@ -860,7 +844,6 @@ static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boo
 	return flat;
 }
 
-#ifdef ESLOPE
 static void R_SlopeVectors(visplane_t *pl, INT32 i, float fudge)
 {
 	// Potentially override other stuff for now cus we're mean. :< But draw a slope plane!
@@ -951,7 +934,6 @@ d.z = (v1.x * v2.y) - (v1.y * v2.x)
 	}
 #undef SFMULT
 }
-#endif // ESLOPE
 
 void R_DrawSinglePlane(visplane_t *pl)
 {
@@ -1087,10 +1069,8 @@ void R_DrawSinglePlane(visplane_t *pl)
 	}
 	else light = (pl->lightlevel >> LIGHTSEGSHIFT);
 
-#ifdef ESLOPE
-	if (!pl->slope) // Don't mess with angle on slopes! We'll handle this ourselves later
-#endif
-	if (viewangle != pl->viewangle+pl->plangle)
+	if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later
+		&& viewangle != pl->viewangle+pl->plangle)
 	{
 		memset(cachedheight, 0, sizeof (cachedheight));
 		angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT;
@@ -1148,7 +1128,6 @@ void R_DrawSinglePlane(visplane_t *pl)
 	if (light < 0)
 		light = 0;
 
-#ifdef ESLOPE
 	if (pl->slope)
 	{
 		float fudgecanyon = 0;
@@ -1248,10 +1227,9 @@ void R_DrawSinglePlane(visplane_t *pl)
 			spanfunctype = SPANDRAWFUNC_TILTED;
 
 		planezlight = scalelight[light];
-	} else
-#endif // ESLOPE
-
-	planezlight = zlight[light];
+	}
+	else
+		planezlight = zlight[light];
 
 	// Use the correct span drawer depending on the powers-of-twoness
 	if (!ds_powersoftwo)
diff --git a/src/r_plane.h b/src/r_plane.h
index 405dd9726..a1a5b7a78 100644
--- a/src/r_plane.h
+++ b/src/r_plane.h
@@ -50,9 +50,7 @@ typedef struct visplane_s
 #ifdef POLYOBJECTS_PLANES
 	polyobj_t *polyobj;
 #endif
-#ifdef ESLOPE
 	pslope_t *slope;
-#endif
 } visplane_t;
 
 extern visplane_t *visplanes[MAXVISPLANES];
@@ -86,10 +84,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t
 #ifdef POLYOBJECTS_PLANES
 	, polyobj_t *polyobj
 #endif
-#ifdef ESLOPE
-	, pslope_t *slope
-#endif
-	);
+	, pslope_t *slope);
 visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop);
 void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
 void R_PlaneBounds(visplane_t *plane);
@@ -110,13 +105,11 @@ typedef struct planemgr_s
 	INT16 f_clip[MAXVIDWIDTH];
 	INT16 c_clip[MAXVIDWIDTH];
 
-#ifdef ESLOPE
 	// For slope rendering; the height at the other end
 	fixed_t f_pos_slope;
 	fixed_t b_pos_slope;
 
 	struct pslope_s *slope;
-#endif
 
 	struct ffloor_s *ffloor;
 #ifdef POLYOBJECTS_PLANES
diff --git a/src/r_segs.c b/src/r_segs.c
index 0233b1161..d8f1981ee 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -52,20 +52,16 @@ static fixed_t rw_offset2; // for splats
 static fixed_t rw_scale, rw_scalestep;
 static fixed_t rw_midtexturemid, rw_toptexturemid, rw_bottomtexturemid;
 static INT32 worldtop, worldbottom, worldhigh, worldlow;
-#ifdef ESLOPE
 static INT32 worldtopslope, worldbottomslope, worldhighslope, worldlowslope; // worldtop/bottom at end of slope
 static fixed_t rw_toptextureslide, rw_midtextureslide, rw_bottomtextureslide; // Defines how to adjust Y offsets along the wall for slopes
 static fixed_t rw_midtextureback, rw_midtexturebackslide; // Values for masked midtexture height calculation
-#endif
 static fixed_t pixhigh, pixlow, pixhighstep, pixlowstep;
 static fixed_t topfrac, topstep;
 static fixed_t bottomfrac, bottomstep;
 
 static lighttable_t **walllights;
 static INT16 *maskedtexturecol;
-#ifdef ESLOPE
 static fixed_t *maskedtextureheight = NULL;
-#endif
 
 // ==========================================================================
 // R_Splats Wall Splats Drawer
@@ -299,9 +295,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 	sector_t *front, *back;
 	INT32 times, repeats;
 	INT64 overflow_test;
-#ifdef ESLOPE
 	INT32 range;
-#endif
 
 	// Calculate light table.
 	// Use different light tables
@@ -349,9 +343,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 		colfunc = colfuncs[COLDRAWFUNC_FUZZY];
 	}
 
-#ifdef ESLOPE
 	range = max(ds->x2-ds->x1, 1);
-#endif
 	rw_scalestep = ds->scalestep;
 	spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
 
@@ -389,12 +381,9 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 
 		for (i = 0; i < dc_numlights; i++)
 		{
-#ifdef ESLOPE
 			fixed_t leftheight, rightheight;
-#endif
 			light = &frontsector->lightlist[i];
 			rlight = &dc_lightlist[i];
-#ifdef ESLOPE
 			if (light->slope) {
 				leftheight = P_GetZAt(light->slope, ds->leftpos.x, ds->leftpos.y);
 				rightheight = P_GetZAt(light->slope, ds->rightpos.x, ds->rightpos.y);
@@ -409,10 +398,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 			rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
 			//if (x1 > ds->x1)
 				//rlight->height -= (x1 - ds->x1)*rlight->heightstep;
-#else
-			rlight->height = (centeryfrac) - FixedMul((light->height - viewz), spryscale);
-			rlight->heightstep = -FixedMul(rw_scalestep, (light->height - viewz));
-#endif
 			rlight->startheight = rlight->height; // keep starting value here to reset for each repeat
 			rlight->lightlevel = *light->lightlevel;
 			rlight->extra_colormap = *light->extra_colormap;
@@ -513,40 +498,17 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 			}
 		}
 
-#ifndef ESLOPE
-		if (curline->linedef->flags & ML_DONTPEGBOTTOM)
-		{
-			dc_texturemid = front->floorheight > back->floorheight
-				? front->floorheight : back->floorheight;
-			dc_texturemid = dc_texturemid + textureheight[texnum] - viewz;
-		}
-		else
-		{
-			dc_texturemid = front->ceilingheight < back->ceilingheight
-				? front->ceilingheight : back->ceilingheight;
-			dc_texturemid = dc_texturemid - viewz;
-		}
-		dc_texturemid += curline->sidedef->rowoffset;
-
-		if (curline->linedef->flags & ML_DONTPEGBOTTOM)
-			dc_texturemid += (textureheight[texnum])*times;
-		else
-			dc_texturemid -= (textureheight[texnum])*times;
-#endif
-
 		dc_texheight = textureheight[texnum]>>FRACBITS;
 
 		// draw the columns
 		for (dc_x = x1; dc_x <= x2; dc_x++)
 		{
-#ifdef ESLOPE
 			dc_texturemid = ds->maskedtextureheight[dc_x];
 
 			if (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3))
 				dc_texturemid += (textureheight[texnum])*times + textureheight[texnum];
 			else
 				dc_texturemid -= (textureheight[texnum])*times;
-#endif
 			// calculate lighting
 			if (maskedtexturecol[dc_x] != INT16_MAX)
 			{
@@ -755,14 +717,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	fixed_t         offsetvalue = 0;
 	lightlist_t     *light;
 	r_lightlist_t   *rlight;
-#ifdef ESLOPE
 	INT32           range;
-#endif
-#ifndef ESLOPE
-	fixed_t         lheight;
-#endif
 	line_t          *newline = NULL;
-#ifdef ESLOPE
 	// Render FOF sides kinda like normal sides, with the frac and step and everything
 	// NOTE: INT64 instead of fixed_t because overflow concerns
 	INT64         top_frac, top_step, bottom_frac, bottom_step;
@@ -772,7 +728,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	INT32         oldx = -1;
 	fixed_t       left_top, left_bottom; // needed here for slope skewing
 	pslope_t      *skewslope = NULL;
-#endif
 
 	void (*colfunc_2s) (column_t *);
 
@@ -829,9 +784,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	else if (pfloor->flags & FF_FOG)
 		colfunc = colfuncs[COLDRAWFUNC_FOG];
 
-#ifdef ESLOPE
 	range = max(ds->x2-ds->x1, 1);
-#endif
 	//SoM: Moved these up here so they are available for my lightlist calculations
 	rw_scalestep = ds->scalestep;
 	spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
@@ -848,14 +801,11 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 
 		for (i = p = 0; i < dc_numlights; i++)
 		{
-#ifdef ESLOPE
 			fixed_t leftheight, rightheight;
 			fixed_t pfloorleft, pfloorright;
 			INT64 overflow_test;
-#endif
 			light = &frontsector->lightlist[i];
 			rlight = &dc_lightlist[p];
-#ifdef ESLOPE
 
 #define SLOPEPARAMS(slope, end1, end2, normalheight) \
 	if (slope) { \
@@ -896,21 +846,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 			else if (overflow_test > (INT64)CLAMPMIN) rlight->heightstep = (fixed_t)overflow_test;
 			else                                      rlight->heightstep = CLAMPMIN;
 			rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
-#else
-			if (light->height < *pfloor->bottomheight)
-				continue;
-
-			if (light->height > *pfloor->topheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > *pfloor->topheight)
-				continue;
-
-			lheight = light->height;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : light->height;
-			rlight->heightstep = -FixedMul (rw_scalestep, (lheight - viewz));
-			rlight->height = (centeryfrac) - FixedMul((lheight - viewz), spryscale);
-#endif
 			rlight->flags = light->flags;
 			if (light->flags & FF_CUTLEVEL)
 			{
-#ifdef ESLOPE
 				SLOPEPARAMS(*light->caster->b_slope, leftheight, rightheight, *light->caster->bottomheight)
 #undef SLOPEPARAMS
 				leftheight -= viewz;
@@ -927,11 +865,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 				else if (overflow_test > (INT64)CLAMPMIN) rlight->botheightstep = (fixed_t)overflow_test;
 				else                                      rlight->botheightstep = CLAMPMIN;
 				rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range);
-#else
-				lheight = *light->caster->bottomheight;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : *light->caster->bottomheight;
-				rlight->botheightstep = -FixedMul (rw_scalestep, (lheight - viewz));
-				rlight->botheight = (centeryfrac) - FixedMul((lheight - viewz), spryscale);
-#endif
 			}
 
 			rlight->lightlevel = *light->lightlevel;
@@ -988,7 +921,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	mceilingclip = ds->sprtopclip;
 	dc_texheight = textureheight[texnum]>>FRACBITS;
 
-#ifdef ESLOPE
 	// calculate both left ends
 	if (*pfloor->t_slope)
 		left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz;
@@ -1011,21 +943,18 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	if (slopeskew)
 		dc_texturemid = left_top;
 	else
-#endif
-	dc_texturemid = *pfloor->topheight - viewz;
+		dc_texturemid = *pfloor->topheight - viewz;
 
 	if (newline)
 	{
 		offsetvalue = sides[newline->sidenum[0]].rowoffset;
 		if (newline->flags & ML_DONTPEGBOTTOM)
 		{
-#ifdef ESLOPE
 			skewslope = *pfloor->b_slope; // skew using bottom slope
 			if (slopeskew)
 				dc_texturemid = left_bottom;
 			else
-#endif
-			offsetvalue -= *pfloor->topheight - *pfloor->bottomheight;
+				offsetvalue -= *pfloor->topheight - *pfloor->bottomheight;
 		}
 	}
 	else
@@ -1033,17 +962,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 		offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset;
 		if (curline->linedef->flags & ML_DONTPEGBOTTOM)
 		{
-#ifdef ESLOPE
 			skewslope = *pfloor->b_slope; // skew using bottom slope
 			if (slopeskew)
 				dc_texturemid = left_bottom;
 			else
-#endif
-			offsetvalue -= *pfloor->topheight - *pfloor->bottomheight;
+				offsetvalue -= *pfloor->topheight - *pfloor->bottomheight;
 		}
 	}
 
-#ifdef ESLOPE
 	if (slopeskew)
 	{
 		angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y);
@@ -1051,7 +977,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 		if (skewslope)
 			ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT));
 	}
-#endif
 
 	dc_texturemid += offsetvalue;
 
@@ -1076,7 +1001,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 		column2s_length = textures[texnum]->height;
 	}
 
-#ifdef ESLOPE
 	// Set heights according to plane, or slope, whichever
 	{
 		fixed_t right_top, right_bottom;
@@ -1104,24 +1028,20 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 		top_frac += top_step * (x1 - ds->x1);
 		bottom_frac += bottom_step * (x1 - ds->x1);
 	}
-#endif
 
 	// draw the columns
 	for (dc_x = x1; dc_x <= x2; dc_x++)
 	{
 		if (maskedtexturecol[dc_x] != INT16_MAX)
 		{
-#ifdef ESLOPE
 			if (ffloortextureslide) { // skew FOF walls
 				if (oldx != -1)
 					dc_texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])<<FRACBITS);
 				oldx = dc_x;
 			}
-#endif
 			// Calculate bounds
 			// clamp the values if necessary to avoid overflows and rendering glitches caused by them
 
-#ifdef ESLOPE
 			if      (top_frac > (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX;
 			else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac;
 			else                                 sprtopscreen = windowtop = CLAMPMIN;
@@ -1131,10 +1051,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 
 			top_frac += top_step;
 			bottom_frac += bottom_step;
-#else
-			sprtopscreen = windowtop = (centeryfrac - FixedMul((dc_texturemid - offsetvalue), spryscale));
-			sprbotscreen = windowbottom = FixedMul(*pfloor->topheight - *pfloor->bottomheight, spryscale) + sprtopscreen;
-#endif
 
 			// SoM: If column is out of range, why bother with it??
 			if (windowbottom < topbounds || windowtop > bottombounds)
@@ -1344,9 +1260,7 @@ static void R_RenderSegLoop (void)
 
 	INT32     mid;
 	fixed_t texturecolumn = 0;
-#ifdef ESLOPE
 	fixed_t oldtexturecolumn = -1;
-#endif
 	INT32     top;
 	INT32     bottom;
 	INT32     i;
@@ -1466,7 +1380,6 @@ static void R_RenderSegLoop (void)
 		angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
 		texturecolumn = rw_offset-FixedMul(FINETANGENT(angle),rw_distance);
 
-#ifdef ESLOPE
 		if (oldtexturecolumn != -1) {
 			rw_bottomtexturemid += FixedMul(rw_bottomtextureslide,  oldtexturecolumn-texturecolumn);
 			rw_midtexturemid    += FixedMul(rw_midtextureslide,     oldtexturecolumn-texturecolumn);
@@ -1474,7 +1387,6 @@ static void R_RenderSegLoop (void)
 			rw_midtextureback   += FixedMul(rw_midtexturebackslide, oldtexturecolumn-texturecolumn);
 		}
 		oldtexturecolumn = texturecolumn;
-#endif
 
 		texturecolumn >>= FRACBITS;
 
@@ -1650,13 +1562,11 @@ static void R_RenderSegLoop (void)
 			//  for backdrawing of masked mid texture
 			maskedtexturecol[rw_x] = (INT16)texturecolumn;
 
-#ifdef ESLOPE
 			if (maskedtextureheight != NULL) {
 				maskedtextureheight[rw_x] = (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3) ?
 											max(rw_midtexturemid, rw_midtextureback) :
 											min(rw_midtexturemid, rw_midtextureback));
 			}
-#endif
 		}
 
 		if (dc_numlights)
@@ -1712,26 +1622,19 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	fixed_t       sineval;
 	angle_t       distangle, offsetangle;
 	boolean longboi;
-#ifndef ESLOPE
-	fixed_t       vtop;
-#endif
 	INT32           lightnum;
 	INT32           i, p;
 	lightlist_t   *light;
 	r_lightlist_t *rlight;
 	INT32 range;
-#ifdef ESLOPE
 	vertex_t segleft, segright;
 	fixed_t ceilingfrontslide, floorfrontslide, ceilingbackslide, floorbackslide;
-#endif
 	static size_t maxdrawsegs = 0;
 
-#ifdef ESLOPE
 	maskedtextureheight = NULL;
 	//initialize segleft and segright
 	memset(&segleft, 0x00, sizeof(segleft));
 	memset(&segright, 0x00, sizeof(segright));
-#endif
 
 	colfunc = colfuncs[BASEDRAWFUNC];
 
@@ -1841,7 +1744,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 	// calculate texture boundaries
 	//  and decide if floor / ceiling marks are needed
-#ifdef ESLOPE
 	// Figure out map coordinates of where start and end are mapping to on seg, so we can clip right for slope bullshit
 	if (frontsector->hasslope || (backsector && backsector->hasslope)) // Commenting this out for FOFslop. -Red
 	{
@@ -1908,10 +1810,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	worldtopslope -= viewz;
 	worldbottom -= viewz;
 	worldbottomslope -= viewz;
-#else
-	worldtop = frontsector->ceilingheight - viewz;
-	worldbottom = frontsector->floorheight - viewz;
-#endif
 
 	midtexture = toptexture = bottomtexture = maskedtexture = 0;
 	ds_p->maskedtexturecol = NULL;
@@ -1933,18 +1831,15 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 				continue;
 #endif
 
-#ifdef ESLOPE
 			if (ffloor[i].slope) {
 				ffloor[i].f_pos = P_GetZAt(ffloor[i].slope, segleft.x, segleft.y) - viewz;
 				ffloor[i].f_pos_slope = P_GetZAt(ffloor[i].slope, segright.x, segright.y) - viewz;
-			} else
-				ffloor[i].f_pos_slope =
-#endif
-			ffloor[i].f_pos = ffloor[i].height - viewz;
+			}
+			else
+				ffloor[i].f_pos_slope = ffloor[i].f_pos = ffloor[i].height - viewz;
 		}
 	}
 
-#ifdef ESLOPE
 	// Set up texture Y offset slides for sloped walls
 	rw_toptextureslide = rw_midtextureslide = rw_bottomtextureslide = 0;
 	ceilingfrontslide = floorfrontslide = ceilingbackslide = floorbackslide = 0;
@@ -1964,7 +1859,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		if (backsector && backsector->c_slope)
 			ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT));
 	}
-#endif
 
 	if (!backsector)
 	{
@@ -1974,33 +1868,22 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		texheight = textureheight[midtexture];
 		// a single sided line is terminal, so it must mark ends
 		markfloor = markceiling = true;
-#ifdef ESLOPE
 		if (linedef->flags & ML_EFFECT2) {
 			if (linedef->flags & ML_DONTPEGBOTTOM)
 				rw_midtexturemid = frontsector->floorheight + texheight - viewz;
 			else
 				rw_midtexturemid = frontsector->ceilingheight - viewz;
 		}
-		else
-#endif
-		if (linedef->flags & ML_DONTPEGBOTTOM)
+		else if (linedef->flags & ML_DONTPEGBOTTOM)
 		{
-#ifdef ESLOPE
 			rw_midtexturemid = worldbottom + texheight;
 			rw_midtextureslide = floorfrontslide;
-#else
-			vtop = frontsector->floorheight + texheight;
-			// bottom of texture at bottom
-			rw_midtexturemid = vtop - viewz;
-#endif
 		}
 		else
 		{
 			// top of texture at top
 			rw_midtexturemid = worldtop;
-#ifdef ESLOPE
 			rw_midtextureslide = ceilingfrontslide;
-#endif
 		}
 		rw_midtexturemid += sidedef->rowoffset;
 
@@ -2016,17 +1899,12 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		boolean bothceilingssky = false; // turned on if both back and front ceilings are sky
 		boolean bothfloorssky = false; // likewise, but for floors
 
-#ifdef ESLOPE
 		SLOPEPARAMS(backsector->c_slope, worldhigh, worldhighslope, backsector->ceilingheight)
 		SLOPEPARAMS(backsector->f_slope, worldlow,  worldlowslope,  backsector->floorheight)
 		worldhigh -= viewz;
 		worldhighslope -= viewz;
 		worldlow -= viewz;
 		worldlowslope -= viewz;
-#else
-		worldhigh = backsector->ceilingheight - viewz;
-		worldlow = backsector->floorheight - viewz;
-#endif
 
 		// hack to allow height changes in outdoor areas
 		// This is what gets rid of the upper textures if there should be sky
@@ -2048,27 +1926,15 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 		if (!bothfloorssky)
 		{
-			if (
-#ifdef ESLOPE
-				worldbottomslope > worldlowslope ||
-#endif
-				worldbottom > worldlow)
+			if (worldbottomslope > worldlowslope || worldbottom > worldlow)
 			{
 				ds_p->silhouette = SIL_BOTTOM;
-#ifdef ESLOPE
 				if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz)
 					ds_p->bsilheight = INT32_MAX;
 				else
 					ds_p->bsilheight = (frontsector->f_slope ? INT32_MAX : frontsector->floorheight);
-#else
-				ds_p->bsilheight = frontsector->floorheight;
-#endif
 			}
-#ifdef ESLOPE
 			else if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz)
-#else
-			else if (backsector->floorheight > viewz)
-#endif
 			{
 				ds_p->silhouette = SIL_BOTTOM;
 				ds_p->bsilheight = INT32_MAX;
@@ -2078,27 +1944,15 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 		if (!bothceilingssky)
 		{
-			if (
-#ifdef ESLOPE
-				worldtopslope < worldhighslope ||
-#endif
-				worldtop < worldhigh)
+			if (worldtopslope < worldhighslope || worldtop < worldhigh)
 			{
 				ds_p->silhouette |= SIL_TOP;
-#ifdef ESLOPE
 				if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz)
 					ds_p->tsilheight = INT32_MIN;
 				else
 					ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight);
-#else
-				ds_p->tsilheight = frontsector->ceilingheight;
-#endif
 			}
-#ifdef ESLOPE
 			else if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz)
-#else
-			else if (backsector->ceilingheight < viewz)
-#endif
 			{
 				ds_p->silhouette |= SIL_TOP;
 				ds_p->tsilheight = INT32_MIN;
@@ -2108,22 +1962,14 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 		if (!bothceilingssky && !bothfloorssky)
 		{
-#ifdef ESLOPE
 			if (worldhigh <= worldbottom && worldhighslope <= worldbottomslope)
-#else
-			if (worldhigh <= worldbottom)
-#endif
 			{
 				ds_p->sprbottomclip = negonearray;
 				ds_p->bsilheight = INT32_MAX;
 				ds_p->silhouette |= SIL_BOTTOM;
 			}
 
-#ifdef ESLOPE
 			if (worldlow >= worldtop && worldlowslope >= worldtopslope)
-#else
-			if (worldlow >= worldtop)
-#endif
 			{
 				ds_p->sprtopclip = screenheightarray;
 				ds_p->tsilheight = INT32_MIN;
@@ -2136,21 +1982,13 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		// Without the following code, sprites get displayed behind closed doors.
 		if (!bothceilingssky && !bothfloorssky)
 		{
-#ifdef ESLOPE
 			if (doorclosed || (worldhigh <= worldbottom && worldhighslope <= worldbottomslope))
-#else
-			if (doorclosed || backsector->ceilingheight <= frontsector->floorheight)
-#endif
 			{
 				ds_p->sprbottomclip = negonearray;
 				ds_p->bsilheight = INT32_MAX;
 				ds_p->silhouette |= SIL_BOTTOM;
 			}
-#ifdef ESLOPE
 			if (doorclosed || (worldlow >= worldtop && worldlowslope >= worldtopslope))
-#else
-			if (doorclosed || backsector->floorheight >= frontsector->ceilingheight)
-#endif
 			{                   // killough 1/17/98, 2/8/98
 				ds_p->sprtopclip = screenheightarray;
 				ds_p->tsilheight = INT32_MIN;
@@ -2165,10 +2003,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			markfloor = false;
 		}
 		else if (worldlow != worldbottom
-#ifdef ESLOPE
 			|| worldlowslope != worldbottomslope
 			|| backsector->f_slope != frontsector->f_slope
-#endif
 		    || backsector->floorpic != frontsector->floorpic
 		    || backsector->lightlevel != frontsector->lightlevel
 		    //SoM: 3/22/2000: Check floor x and y offsets.
@@ -2198,10 +2034,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			markceiling = false;
 		}
 		else if (worldhigh != worldtop
-#ifdef ESLOPE
 			|| worldhighslope != worldtopslope
 			|| backsector->c_slope != frontsector->c_slope
-#endif
 		    || backsector->ceilingpic != frontsector->ceilingpic
 		    || backsector->lightlevel != frontsector->lightlevel
 		    //SoM: 3/22/2000: Check floor x and y offsets.
@@ -2225,13 +2059,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 		if (!bothceilingssky && !bothfloorssky)
 		{
-#ifdef ESLOPE
 			if ((worldhigh <= worldbottom && worldhighslope <= worldbottomslope)
 			 || (worldlow >= worldtop && worldlowslope >= worldtopslope))
-#else
-			if (backsector->ceilingheight <= frontsector->floorheight
-			 || backsector->floorheight >= frontsector->ceilingheight)
-#endif
 			{
 				// closed door
 				markceiling = markfloor = true;
@@ -2240,11 +2069,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 		// check TOP TEXTURE
 		if (!bothceilingssky // never draw the top texture if on
-			&& (worldhigh < worldtop
-#ifdef ESLOPE
-				|| worldhighslope < worldtopslope
-#endif
-			))
+			&& (worldhigh < worldtop || worldhighslope < worldtopslope))
 		{
 			fixed_t texheight;
 			// top texture
@@ -2264,67 +2089,47 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 				toptexture = R_GetTextureNum(sidedef->toptexture);
 				texheight = textureheight[toptexture];
 			}
-#ifdef ESLOPE
 			if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
 				if (linedef->flags & ML_DONTPEGTOP)
 					rw_toptexturemid = frontsector->ceilingheight - viewz;
 				else
 					rw_toptexturemid = backsector->ceilingheight - viewz;
-			} else
-#endif
-			if (linedef->flags & ML_DONTPEGTOP)
+			}
+			else if (linedef->flags & ML_DONTPEGTOP)
 			{
 				// top of texture at top
 				rw_toptexturemid = worldtop;
-#ifdef ESLOPE
 				rw_toptextureslide = ceilingfrontslide;
-#endif
 			}
 			else
 			{
-#ifdef ESLOPE
 				rw_toptexturemid = worldhigh + texheight;
 				rw_toptextureslide = ceilingbackslide;
-#else
-				vtop = backsector->ceilingheight + texheight;
-				// bottom of texture
-				rw_toptexturemid = vtop - viewz;
-#endif
 			}
 		}
 		// check BOTTOM TEXTURE
 		if (!bothfloorssky // never draw the bottom texture if on
-			&& (worldlow > worldbottom
-#ifdef ESLOPE
-				|| worldlowslope > worldbottomslope
-#endif
-			))     //seulement si VISIBLE!!!
+			&& (worldlow > worldbottom || worldlowslope > worldbottomslope)) // Only if VISIBLE!!!
 		{
 			// bottom texture
 			bottomtexture = R_GetTextureNum(sidedef->bottomtexture);
 
-#ifdef ESLOPE
 			if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
 				if (linedef->flags & ML_DONTPEGBOTTOM)
 					rw_bottomtexturemid = frontsector->floorheight - viewz;
 				else
 					rw_bottomtexturemid = backsector->floorheight - viewz;
-			} else
-#endif
-			if (linedef->flags & ML_DONTPEGBOTTOM)
+			}
+			else if (linedef->flags & ML_DONTPEGBOTTOM)
 			{
 				// bottom of texture at bottom
 				// top of texture at top
 				rw_bottomtexturemid = worldbottom;
-#ifdef ESLOPE
 				rw_bottomtextureslide = floorfrontslide;
-#endif
 			}
 			else {   // top of texture at top
 				rw_bottomtexturemid = worldlow;
-#ifdef ESLOPE
 				rw_bottomtextureslide = floorbackslide;
-#endif
 			}
 		}
 
@@ -2337,12 +2142,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			ffloor_t *rover;
 			ffloor_t *r2;
 			fixed_t   lowcut, highcut;
-#ifdef ESLOPE
 			fixed_t lowcutslope, highcutslope;
 
 			// Used for height comparisons and etc across FOFs and slopes
 			fixed_t high1, highslope1, low1, lowslope1, high2, highslope2, low2, lowslope2;
-#endif
 
 			//markceiling = markfloor = true;
 			maskedtexture = true;
@@ -2352,10 +2155,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 			lowcut = max(worldbottom, worldlow) + viewz;
 			highcut = min(worldtop, worldhigh) + viewz;
-#ifdef ESLOPE
 			lowcutslope = max(worldbottomslope, worldlowslope) + viewz;
 			highcutslope = min(worldtopslope, worldhighslope) + viewz;
-#endif
 
 			if (frontsector->ffloors && backsector->ffloors)
 			{
@@ -2370,16 +2171,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					if (rover->norender == leveltime)
 						continue;
 
-#ifdef ESLOPE
 					SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight)
 					SLOPEPARAMS(*rover->b_slope, low1,  lowslope1,  *rover->bottomheight)
 
 					if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
 						continue;
-#else
-					if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
-						continue;
-#endif
 
 					for (r2 = frontsector->ffloors; r2; r2 = r2->next)
 					{
@@ -2403,7 +2199,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 								continue;
 						}
 
-#ifdef ESLOPE
 						SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight)
 						SLOPEPARAMS(*r2->b_slope, low2,  lowslope2,  *r2->bottomheight)
 
@@ -2411,12 +2206,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 							continue;
 						if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2))
 							continue;
-#else
-						if (*r2->topheight < lowcut || *r2->bottomheight > highcut)
-							continue;
-						if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight)
-							continue;
-#endif
 
 						break;
 					}
@@ -2437,16 +2226,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					if (rover->norender == leveltime)
 						continue;
 
-#ifdef ESLOPE
 					SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight)
 					SLOPEPARAMS(*rover->b_slope, low1,  lowslope1,  *rover->bottomheight)
 
 					if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
 						continue;
-#else
-					if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
-						continue;
-#endif
 
 					for (r2 = backsector->ffloors; r2; r2 = r2->next)
 					{
@@ -2470,7 +2254,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 								continue;
 						}
 
-#ifdef ESLOPE
 						SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight)
 						SLOPEPARAMS(*r2->b_slope, low2,  lowslope2,  *r2->bottomheight)
 #undef SLOPEPARAMS
@@ -2478,12 +2261,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 							continue;
 						if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2))
 							continue;
-#else
-						if (*r2->topheight < lowcut || *r2->bottomheight > highcut)
-							continue;
-						if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight)
-							continue;
-#endif
 
 						break;
 					}
@@ -2503,17 +2280,12 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					if (rover->norender == leveltime)
 						continue;
 
-#ifdef ESLOPE
 					// Oy vey.
-					if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz
-							&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz)
-							||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz
-							&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz))
+					if (      ((*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft .x, segleft .y) : *rover->   topheight) <= worldbottom      + viewz
+					        && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->   topheight) <= worldbottomslope + viewz)
+					        ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft .x, segleft .y) : *rover->bottomheight) >= worldtop         + viewz
+					        && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope    + viewz))
 						continue;
-#else
-					if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight)
-						continue;
-#endif
 
 					ds_p->thicksides[i] = rover;
 					i++;
@@ -2527,25 +2299,18 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 						continue;
 					if (rover->norender == leveltime)
 						continue;
-#ifdef ESLOPE
 					// Oy vey.
-					if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz
-							&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz)
-							||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz
-							&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz))
+					if (      ((*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft .x, segleft .y) : *rover->   topheight) <= worldbottom      + viewz
+					        && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->   topheight) <= worldbottomslope + viewz)
+					        ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft .x, segleft .y) : *rover->bottomheight) >= worldtop         + viewz
+					        && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope    + viewz))
 						continue;
 
-					if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldlow+viewz
-							&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldlowslope+viewz)
-							||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldhigh+viewz
-							&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldhighslope+viewz))
+					if (      ((*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft .x, segleft .y) : *rover->   topheight) <= worldlow       + viewz
+					        && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->   topheight) <= worldlowslope  + viewz)
+					        ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft .x, segleft .y) : *rover->bottomheight) >= worldhigh      + viewz
+					        && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldhighslope + viewz))
 						continue;
-#else
-					if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight)
-						continue;
-					if (*rover->topheight <= backsector->floorheight || *rover->bottomheight >= backsector->ceilingheight)
-						continue;
-#endif
 
 					ds_p->thicksides[i] = rover;
 					i++;
@@ -2565,7 +2330,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			else
 				ds_p->maskedtexturecol = ds_p->thicksidecol;
 
-#ifdef ESLOPE
 			maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0])
 
 #ifdef POLYOBJECTS
@@ -2598,7 +2362,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			}
 			rw_midtexturemid += sidedef->rowoffset;
 			rw_midtextureback += sidedef->rowoffset;
-#endif
 
 			maskedtexture = true;
 		}
@@ -2662,22 +2425,16 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	//  and doesn't need to be marked.
 	if (frontsector->heightsec == -1)
 	{
-		if (frontsector->floorpic != skyflatnum
-		&& (
-#ifdef ESLOPE
-			frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) :
-#endif
+		if (frontsector->floorpic != skyflatnum && (frontsector->f_slope ?
+			P_GetZAt(frontsector->f_slope, viewx, viewy) :
 			frontsector->floorheight) >= viewz)
 		{
 			// above view plane
 			markfloor = false;
 		}
 
-		if (frontsector->ceilingpic != skyflatnum
-		&& (
-#ifdef ESLOPE
-			frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) :
-#endif
+		if (frontsector->ceilingpic != skyflatnum && (frontsector->c_slope ?
+			P_GetZAt(frontsector->c_slope, viewx, viewy) :
 			frontsector->ceilingheight) <= viewz)
 		{
 			// below view plane
@@ -2688,10 +2445,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	// calculate incremental stepping values for texture edges
 	worldtop >>= 4;
 	worldbottom >>= 4;
-#ifdef ESLOPE
 	worldtopslope >>= 4;
 	worldbottomslope >>= 4;
-#endif
 
 	if (linedef->special == HORIZONSPECIAL) { // HORIZON LINES
 		topstep = bottomstep = 0;
@@ -2704,7 +2459,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		bottomstep = -FixedMul (rw_scalestep,worldbottom);
 		bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
 
-#ifdef ESLOPE
 		if (frontsector->c_slope) {
 			fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldtopslope, ds_p->scale2);
 			topstep = (topfracend-topfrac)/(range);
@@ -2713,7 +2467,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldbottomslope, ds_p->scale2);
 			bottomstep = (bottomfracend-bottomfrac)/(range);
 		}
-#endif
 	}
 
 	dc_numlights = 0;
@@ -2729,14 +2482,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 		for (i = p = 0; i < dc_numlights; i++)
 		{
-#ifdef ESLOPE
 			fixed_t leftheight, rightheight;
-#endif
 
 			light = &frontsector->lightlist[i];
 			rlight = &dc_lightlist[p];
 
-#ifdef ESLOPE
 			if (light->slope) {
 				leftheight = P_GetZAt(light->slope, segleft.x, segleft.y);
 				rightheight = P_GetZAt(light->slope, segright.x, segright.y);
@@ -2751,38 +2501,23 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 			leftheight >>= 4;
 			rightheight >>= 4;
-#endif
 
 			if (i != 0)
 			{
-#ifdef ESLOPE
 				if (leftheight < worldbottom && rightheight < worldbottomslope)
 					continue;
 
 				if (leftheight > worldtop && rightheight > worldtopslope && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight)
 					continue;
-#else
-				if (light->height < frontsector->floorheight)
-					continue;
-
-				if (light->height > frontsector->ceilingheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight)
-					continue;
-#endif
 			}
 
-#ifdef ESLOPE
 			rlight->height = (centeryfrac>>4) - FixedMul(leftheight, rw_scale);
 			rlight->heightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2);
 			rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
-#else
-			rlight->height = (centeryfrac>>4) - FixedMul((light->height - viewz) >> 4, rw_scale);
-			rlight->heightstep = -FixedMul (rw_scalestep, (light->height - viewz) >> 4);
-#endif
 			rlight->flags = light->flags;
 
 			if (light->caster && light->caster->flags & FF_CUTSOLIDS)
 			{
-#ifdef ESLOPE
 				if (*light->caster->b_slope) {
 					leftheight = P_GetZAt(*light->caster->b_slope, segleft.x, segleft.y);
 					rightheight = P_GetZAt(*light->caster->b_slope, segright.x, segright.y);
@@ -2802,10 +2537,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 				rlight->botheightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2);
 				rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range);
 
-#else
-				rlight->botheight = (centeryfrac >> 4) - FixedMul((*light->caster->bottomheight - viewz) >> 4, rw_scale);
-				rlight->botheightstep = -FixedMul (rw_scalestep, (*light->caster->bottomheight - viewz) >> 4);
-#endif
 			}
 
 			rlight->lightlevel = *light->lightlevel;
@@ -2821,9 +2552,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		for (i = 0; i < numffloors; i++)
 		{
 			ffloor[i].f_pos >>= 4;
-#ifdef ESLOPE
 			ffloor[i].f_pos_slope >>= 4;
-#endif
 			if (linedef->special == HORIZONSPECIAL) // Horizon lines extend FOFs in contact with them too.
 			{
 				ffloor[i].f_step = 0;
@@ -2832,13 +2561,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			}
 			else
 			{
-#ifdef ESLOPE
 				ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale);
 				ffloor[i].f_step = ((centeryfrac>>4) - FixedMul(ffloor[i].f_pos_slope, ds_p->scale2) - ffloor[i].f_frac)/(range);
-#else
-				ffloor[i].f_step = FixedMul(-rw_scalestep, ffloor[i].f_pos);
-				ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale);
-#endif
 			}
 		}
 	}
@@ -2847,42 +2571,34 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	{
 		worldhigh >>= 4;
 		worldlow >>= 4;
-#ifdef ESLOPE
 		worldhighslope >>= 4;
 		worldlowslope >>= 4;
-#endif
 
 		if (toptexture)
 		{
 			pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
 			pixhighstep = -FixedMul (rw_scalestep,worldhigh);
 
-#ifdef ESLOPE
 			if (backsector->c_slope) {
 				fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldhighslope, ds_p->scale2);
 				pixhighstep = (topfracend-pixhigh)/(range);
 			}
-#endif
 		}
 
 		if (bottomtexture)
 		{
 			pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
 			pixlowstep = -FixedMul (rw_scalestep,worldlow);
-#ifdef ESLOPE
 			if (backsector->f_slope) {
 				fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldlowslope, ds_p->scale2);
 				pixlowstep = (bottomfracend-pixlow)/(range);
 			}
-#endif
 		}
 
 		{
 			ffloor_t * rover;
-#ifdef ESLOPE
 			fixed_t roverleft, roverright;
 			fixed_t planevistest;
-#endif
 			i = 0;
 
 			if (backsector->ffloors)
@@ -2894,7 +2610,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					if (rover->norender == leveltime)
 						continue;
 
-#ifdef ESLOPE
 					// Let the renderer know this sector is sloped.
 					if (*rover->b_slope || *rover->t_slope)
 						backsector->hasslope = true;
@@ -2941,34 +2656,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
 						i++;
 					}
-#else
-					if (*rover->bottomheight <= backsector->ceilingheight &&
-					    *rover->bottomheight >= backsector->floorheight &&
-					    ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) ||
-					     (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES))))
-					{
-						ffloor[i].b_pos = *rover->bottomheight;
-						ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
-						ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
-						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
-						i++;
-					}
-
-					if (i >= MAXFFLOORS)
-						break;
-
-					if (*rover->topheight >= backsector->floorheight &&
-					    *rover->topheight <= backsector->ceilingheight &&
-					    ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) ||
-					     (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES))))
-					{
-						ffloor[i].b_pos = *rover->topheight;
-						ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
-						ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
-						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
-						i++;
-					}
-#endif
 				}
 			}
 			else if (frontsector && frontsector->ffloors)
@@ -2980,8 +2667,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					if (rover->norender == leveltime)
 						continue;
 
-
-#ifdef ESLOPE
 					// Let the renderer know this sector is sloped.
 					if (*rover->b_slope || *rover->t_slope)
 						frontsector->hasslope = true;
@@ -3028,32 +2713,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
 						i++;
 					}
-#else
-					if (*rover->bottomheight <= frontsector->ceilingheight &&
-					    *rover->bottomheight >= frontsector->floorheight &&
-					    ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) ||
-					     (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES))))
-					{
-						ffloor[i].b_pos = *rover->bottomheight;
-						ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
-						ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
-						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
-						i++;
-					}
-					if (i >= MAXFFLOORS)
-						break;
-					if (*rover->topheight >= frontsector->floorheight &&
-					    *rover->topheight <= frontsector->ceilingheight &&
-					    ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) ||
-					     (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES))))
-					{
-						ffloor[i].b_pos = *rover->topheight;
-						ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
-						ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
-						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
-						i++;
-					}
-#endif
 				}
 			}
 #ifdef POLYOBJECTS_PLANES
@@ -3070,9 +2729,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					if (ffloor[i].plane->maxx < ds_p->x2)
 						ffloor[i].plane->maxx = ds_p->x2;
 
-#ifdef ESLOPE
 					ffloor[i].slope = NULL;
-#endif
 					ffloor[i].b_pos = backsector->floorheight;
 					ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
 					ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
@@ -3089,9 +2746,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					if (ffloor[i].plane->maxx < ds_p->x2)
 						ffloor[i].plane->maxx = ds_p->x2;
 
-#ifdef ESLOPE
 					ffloor[i].slope = NULL;
-#endif
 					ffloor[i].b_pos = backsector->ceilingheight;
 					ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
 					ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
diff --git a/src/r_things.c b/src/r_things.c
index 2fc44faf8..fc0469f4c 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1030,10 +1030,8 @@ static void R_SplitSprite(vissprite_t *sprite)
 		if (!(sector->lightlist[i].caster->flags & FF_CUTSPRITES))
 			continue;
 
-#ifdef ESLOPE
 		if (sector->lightlist[i].slope)
 			testheight = P_GetZAt(sector->lightlist[i].slope, sprite->gx, sprite->gy);
-#endif
 
 		if (testheight >= sprite->gzt)
 			continue;
@@ -1321,9 +1319,9 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
 	if (thing->subsector->sector->numlights)
 	{
 		INT32 lightnum;
-#ifdef ESLOPE // R_GetPlaneLight won't work on sloped lights!
 		light = thing->subsector->sector->numlights - 1;
 
+		// R_GetPlaneLight won't work on sloped lights!
 		for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
 			fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y)
 			            : thing->subsector->sector->lightlist[lightnum].height;
@@ -1332,9 +1330,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
 				break;
 			}
 		}
-#else
-		light = R_GetPlaneLight(thing->subsector->sector, shadow->gzt, false);
-#endif
+		//light = R_GetPlaneLight(thing->subsector->sector, shadow->gzt, false);
 	}
 
 	if (thing->subsector->sector->numlights)
@@ -1730,9 +1726,9 @@ static void R_ProjectSprite(mobj_t *thing)
 	if (thing->subsector->sector->numlights)
 	{
 		INT32 lightnum;
-#ifdef ESLOPE // R_GetPlaneLight won't work on sloped lights!
 		light = thing->subsector->sector->numlights - 1;
 
+		// R_GetPlaneLight won't work on sloped lights!
 		for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
 			fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y)
 			            : thing->subsector->sector->lightlist[lightnum].height;
@@ -1741,9 +1737,7 @@ static void R_ProjectSprite(mobj_t *thing)
 				break;
 			}
 		}
-#else
-		light = R_GetPlaneLight(thing->subsector->sector, gzt, false);
-#endif
+		//light = R_GetPlaneLight(thing->subsector->sector, gzt, false);
 		lightnum = (*thing->subsector->sector->lightlist[light].lightlevel >> LIGHTSEGSHIFT);
 
 		if (lightnum < 0)
@@ -2393,13 +2387,12 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
 				if (rover->szt > r2->plane->low || rover->sz < r2->plane->high)
 					continue;
 
-#ifdef ESLOPE
 				// Effective height may be different for each comparison in the case of slopes
 				if (r2->plane->slope) {
 					planeobjectz = P_GetZAt(r2->plane->slope, rover->gx, rover->gy);
 					planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy);
-				} else
-#endif
+				}
+				else
 					planeobjectz = planecameraz = r2->plane->height;
 
 				if (rover->mobjflags & MF_NOCLIPHEIGHT)
@@ -2458,20 +2451,18 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
 				if (scale <= rover->sortscale)
 					continue;
 
-#ifdef ESLOPE
 				if (*r2->ffloor->t_slope) {
 					topplaneobjectz = P_GetZAt(*r2->ffloor->t_slope, rover->gx, rover->gy);
 					topplanecameraz = P_GetZAt(*r2->ffloor->t_slope, viewx, viewy);
-				} else
-#endif
+				}
+				else
 					topplaneobjectz = topplanecameraz = *r2->ffloor->topheight;
 
-#ifdef ESLOPE
 				if (*r2->ffloor->b_slope) {
 					botplaneobjectz = P_GetZAt(*r2->ffloor->b_slope, rover->gx, rover->gy);
 					botplanecameraz = P_GetZAt(*r2->ffloor->b_slope, viewx, viewy);
-				} else
-#endif
+				}
+				else
 					botplaneobjectz = botplanecameraz = *r2->ffloor->bottomheight;
 
 				if ((topplanecameraz > viewz && botplanecameraz < viewz) ||
diff --git a/src/screen.c b/src/screen.c
index 7ebe34635..6bdf91ed8 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -127,14 +127,12 @@ void SCR_SetDrawFuncs(void)
 #ifndef NOWATER
 		spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8;
 #endif
-#ifdef ESLOPE
 		spanfuncs[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_8;
 		spanfuncs[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_8;
 #ifndef NOWATER
 		spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_8;
 #endif
 		spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8;
-#endif
 
 		// Lactozilla: Non-powers-of-two
 		spanfuncs_npo2[BASEDRAWFUNC] = R_DrawSpan_NPO2_8;
@@ -145,14 +143,12 @@ void SCR_SetDrawFuncs(void)
 #ifndef NOWATER
 		spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8;
 #endif
-#ifdef ESLOPE
 		spanfuncs_npo2[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_NPO2_8;
 		spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_NPO2_8;
 #ifndef NOWATER
 		spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8;
 #endif
 		spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8;
-#endif
 
 #ifdef RUSEASM
 		if (R_ASM)
diff --git a/src/screen.h b/src/screen.h
index 717ce9adc..ddbd499bb 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -140,13 +140,11 @@ enum
 #ifndef NOWATER
 	SPANDRAWFUNC_WATER,
 #endif
-#ifdef ESLOPE
 	SPANDRAWFUNC_TILTED,
 	SPANDRAWFUNC_TILTEDTRANS,
 	SPANDRAWFUNC_TILTEDSPLAT,
 #ifndef NOWATER
 	SPANDRAWFUNC_TILTEDWATER,
-#endif
 #endif
 
 	SPANDRAWFUNC_MAX

From feb18208cbb6fbe0c380d96713af2278aa4119cb Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Sat, 21 Mar 2020 01:36:39 -0500
Subject: [PATCH 135/251] Add support for srb2:// URL handler (server links)

---
 src/d_main.c | 27 +++++++++++++++++++++++++--
 src/i_tcp.c  |  9 ++++++---
 src/m_argv.c | 18 ++++++++++++++++++
 src/m_argv.h |  3 +++
 4 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/src/d_main.c b/src/d_main.c
index 3840e77a0..d954fa4d1 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -889,6 +889,29 @@ static void IdentifyVersion(void)
 	char *srb2wad;
 	const char *srb2waddir = NULL;
 
+	// URL handlers are opened by web browsers (at least Firefox) from the browser's working directory, not the game's stored directory,
+	// so chdir to that directory unless overridden.
+	if (M_GetUrlProtocolArg() != NULL && !M_CheckParm("-nochdir"))
+	{
+		size_t i;
+
+		CONS_Printf("srb2:// connect links load game files from the SRB2 application's stored directory. Switching to ");
+		strlcpy(srb2path, myargv[0], sizeof(srb2path));
+
+		// Get just the directory, minus the EXE name
+		for (i = strlen(srb2path)-1; i > 0; i--)
+		{
+			if (srb2path[i] == '/' || srb2path[i] == '\\')
+			{
+				srb2path[i] = '\0';
+				break;
+			}
+		}
+
+		CONS_Printf("%s\n", srb2path);
+		chdir(srb2path);
+	}
+
 #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
 	// change to the directory where 'srb2.pk3' is found
 	srb2waddir = I_LocateWad();
@@ -1152,7 +1175,7 @@ void D_SRB2Main(void)
 
 	// add any files specified on the command line with -file wadfile
 	// to the wad list
-	if (!(M_CheckParm("-connect") && !M_CheckParm("-server")))
+	if (!((M_GetUrlProtocolArg() || M_CheckParm("-connect")) && !M_CheckParm("-server")))
 	{
 		if (M_CheckParm("-file"))
 		{
@@ -1187,7 +1210,7 @@ void D_SRB2Main(void)
 	M_InitMenuPresTables();
 
 	// init title screen display params
-	if (M_CheckParm("-connect"))
+	if (M_GetUrlProtocolArg() || M_CheckParm("-connect"))
 		F_InitMenuPresValues();
 
 	//---------------------------------------------------- READY TIME
diff --git a/src/i_tcp.c b/src/i_tcp.c
index 34cad1765..373ea1bd0 100644
--- a/src/i_tcp.c
+++ b/src/i_tcp.c
@@ -1423,6 +1423,7 @@ static void SOCK_ClearBans(void)
 boolean I_InitTcpNetwork(void)
 {
 	char serverhostname[255];
+	const char *urlparam = NULL;
 	boolean ret = false;
 	// initilize the OS's TCP/IP stack
 	if (!I_InitTcpDriver())
@@ -1476,10 +1477,12 @@ boolean I_InitTcpNetwork(void)
 
 		ret = true;
 	}
-	else if (M_CheckParm("-connect"))
+	else if ((urlparam = M_GetUrlProtocolArg()) != NULL || M_CheckParm("-connect"))
 	{
-		if (M_IsNextParm())
-			strcpy(serverhostname, M_GetNextParm());
+		if (urlparam != NULL)
+			strlcpy(serverhostname, urlparam, sizeof(serverhostname));
+		else if (M_IsNextParm())
+			strlcpy(serverhostname, M_GetNextParm(), sizeof(serverhostname));
 		else
 			serverhostname[0] = 0; // assuming server in the LAN, use broadcast to detect it
 
diff --git a/src/m_argv.c b/src/m_argv.c
index acb74cff4..d7d1f4463 100644
--- a/src/m_argv.c
+++ b/src/m_argv.c
@@ -34,6 +34,24 @@ boolean myargmalloc = false;
 */
 static INT32 found;
 
+/**	\brief Parses a server URL (such as srb2://127.0.0.1) as may be passed to the game via a web browser, etc.
+
+	\return the contents of the URL after the protocol (a server to join), or NULL if not found
+*/
+const char *M_GetUrlProtocolArg(void)
+{
+	INT32 i;
+
+	for (i = 1; i < myargc; i++)
+	{
+		if (!strnicmp(myargv[i], "srb2://", 7))
+		{
+			return &myargv[i][7];
+		}
+	}
+
+	return NULL;
+}
 
 /**	\brief	The M_CheckParm function
 
diff --git a/src/m_argv.h b/src/m_argv.h
index ca97d9b12..92770f4e9 100644
--- a/src/m_argv.h
+++ b/src/m_argv.h
@@ -21,6 +21,9 @@ extern INT32 myargc;
 extern char **myargv;
 extern boolean myargmalloc;
 
+// Looks for an srb2:// (or similar) URL passed in as an argument and returns the IP to connect to if found.
+const char *M_GetUrlProtocolArg(void);
+
 // Returns the position of the given parameter in the arg list (0 if not found).
 INT32 M_CheckParm(const char *check);
 

From 2107b89586392e26758ad8da2aa900eb1f51a875 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 21 Mar 2020 09:40:37 +0100
Subject: [PATCH 136/251] Remove the multi-file ZB configs. We're stick with
 the single-file config for ZB and doing all the UDMF stuff in UDB

---
 extras/conf/Includes/Game_SRB222.cfg     |   77 -
 extras/conf/Includes/SRB222_common.cfg   |  309 --
 extras/conf/Includes/SRB222_linedefs.cfg | 2486 ----------------
 extras/conf/Includes/SRB222_misc.cfg     |  726 -----
 extras/conf/Includes/SRB222_sectors.cfg  |  109 -
 extras/conf/Includes/SRB222_things.cfg   | 3398 ----------------------
 extras/conf/SRB2_22Doom.cfg              |   38 -
 extras/conf/SRB2_22UDMF.cfg              |   47 -
 8 files changed, 7190 deletions(-)
 delete mode 100644 extras/conf/Includes/Game_SRB222.cfg
 delete mode 100644 extras/conf/Includes/SRB222_common.cfg
 delete mode 100644 extras/conf/Includes/SRB222_linedefs.cfg
 delete mode 100644 extras/conf/Includes/SRB222_misc.cfg
 delete mode 100644 extras/conf/Includes/SRB222_sectors.cfg
 delete mode 100644 extras/conf/Includes/SRB222_things.cfg
 delete mode 100644 extras/conf/SRB2_22Doom.cfg
 delete mode 100644 extras/conf/SRB2_22UDMF.cfg

diff --git a/extras/conf/Includes/Game_SRB222.cfg b/extras/conf/Includes/Game_SRB222.cfg
deleted file mode 100644
index 3c4b11e9f..000000000
--- a/extras/conf/Includes/Game_SRB222.cfg
+++ /dev/null
@@ -1,77 +0,0 @@
-// Default lump name for new map
-defaultlumpname = "MAP01";
-//GZDB specific. Don't try to load lumps that don't exist.
-basegame = 0;
-
-//Sky textures for vanilla maps
-defaultskytextures
-{
-	SKY1 = "MAP01,MAP02,MAP03,MAP33,MAP50,MAP60,MAPF0,MAPM0";
-	SKY2 = "MAPM7,MAPMB";
-	SKY4 = "MAP04,MAP06,MAP61,MAPF6,MAPM1";
-	SKY6 = "MAP05,MAP51,MAPMA";
-	SKY7 = "MAPM2,MAPM5";
-	SKY8 = "MAP07,MAP08,MAP09,MAP52,MAP62,MAPF1";
-	SKY10 = "MAP10,MAP12,MAP53,MAP63,MAPM3";
-	SKY11 = "MAP11,MAPF7";
-	SKY13 = "MAP13,MAP64";
-	SKY14 = "MAP14";
-	SKY15 = "MAP15,MAP54";
-	SKY17 = "MAP70";
-	SKY20 = "MAP32,MAP55,MAP65,MAPF2,MAPF5";
-	SKY21 = "MAPM4";
-	SKY22 = "MAP22,MAP23,MAP25,MAP26,MAP27,MAP56,MAP66,MAPF4,MAPM6";
-	SKY30 = "MAP30";
-	SKY31 = "MAP31";
-	SKY35 = "MAP42";
-	SKY40 = "MAP41,MAP71,MAPM9";
-	SKY55 = "MAPF3,MAPM8";
-	SKY68 = "MAPF8";
-	SKY99 = "MAP57,MAPZ0";
-	SKY159 = "MAP16";
-	SKY172 = "MAP40";
-	SKY300 = "MAP72";
-	SKY301 = "MAP73";
-}
-
-// Skill levels
-skills
-{
-	1 = "Normal";
-}
-
-// Skins
-skins
-{
-	Sonic;
-	Tails;
-	Knuckles;
-	Amy;
-	Fang;
-	Metalsonic;
-}
-
-// Gametypes
-gametypes
-{
-	-1 = "Single Player";
-	0 = "Co-op";
-	1 = "Competition";
-	2 = "Race";
-	3 = "Match";
-	4 = "Team Match";
-	5 = "Tag";
-	6 = "Hide and Seek";
-	7 = "CTF";
-}
-
-// Texture loading options
-defaultwalltexture = "GFZROCK";
-defaultfloortexture = "GFZFLR01";
-defaultceilingtexture = "F_SKY1";
-
-// Default texture sets
-// (these are not required, but useful for new users)
-texturesets
-{
-}
\ No newline at end of file
diff --git a/extras/conf/Includes/SRB222_common.cfg b/extras/conf/Includes/SRB222_common.cfg
deleted file mode 100644
index a832e6cef..000000000
--- a/extras/conf/Includes/SRB222_common.cfg
+++ /dev/null
@@ -1,309 +0,0 @@
-common
-{
-	// Some common settings
-
-
-
-	// Default testing parameters
-	testparameters = "-file \"%AP\" \"%F\" -warp %L";
-	testshortpaths = true;
-
-	// Action special help (mxd)
-	actionspecialhelp = "https://wiki.srb2.org/wiki/Linedef_type_%K";
-
-	// Default nodebuilder configurations
-	defaultsavecompiler = "zennode_normal";
-	defaulttestcompiler = "zennode_fast";
-
-	// Generalized actions
-	generalizedlinedefs = false;
-	generalizedsectors = true;
-
-	mixtexturesflats = true;
-	defaulttexturescale = 1.0f;
-	defaultflatscale = 1.0f;
-	scaledtextureoffsets = true;
-
-	// Thing number for start position in 3D Mode
-	start3dmode = 3328;
-
-	// Texture sources
-	textures
-	{
-		include("SRB222_misc.cfg", "textures");
-	}
-
-	// Patch sources
-	patches
-	{
-		include("SRB222_misc.cfg", "patches");
-	}
-
-	// Sprite sources
-	sprites
-	{
-		include("SRB222_misc.cfg", "sprites");
-	}
-
-	// Flat sources
-	flats
-	{
-		include("SRB222_misc.cfg", "flats");
-	}
-}
-
-mapformat_doom
-{
-	// The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder
-	formatinterface = "SRB2MapSetIO";
-
-	/*
-	GAME DETECT PATTERN
-	Used to guess the game for which a WAD file is made.
-
-	1 = One of these lumps must exist
-	2 = None of these lumps must exist
-	3 = All of these lumps must exist
-	*/
-
-	gamedetect
-	{
-		EXTENDED = 2;
-
-
-		BEHAVIOR = 2;
-
-		E#M# = 2;
-
-		MAP?? = 1;
-	}
-
-	/*
-	MAP LUMP NAMES
-	Map lumps are loaded with the map as long as they are right after each other. When the editor
-	meets a lump which is not defined in this list it will ignore the map if not satisfied.
-	The order of items defines the order in which lumps will be written to WAD file on save.
-	To indicate the map header lump, use ~MAP
-
-	Legenda:
-	required = Lump is required to exist.
-	blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use)
-	nodebuild = The nodebuilder generates this lump.
-	allowempty = The nodebuilder is allowed to leave this lump empty.
-	script = This lump is a text-based script. Specify the filename of the script configuration to use.
-	*/
-
-	maplumpnames
-	{
-		include("SRB222_misc.cfg", "doommaplumpnames");
-	}
-
-	// When this is set to true, sectors with the same tag will light up when a line is highlighted
-	linetagindicatesectors = true;
-
-	// Special linedefs
-	include("SRB222_misc.cfg", "speciallinedefs");
-
-	// Default flags for first new thing (As far as 2.2 goes, they're empty just like in 2.1)
-	defaultthingflags
-	{
-	}
-
-	// DEFAULT SECTOR BRIGHTNESS LEVELS
-	sectorbrightness
-	{
-		include("SRB222_misc.cfg", "sectorbrightness");
-	}
-
-	// SECTOR TYPES-----------------------------------------------------------------
-	sectortypes
-	{
-		include("SRB222_sectors.cfg", "sectortypes");
-	}
-
-	// GENERALISED SECTOR TYPES-----------------------------------------------------------------
-	gen_sectortypes
-	{
-		include("SRB222_sectors.cfg", "gen_sectortypes");
-	}
-
-	// LINEDEF FLAGS
-	linedefflags
-	{
-		include("SRB222_misc.cfg", "linedefflags");
-	}
-
-	// Linedef flags UDMF translation table
-	// This is needed for copy/paste and prefabs to work properly
-	// When the UDMF field name is prefixed with ! it is inverted
-	linedefflagstranslation
-	{
-		include("SRB222_misc.cfg", "linedefflagstranslation");
-	}
-
-	// LINEDEF ACTIVATIONS
-	linedefactivations
-	{
-	}
-
-	// LINEDEF TYPES
-	linedeftypes
-	{
-		include("SRB222_linedefs.cfg", "doom");
-	}
-
-	// THING FLAGS
-	thingflags
-	{
-		include("SRB222_misc.cfg", "thingflags");
-	}
-
-	// Thing flags UDMF translation table
-	// This is needed for copy/paste and prefabs to work properly
-	// When the UDMF field name is prefixed with ! it is inverted
-	thingflagstranslation
-	{
-		include("SRB222_misc.cfg", "thingflagstranslation");
-	}
-
-	// THING FLAGS ERROR MASK
-	// Mask for the thing flags which indicates the options
-	// that make the same thing appear in the same modes
-	thingflagsmask1 = 7;	// 1 + 2 + 4
-	thingflagsmask2 = 0;
-}
-
-mapformat_udmf
-{
-	// The format interface handles the map data format
-	formatinterface = "UniversalMapSetIO";
-
-	// Enables support for long (> 8 chars) texture names
-	// WARNING: this should only be enabled for UDMF game configurations!
-	// WARNING: enabling this will make maps incompatible with Doom Builder 2 and can lead to problems in Slade 3!
-	longtexturenames = false;
-
-	// Default nodebuilder configurations
-	defaultsavecompiler = "zdbsp_udmf_normal";
-	defaulttestcompiler = "zdbsp_udmf_fast";
-
-	engine = "srb2"; // override that so that DB2 uses the correct namespace
-
-	maplumpnames
-	{
-		include("UDMF_misc.cfg", "udmfmaplumpnames_begin");
-		include("SRB222_misc.cfg", "udmfmaplumpnames");
-		include("UDMF_misc.cfg", "udmfmaplumpnames_end");
-	}
-
-	universalfields
-	{
-//		include("SRB222_misc.cfg", "universalfields");
-	}
-
-	// When this is set to true, sectors with the same tag will light up when a line is highlighted
-	linetagindicatesectors = false;
-
-	// Special linedefs
-	include("SRB222_misc.cfg", "speciallinedefs_udmf");
-
-	// Default flags for first new thing (As far as 2.2 goes, they're empty just like in 2.1)
-	defaultthingflags
-	{
-	}
-
-	// Generalized actions
-	generalizedlinedefs = false;
-
-	// SECTOR FLAGS
-	sectorflags
-	{
-//		include("SRB222_misc.cfg", "sectorflags");
-	}
-
-	// DEFAULT SECTOR BRIGHTNESS LEVELS
-	sectorbrightness
-	{
-		include("SRB222_misc.cfg", "sectorbrightness");
-	}
-
-	// SECTOR TYPES
-	sectortypes
-	{
-		include("SRB222_sectors.cfg", "sectortypes");
-	}
-
-	// SECTOR RENSERSTYLES
-/*	sectorrenderstyles
-	{
-		include("SRB222_misc.cfg", "sectorrenderstyles");
-	}*/
-
-	// LINEDEF FLAGS
-	linedefflags
-	{
-		include("SRB222_misc.cfg", "linedefflags_udmf");
-	}
-
-	// LINEDEF ACTIVATIONS
-	linedefactivations
-	{
-		include("SRB222_misc.cfg", "linedefactivations_udmf");
-	}
-
-	linedefflagstranslation
-	{
-	}
-
-
-	// LINEDEF RENSERSTYLES
-	linedefrenderstyles
-	{
-		include("SRB222_misc.cfg", "linedefrenderstyles");
-	}
-
-	//SIDEDEF FLAGS
-/*	sidedefflags
-	{
-		include("UDMF_misc.cfg", "sidedefflags");
-	}*/
-
-	// THING FLAGS
-	thingflags
-	{
-		include("SRB222_misc.cfg", "thingflags_udmf");
-	}
-
-	// Thing flags UDMF translation table
-	// This is needed for copy/paste and prefabs to work properly
-	// When the UDMF field name is prefixed with ! it is inverted
-	thingflagstranslation
-	{
-		include("SRB222_misc.cfg", "thingflagstranslation");
-	}
-
-	// THING RENSERSTYLES
-/*	thingrenderstyles
-	{
-		include("SRB222_misc.cfg", "thingrenderstyles");
-	}*/
-
-	// How to compare thing flags (for the stuck things error checker)
-/*	thingflagscompare
-	{
-		include("UDMF_misc.cfg", "thingflagscompare");
-	}*/
-
-	//mxd. Thing flags UDMF translation table
-	// This is needed for copy/paste and prefabs to work properly
-	// When the UDMF field name is prefixed with ! it is inverted
-	thingflagstranslation
-	{
-	}
-
-	// LINEDEF TYPES
-	linedeftypes
-	{
-		include("SRB222_linedefs.cfg", "udmf");
-	}
-}
\ No newline at end of file
diff --git a/extras/conf/Includes/SRB222_linedefs.cfg b/extras/conf/Includes/SRB222_linedefs.cfg
deleted file mode 100644
index fdf191850..000000000
--- a/extras/conf/Includes/SRB222_linedefs.cfg
+++ /dev/null
@@ -1,2486 +0,0 @@
-doom
-{
-	misc
-	{
-		title = "Miscellaneous";
-
-		0
-		{
-			title = "None";
-			prefix = "(0)";
-		}
-
-		1
-		{
-			title = "Per-Sector Gravity";
-			prefix = "(1)";
-			flags64text = "[6] Flip in reverse gravity";
-		}
-
-		5
-		{
-			title = "Camera Scanner";
-			prefix = "(5)";
-		}
-
-		7
-		{
-			title = "Sector Flat Alignment";
-			prefix = "(7)";
-			flags2048text = "[11] Don't align floor";
-			flags4096text = "[12] Don't align ceiling";
-			flags8192text = "[13] Use texture offsets";
-		}
-
-		10
-		{
-			title = "Culling Plane";
-			prefix = "(10)";
-			flags64text = "[6] Cull only while in sector";
-		}
-
-		13
-		{
-			title = "Heat Wave Effect";
-			prefix = "(13)";
-		}
-
-	    40
-		{
-			title = "Visual Portal Between Tagged Linedefs";
-			prefix = "(40)";
-		}
-
-	    41
-		{
-			title = "Horizon Effect";
-			prefix = "(41)";
-		}
-
-		50
-		{
-			title = "Instantly Lower Floor on Level Load";
-			prefix = "(50)";
-		}
-
-		51
-		{
-			title = "Instantly Raise Ceiling on Level Load";
-			prefix = "(51)";
-		}
-
-		63
-		{
-			title = "Fake Floor/Ceiling Planes";
-			prefix = "(63)";
-		}
-
-		540
-		{
-			title = "Floor Friction";
-			prefix = "(540)";
-		}
-	}
-
-	parameters
-	{
-		title = "Parameters";
-
-		2
-		{
-			title = "Custom Exit";
-			prefix = "(2)";
-			flags2text = "[1] Check emeralds";
-			flags64text = "[6] Skip score tally";
-		}
-
-		3
-		{
-			title = "Zoom Tube Parameters";
-			prefix = "(3)";
-			flags512text = "[9] Ignore player direction";
-		}
-
-		4
-		{
-			title = "Speed Pad Parameters";
-			prefix = "(4)";
-			flags512text = "[9] No teleport to center";
-			flags1024text = "[10] Force spinning frames";
-		}
-
-		8
-		{
-			title = "Special Sector Properties";
-			prefix = "(8)";
-			flags32text = "[5] Invert precipitation";
-			flags64text = "[6] Touch only ceiling";
-			flags128text = "[7] Allow opposite gravity";
-			flags256text = "[8] Touch sector edge";
-			flags512text = "[9] Touch floor or ceiling";
-		}
-
-		9
-		{
-			title = "Chain Parameters";
-			prefix = "(9)";
-			flags32text = "[5] Swing instead of spin";
-			flags64text = "[6] Player-turnable chain";
-			flags128text = "[7] Make chain from end item";
-			flags256text = "[8] Spawn link at origin";
-			flags512text = "[9] Don't clip inside ground";
-			flags1024text = "[10] No distance check";
-		}
-
-		11
-		{
-			title = "Rope Hang Parameters";
-			prefix = "(11)";
-			flags32text = "[5] Don't loop";
-			flags64text = "[6] Static";
-		}
-
-		12
-		{
-			title = "Rock Spawner Parameters";
-			prefix = "(12)";
-			flags64text = "[6] Randomize speed";
-		}
-
-		14
-		{
-			title = "Bustable Block Parameters";
-			prefix = "(14)";
-			flags32text = "[5] Particles launch from center";
-		}
-
-		15
-		{
-			title = "Fan Particle Spawner Parameters";
-			prefix = "(15)";
-		}
-
-		16
-		{
-			title = "Minecart Parameters";
-			prefix = "(16)";
-		}
-
-		64
-		{
-			title = "Continuously Appearing/Disappearing FOF";
-			prefix = "(64)";
-			flags2text = "[1] Use control sector tag";
-			flags64text = "[6] No sound effect";
-		}
-
-		65
-		{
-			title = "Bridge Thinker <disabled>";
-			prefix = "(65)";
-		}
-	}
-
-	polyobject
-	{
-		title = "PolyObject";
-
-		20
-		{
-			title = "First Line";
-			prefix = "(20)";
-		}
-
-		21
-		{
-			title = "Explicitly Include Line <disabled>";
-			prefix = "(21)";
-		}
-
-		22
-		{
-			title = "Parameters";
-			prefix = "(22)";
-			flags64text = "[6] Trigger linedef executor";
-			flags128text = "[7] Intangible";
-			flags256text = "[8] Stopped by pushables";
-			flags512text = "[9] Render flats";
-		}
-
-		30
-		{
-			title = "Waving Flag";
-			prefix = "(30)";
-		}
-
-		31
-		{
-			title = "Displacement by Front Sector";
-			prefix = "(31)";
-		}
-
-		32
-		{
-			title = "Angular Displacement by Front Sector";
-			prefix = "(32)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Don't turn players";
-			flags512text = "[9] Turn all objects";
-		}
-	}
-
-	planemove
-	{
-		title = "Plane Movement";
-
-		52
-		{
-			title = "Continuously Falling Sector";
-			prefix = "(52)";
-			flags64text = "[6] Continuously rising";
-		}
-
-		53
-		{
-			title = "Continuous Floor/Ceiling Mover";
-			prefix = "(53)";
-		}
-
-		54
-		{
-			title = "Continuous Floor Mover";
-			prefix = "(54)";
-		}
-
-		55
-		{
-			title = "Continuous Ceiling Mover";
-			prefix = "(55)";
-		}
-
-		56
-		{
-			title = "Continuous Two-Speed Floor/Ceiling Mover";
-			prefix = "(56)";
-		}
-
-		57
-		{
-			title = "Continuous Two-Speed Floor Mover";
-			prefix = "(57)";
-		}
-
-		58
-		{
-			title = "Continuous Two-Speed Ceiling Mover";
-			prefix = "(58)";
-		}
-
-		59
-		{
-			title = "Activate Moving Platform";
-			prefix = "(59)";
-			flags64text = "[6] Move upwards at start";
-		}
-
-		60
-		{
-			title = "Activate Moving Platform (Adjustable Speed)";
-			prefix = "(60)";
-			flags64text = "[6] Move upwards at start";
-		}
-
-		61
-		{
-			title = "Crusher (Ceiling to Floor)";
-			prefix = "(61)";
-			flags512text = "[9] Double, constant speed";
-		}
-
-		62
-		{
-			title = "Crusher (Floor to Ceiling)";
-			prefix = "(62)";
-			flags512text = "[9] Double, constant speed";
-		}
-
-		66
-		{
-			title = "Move Floor by Displacement";
-			prefix = "(66)";
-			flags64text = "[6] Inverse movement";
-		}
-
-		67
-		{
-			title = "Move Ceiling by Displacement";
-			prefix = "(67)";
-			flags64text = "[6] Inverse movement";
-		}
-
-		68
-		{
-			title = "Move Floor and Ceiling by Displacement";
-			prefix = "(68)";
-			flags64text = "[6] Inverse movement";
-		}
-	}
-
-	fofsolid
-	{
-		title = "FOF (solid)";
-
-		100
-		{
-			title = "Solid, Opaque";
-			prefix = "(100)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "19F";
-		}
-
-		101
-		{
-			title = "Solid, Opaque, No Shadow";
-			prefix = "(101)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "1DF";
-		}
-
-		102
-		{
-			title = "Solid, Translucent";
-			prefix = "(102)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Render insides";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "195F";
-			flags643dfloorflagsadd = "7C80";
-		}
-
-		103
-		{
-			title = "Solid, Sides Only";
-			prefix = "(103)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "1CF";
-		}
-
-		104
-		{
-			title = "Solid, No Sides";
-			prefix = "(104)";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Cast shadow";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "1D7";
-			flags643dfloorflagsremove = "40";
-		}
-
-		105
-		{
-			title = "Solid, Invisible";
-			prefix = "(105)";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "47";
-		}
-
-		140
-		{
-			title = "Intangible from Bottom, Opaque";
-			prefix = "(140)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Don't cast shadow";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "200841F";
-			flags643dfloorflagsadd = "40";
-		}
-
-		141
-		{
-			title = "Intangible from Bottom, Translucent";
-			prefix = "(141)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Don't cast shadow";
-			flags128text = "[7] Render insides/block non-plr";
-			3dfloor = true;
-			3dfloorflags = "200191F";
-			flags1283dfloorflagsadd = "7C80";
-			flags643dfloorflagsadd = "40";
-		}
-
-		142
-		{
-			title = "Intangible from Bottom, Translucent, No Sides";
-			prefix = "(142)";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Don't cast shadow";
-			flags128text = "[7] Render insides/block non-plr";
-			3dfloor = true;
-			3dfloorflags = "2001917";
-			flags1283dfloorflagsadd = "7C80";
-			flags643dfloorflagsadd = "40";
-		}
-
-		143
-		{
-			title = "Intangible from Top, Opaque";
-			prefix = "(143)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Don't cast shadow";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "400841F";
-			flags643dfloorflagsadd = "40";
-		}
-
-		144
-		{
-			title = "Intangible from Top, Translucent";
-			prefix = "(144)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Don't cast shadow";
-			flags128text = "[7] Render insides/block non-plr";
-			3dfloor = true;
-			3dfloorflags = "400191F";
-			flags1283dfloorflagsadd = "7C80";
-			flags643dfloorflagsadd = "40";
-		}
-
-		145
-		{
-			title = "Intangible from Top, Translucent, No Sides";
-			prefix = "(145)";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Don't cast shadow";
-			flags128text = "[7] Render insides/block non-plr";
-			3dfloor = true;
-			3dfloorflags = "4001917";
-			flags1283dfloorflagsadd = "7C80";
-			flags643dfloorflagsadd = "40";
-		}
-
-		146
-		{
-			title = "Only Tangible from Sides";
-			prefix = "(146)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "600800F";
-		}
-	}
-
-	fofintangible
-	{
-		title = "FOF (intangible)";
-
-		120
-		{
-			title = "Water, Opaque";
-			prefix = "(120)";
-			flags8text = "[3] Slope skew sides";
-			flags64text = "[6] Use two light levels";
-			flags512text = "[9] Use target light level";
-			flags1024text = "[10] Ripple effect";
-			3dfloor = true;
-			3dfloorflags = "8F39";
-			flags643dfloorflagsadd = "20000";
-			flags5123dfloorflagsadd = "80000000";
-			flags10243dfloorflagsadd = "40000000";
-		}
-
-		121
-		{
-			title = "Water, Translucent";
-			prefix = "(121)";
-			flags8text = "[3] Slope skew sides";
-			flags64text = "[6] Use two light levels";
-			flags512text = "[9] Use target light level";
-			flags1024text = "[10] Ripple effect";
-			3dfloor = true;
-			3dfloorflags = "9F39";
-			flags643dfloorflagsadd = "20000";
-			flags5123dfloorflagsadd = "80000000";
-			flags10243dfloorflagsadd = "40000000";
-		}
-
-		122
-		{
-			title = "Water, Opaque, No Sides";
-			prefix = "(122)";
-			flags64text = "[6] Use two light levels";
-			flags512text = "[9] Use target light level";
-			flags1024text = "[10] Ripple effect";
-			3dfloor = true;
-			3dfloorflags = "F31";
-			flags643dfloorflagsadd = "20000";
-			flags5123dfloorflagsadd = "80000000";
-			flags10243dfloorflagsadd = "40000000";
-		}
-
-		123
-		{
-			title = "Water, Translucent, No Sides";
-			prefix = "(123)";
-			flags64text = "[6] Use two light levels";
-			flags512text = "[9] Use target light level";
-			flags1024text = "[10] Ripple effect";
-			3dfloor = true;
-			3dfloorflags = "1F31";
-			flags643dfloorflagsadd = "20000";
-			flags5123dfloorflagsadd = "80000000";
-			flags10243dfloorflagsadd = "40000000";
-		}
-
-		124
-		{
-			title = "Goo Water, Translucent";
-			prefix = "(124)";
-			flags8text = "[3] Slope skew sides";
-			flags64text = "[6] Use two light levels";
-			flags512text = "[9] Use target light level";
-			flags1024text = "[10] Ripple effect";
-			3dfloor = true;
-			3dfloorflags = "209F39";
-			flags643dfloorflagsadd = "20000";
-			flags5123dfloorflagsadd = "80000000";
-			flags10243dfloorflagsadd = "40000000";
-		}
-
-		125
-		{
-			title = "Goo Water, Translucent, No Sides";
-			prefix = "(125)";
-			flags8text = "[3] Slope skew sides";
-			flags64text = "[6] Use two light levels";
-			flags512text = "[9] Use target light level";
-			flags1024text = "[10] Ripple effect";
-			3dfloor = true;
-			3dfloorflags = "201F31";
-			flags643dfloorflagsadd = "20000";
-			flags5123dfloorflagsadd = "80000000";
-			flags10243dfloorflagsadd = "40000000";
-		}
-
-		220
-		{
-			title = "Intangible, Opaque";
-			prefix = "(220)";
-			flags8text = "[3] Slope skew sides";
-			3dfloor = true;
-			3dfloorflags = "8F19";
-		}
-
-		221
-		{
-			title = "Intangible, Translucent";
-			prefix = "(221)";
-			flags8text = "[3] Slope skew sides";
-			flags64text = "[6] Cast shadow";
-			3dfloor = true;
-			3dfloorflags = "1B59";
-			flags643dfloorflagsremove = "40";
-		}
-
-		222
-		{
-			title = "Intangible, Sides Only";
-			prefix = "(222)";
-			flags8text = "[3] Slope skew sides";
-			flags64text = "[6] Cast shadow";
-			3dfloor = true;
-			3dfloorflags = "8249";
-			flags643dfloorflagsremove = "240";
-		}
-
-		223
-		{
-			title = "Intangible, Invisible";
-			prefix = "(223)";
-			3dfloor = true;
-			3dfloorflags = "41";
-		}
-	}
-
-	fofmoving
-	{
-		title = "FOF (moving)";
-
-		150
-		{
-			title = "Air Bobbing";
-			prefix = "(150)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash to move";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "19F";
-		}
-
-		151
-		{
-			title = "Air Bobbing (Adjustable)";
-			prefix = "(151)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash to move";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "19F";
-		}
-
-		152
-		{
-			title = "Reverse Air Bobbing (Adjustable)";
-			prefix = "(152)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash to move";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "19F";
-		}
-
-		160
-		{
-			title = "Floating, Bobbing";
-			prefix = "(160)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "4019F";
-		}
-
-		190
-		{
-			title = "Rising Platform, Solid, Opaque";
-			prefix = "(190)";
-			flags2text = "[1] Sink when stepped on";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash to move";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "19F";
-		}
-
-		191
-		{
-			title = "Rising Platform, Solid, Opaque, No Shadow";
-			prefix = "(191)";
-			flags2text = "[1] Sink when stepped on";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash to move";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "1DF";
-		}
-
-		192
-		{
-			title = "Rising Platform, Solid, Translucent";
-			prefix = "(192)";
-			flags2text = "[1] Sink when stepped on";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash to move";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "195F";
-		}
-
-		193
-		{
-			title = "Rising Platform, Solid, Invisible";
-			prefix = "(193)";
-			flags2text = "[1] Sink when stepped on";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash to move";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "47";
-		}
-
-		194
-		{
-			title = "Rising Platform, Intangible from Bottom, Opaque";
-			prefix = "(194)";
-			flags2text = "[1] Sink when stepped on";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash, no shadow";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "200841F";
-			flags643dfloorflagsadd = "40";
-		}
-
-		195
-		{
-			title = "Rising Platform, Intangible from Bottom, Translucent";
-			prefix = "(195)";
-			flags2text = "[1] Sink when stepped on";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash, no shadow";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "2009D1F";
-			flags643dfloorflagsadd = "40";
-		}
-	}
-
-	fofcrumbling
-	{
-		title = "FOF (crumbling)";
-
-		170
-		{
-			title = "Crumbling, Respawn";
-			prefix = "(170)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "10019F";
-		}
-
-		171
-		{
-			title = "Crumbling, No Respawn";
-			prefix = "(171)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "80019F";
-		}
-
-		172
-		{
-			title = "Crumbling, Respawn, Intangible from Bottom";
-			prefix = "(172)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Don't cast shadow";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "210841F";
-			flags643dfloorflagsadd = "40";
-		}
-
-		173
-		{
-			title = "Crumbling, No Respawn, Intangible from Bottom";
-			prefix = "(173)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Don't cast shadow";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "218841F";
-			flags643dfloorflagsadd = "40";
-		}
-
-		174
-		{
-			title = "Crumbling, Respawn, Int. from Bottom, Translucent";
-			prefix = "(174)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Don't cast shadow";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "210959F";
-			flags643dfloorflagsadd = "40";
-		}
-
-		175
-		{
-			title = "Crumbling, No Respawn, Int. from Bottom, Translucent";
-			prefix = "(175)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Don't cast shadow";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "218959F";
-			flags643dfloorflagsadd = "40";
-		}
-
-		176
-		{
-			title = "Crumbling, Respawn, Floating, Bobbing";
-			prefix = "(176)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash to move";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "14019F";
-		}
-
-		177
-		{
-			title = "Crumbling, No Respawn, Floating, Bobbing";
-			prefix = "(177)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash to move";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "1C019F";
-		}
-
-		178
-		{
-			title = "Crumbling, Respawn, Floating";
-			prefix = "(178)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "14019F";
-		}
-
-		179
-		{
-			title = "Crumbling, No Respawn, Floating";
-			prefix = "(179)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "1C019F";
-		}
-
-		180
-		{
-			title = "Crumbling, Respawn, Air Bobbing";
-			prefix = "(180)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags64text = "[6] Spindash to move";
-			flags128text = "[7] Only block non-players";
-			3dfloor = true;
-			3dfloorflags = "10019F";
-		}
-	}
-
-	fofspecial
-	{
-		title = "FOF (special)";
-
-		200
-		{
-			title = "Light Block";
-			prefix = "(200)";
-			3dfloor = true;
-			3dfloorflags = "20201";
-		}
-
-		201
-		{
-			title = "Half Light Block";
-			prefix = "(201)";
-			3dfloor = true;
-			3dfloorflags = "201";
-		}
-
-		202
-		{
-			title = "Fog Block";
-			prefix = "(202)";
-			3dfloor = true;
-			3dfloorflags = "3EF19";
-		}
-
-		250
-		{
-			title = "Mario Block";
-			prefix = "(250)";
-			flags32text = "[5] Invisible block";
-			flags64text = "[6] Brick block";
-			3dfloor = true;
-			3dfloorflags = "40019F";
-		}
-
-		251
-		{
-			title = "Thwomp Block";
-			prefix = "(251)";
-			flags512text = "[9] Custom crushing sound";
-			flags1024text = "[10] Custom speed";
-			3dfloor = true;
-			3dfloorflags = "19F";
-		}
-
-		252
-		{
-			title = "Shatter Block";
-			prefix = "(252)";
-			flags8text = "[3] Slope skew sides";
-			flags64text = "[6] Shatter only from below";
-			flags512text = "[9] Shattered by pushables";
-			flags1024text = "[10] Trigger linedef executor";
-			3dfloor = true;
-			3dfloorflags = "8800019";
-			flags643dfloorflagsadd = "200006";
-		}
-
-		253
-		{
-			title = "Shatter Block, Translucent";
-			prefix = "(253)";
-			flags8text = "[3] Slope skew sides";
-			flags512text = "[9] Shattered by pushables";
-			flags1024text = "[10] Trigger linedef executor";
-			3dfloor = true;
-			3dfloorflags = "8801019";
-		}
-
-		254
-		{
-			title = "Bustable Block";
-			prefix = "(254)";
-			flags8text = "[3] Slope skew sides";
-			flags64text = "[6] Strong characters only";
-			flags128text = "[7] Only block non-players";
-			flags512text = "[9] Shattered by pushables";
-			flags1024text = "[10] Trigger linedef executor";
-			3dfloor = true;
-			3dfloorflags = "80001F";
-			flags643dfloorflagsadd = "20000000";
-		}
-
-		255
-		{
-			title = "Spin-Bustable Block";
-			prefix = "(255)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			flags512text = "[9] Shattered by pushables";
-			flags1024text = "[10] Trigger linedef executor";
-			3dfloor = true;
-			3dfloorflags = "1080001F";
-		}
-
-		256
-		{
-			title = "Spin-Bustable Block, Translucent";
-			prefix = "(256)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			flags512text = "[9] Shattered by pushables";
-			flags1024text = "[10] Trigger linedef executor";
-			3dfloor = true;
-			3dfloorflags = "1080101F";
-		}
-
-		257
-		{
-			title = "Quicksand";
-			prefix = "(257)";
-			flags8text = "[3] Slope skew sides";
-			flags1024text = "[10] Ripple effect";
-			3dfloor = true;
-			3dfloorflags = "1008219";
-			flags10243dfloorflagsadd = "40000000";
-		}
-
-		258
-		{
-			title = "Laser";
-			prefix = "(258)";
-			flags8text = "[3] Slope skew sides";
-			flags32text = "[5] Don't damage bosses";
-			3dfloor = true;
-			3dfloorflags = "959";
-		}
-
-		259
-		{
-			title = "Custom FOF";
-			prefix = "(259)";
-			flags32text = "[5] Only block player";
-			flags128text = "[7] Only block non-players";
-			flags512text = "[9] Shattered by pushables";
-			flags1024text = "[10] Trigger linedef executor";
-			3dfloor = true;
-			3dfloorcustom = true;
-		}
-	}
-
-	linedeftrigger
-	{
-		title = "Linedef Executor Trigger";
-
-		300
-		{
-			title = "Continuous";
-			prefix = "(300)";
-		}
-
-		301
-		{
-			title = "Each Time";
-			prefix = "(301)";
-			flags16384text = "[14] Also trigger on exit";
-		}
-
-		302
-		{
-			title = "Once";
-			prefix = "(302)";
-		}
-
-		303
-		{
-			title = "Ring Count - Continuous";
-			prefix = "(303)";
-			flags2text = "[1] Rings greater or equal";
-			flags64text = "[6] Rings less or equal";
-			flags512text = "[9] Consider all players";
-		}
-
-		304
-		{
-			title = "Ring Count - Once";
-			prefix = "(304)";
-			flags2text = "[1] Rings greater or equal";
-			flags64text = "[6] Rings less or equal";
-			flags512text = "[9] Consider all players";
-		}
-
-		305
-		{
-			title = "Character Ability - Continuous";
-			prefix = "(305)";
-		}
-
-		306
-		{
-			title = "Character Ability - Each Time";
-			prefix = "(306)";
-			flags16384text = "[14] Also trigger on exit";
-		}
-
-		307
-		{
-			title = "Character Ability - Once";
-			prefix = "(307)";
-		}
-
-		308
-		{
-			title = "Race Only - Once";
-			prefix = "(308)";
-		}
-
-		309
-		{
-			title = "CTF Red Team - Continuous";
-			prefix = "(309)";
-		}
-
-		310
-		{
-			title = "CTF Red Team - Each Time";
-			prefix = "(310)";
-			flags16384text = "[14] Also trigger on exit";
-		}
-
-		311
-		{
-			title = "CTF Blue Team - Continuous";
-			prefix = "(311)";
-		}
-
-		312
-		{
-			title = "CTF Blue Team - Each Time";
-			prefix = "(312)";
-			flags16384text = "[14] Also trigger on exit";
-		}
-
-		313
-		{
-			title = "No More Enemies - Once";
-			prefix = "(313)";
-		}
-
-		314
-		{
-			title = "Number of Pushables - Continuous";
-			prefix = "(314)";
-			flags64text = "[6] Number greater or equal";
-			flags512text = "[9] Number less";
-		}
-
-		315
-		{
-			title = "Number of Pushables - Once";
-			prefix = "(315)";
-			flags64text = "[6] Number greater or equal";
-			flags512text = "[9] Number less";
-		}
-
-		317
-		{
-			title = "Condition Set Trigger - Continuous";
-			prefix = "(317)";
-		}
-
-		318
-		{
-			title = "Condition Set Trigger - Once";
-			prefix = "(318)";
-		}
-
-		319
-		{
-			title = "Unlockable - Continuous";
-			prefix = "(319)";
-		}
-
-		320
-		{
-			title = "Unlockable - Once";
-			prefix = "(320)";
-		}
-
-		321
-		{
-			title = "Trigger After X Calls - Continuous";
-			prefix = "(321)";
-			flags64text = "[6] Trigger more than once";
-
-		}
-
-		322
-		{
-			title = "Trigger After X Calls - Each Time";
-			prefix = "(322)";
-			flags64text = "[6] Trigger more than once";
-		}
-
-		323
-		{
-			title = "NiGHTSerize - Each Time";
-			prefix = "(323)";
-			flags2text = "[1] Mare >= Front X Offset";
-			flags8text = "[3] Run only if player is NiGHTS";
-			flags16text = "[4] Count from lowest of players";
-			flags32text = "[5] Lap <= Front Y Offset";
-			flags64text = "[6] Mare <= Front X Offset";
-			flags128text = "[7] Lap >= Front Y Offset";
-			flags256text = "[8] Count laps from Bonus Time";
-			flags512text = "[9] Count from triggering player";
-			flags16384text = "[14] Run if no more mares";
-			flags32768text = "[15] Run if player is not NiGHTS";
-		}
-
-		324
-		{
-			title = "NiGHTSerize - Once";
-			flags2text = "[1] Mare >= Front X Offset";
-			flags8text = "[3] Run only if player is NiGHTS";
-			flags16text = "[4] Count from lowest of players";
-			flags32text = "[5] Lap <= Front Y Offset";
-			flags64text = "[6] Mare <= Front X Offset";
-			flags128text = "[7] Lap >= Front Y Offset";
-			flags256text = "[8] Count laps from Bonus Time";
-			flags512text = "[9] Count from triggering player";
-			flags16384text = "[14] Run if no more mares";
-			flags32768text = "[15] Run if player is not NiGHTS";
-			prefix = "(324)";
-		}
-
-		325
-		{
-			title = "De-NiGHTSerize - Each Time";
-			flags2text = "[1] Mare >= Front X Offset";
-			flags8text = "[3] Run if anyone is NiGHTS";
-			flags16text = "[4] Count from lowest of players";
-			flags32text = "[5] Lap <= Front Y Offset";
-			flags64text = "[6] Mare <= Front X Offset";
-			flags128text = "[7] Lap >= Front Y Offset";
-			flags256text = "[8] Count laps from Bonus Time";
-			flags512text = "[9] Count from triggering player";
-			flags32768text = "[15] Run if no one is NiGHTS";
-			prefix = "(325)";
-		}
-
-		326
-		{
-			title = "De-NiGHTSerize - Once";
-			flags2text = "[1] Mare >= Front X Offset";
-			flags8text = "[3] Run if anyone is NiGHTS";
-			flags16text = "[4] Count from lowest of players";
-			flags32text = "[5] Lap <= Front Y Offset";
-			flags64text = "[6] Mare <= Front X Offset";
-			flags128text = "[7] Lap >= Front Y Offset";
-			flags256text = "[8] Count laps from Bonus Time";
-			flags512text = "[9] Count from triggering player";
-			flags32768text = "[15] Run if no one is NiGHTS";
-			prefix = "(326)";
-		}
-
-		327
-		{
-			title = "NiGHTS Lap - Each Time";
-			flags2text = "[1] Mare >= Front X Offset";
-			flags16text = "[4] Count from lowest of players";
-			flags32text = "[5] Lap <= Front Y Offset";
-			flags64text = "[6] Mare <= Front X Offset";
-			flags128text = "[7] Lap >= Front Y Offset";
-			flags256text = "[8] Count laps from Bonus Time";
-			flags512text = "[9] Count from triggering player";
-			prefix = "(327)";
-		}
-
-		328
-		{
-			title = "NiGHTS Lap - Once";
-			flags2text = "[1] Mare >= Front X Offset";
-			flags16text = "[4] Count from lowest of players";
-			flags32text = "[5] Lap <= Front Y Offset";
-			flags64text = "[6] Mare <= Front X Offset";
-			flags128text = "[7] Lap >= Front Y Offset";
-			flags256text = "[8] Count laps from Bonus Time";
-			flags512text = "[9] Count from triggering player";
-			prefix = "(328)";
-		}
-
-		329
-		{
-			title = "Ideya Capture Touch - Each Time";
-			flags2text = "[1] Mare >= Front X Offset";
-			flags8text = "[3] Run regardless of spheres";
-			flags16text = "[4] Count from lowest of players";
-			flags32text = "[5] Lap <= Front Y Offset";
-			flags64text = "[6] Mare <= Front X Offset";
-			flags128text = "[7] Lap >= Front Y Offset";
-			flags256text = "[8] Count laps from Bonus Time";
-			flags512text = "[9] Count from triggering player";
-			flags16384text = "[14] Only if not enough spheres";
-			flags32768text = "[15] Run when entering Capture";
-			prefix = "(329)";
-		}
-
-		330
-		{
-			title = "Ideya Capture Touch - Once";
-			flags2text = "[1] Mare >= Front X Offset";
-			flags8text = "[3] Run regardless of spheres";
-			flags16text = "[4] Count from lowest of players";
-			flags32text = "[5] Lap <= Front Y Offset";
-			flags64text = "[6] Mare <= Front X Offset";
-			flags128text = "[7] Lap >= Front Y Offset";
-			flags256text = "[8] Count laps from Bonus Time";
-			flags512text = "[9] Count from triggering player";
-			flags16384text = "[14] Only if not enough spheres";
-			flags32768text = "[15] Run when entering Capture";
-			prefix = "(330)";
-		}
-
-		331
-		{
-			title = "Player Skin - Continuous";
-			flags64text = "[6] Disable for this skin";
-			prefix = "(331)";
-		}
-
-		332
-		{
-			title = "Player Skin - Each Time";
-			flags64text = "[6] Disable for this skin";
-			prefix = "(332)";
-		}
-
-		333
-		{
-			title = "Player Skin - Once";
-			flags64text = "[6] Disable for this skin";
-			prefix = "(333)";
-		}
-
-		399
-		{
-			title = "Level Load";
-			prefix = "(399)";
-		}
-	}
-
-	linedefexecsector
-	{
-		title = "Linedef Executor (sector)";
-
-		400
-		{
-			title = "Set Tagged Sector's Floor Height/Texture";
-			prefix = "(400)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Keep floor flat";
-		}
-
-		401
-		{
-			title = "Set Tagged Sector's Ceiling Height/Texture";
-			prefix = "(401)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		402
-		{
-			title = "Set Tagged Sector's Light Level";
-			prefix = "(402)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		409
-		{
-			title = "Change Tagged Sector's Tag";
-			prefix = "(409)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		410
-		{
-			title = "Change Front Sector's Tag";
-			prefix = "(410)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		416
-		{
-			title = "Start Adjustable Flickering Light";
-			prefix = "(416)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Second level from back";
-		}
-
-		417
-		{
-			title = "Start Adjustable Pulsating Light";
-			prefix = "(417)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Second level from back";
-		}
-
-		418
-		{
-			title = "Start Adjustable Blinking Light (unsynchronized)";
-			prefix = "(418)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Second level from back";
-		}
-
-		419
-		{
-			title = "Start Adjustable Blinking Light (synchronized)";
-			prefix = "(419)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Second level from back";
-		}
-
-		420
-		{
-			title = "Fade Light Level";
-			prefix = "(420)";
-			flags8text = "[3] Set delay by backside sector";
-			flags16text = "[4] Set params by X/Y offsets";
-			flags512text = "[9] Speed = Tic Duration";
-			flags1024text = "[10] Override existing fade";
-		}
-
-		421
-		{
-			title = "Stop Lighting Effect";
-			prefix = "(421)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		435
-		{
-			title = "Change Plane Scroller Direction";
-			prefix = "(435)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-	}
-
-	linedefexecplane
-	{
-		title = "Linedef Executor (plane movement)";
-
-		403
-		{
-			title = "Move Tagged Sector's Floor";
-			prefix = "(403)";
-			flags2text = "[1] Trigger linedef executor";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Change floor flat";
-		}
-
-		404
-		{
-			title = "Move Tagged Sector's Ceiling";
-			prefix = "(404)";
-			flags2text = "[1] Trigger linedef executor";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Change ceiling flat";
-		}
-
-		405
-		{
-			title = "Move Floor According to Front Texture Offsets";
-			prefix = "(405)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Move instantly";
-		}
-
-		407
-		{
-			title = "Move Ceiling According to Front Texture Offsets";
-			prefix = "(407)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Move instantly";
-		}
-
-		411
-		{
-			title = "Stop Plane Movement";
-			prefix = "(411)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		428
-		{
-			title = "Start Platform Movement";
-			prefix = "(428)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Move upwards at start";
-		}
-
-		429
-		{
-			title = "Crush Ceiling Once";
-			prefix = "(429)";
-			flags8text = "[3] Set delay by backside sector";
-			flags512text = "[9] Double, constant speed";
-		}
-
-		430
-		{
-			title = "Crush Floor Once";
-			prefix = "(430)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		431
-		{
-			title = "Crush Floor and Ceiling Once";
-			prefix = "(431)";
-			flags8text = "[3] Set delay by backside sector";
-			flags512text = "[9] Double, constant speed";
-		}
-	}
-
-	linedefexecplayer
-	{
-		title = "Linedef Executor (player/object)";
-
-		412
-		{
-			title = "Teleporter";
-			prefix = "(412)";
-			flags2text = "[1] Silent";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Retain angle";
-			flags256text = "[8] Relative, silent";
-			flags512text = "[9] Retain momentum";
-		}
-
-		425
-		{
-			title = "Change Object State";
-			prefix = "(425)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		426
-		{
-			title = "Stop Object";
-			prefix = "(426)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Teleport to sector center";
-		}
-
-		427
-		{
-			title = "Award Score";
-			prefix = "(427)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		432
-		{
-			title = "Enable/Disable 2D Mode";
-			prefix = "(432)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Return to 3D";
-		}
-
-		433
-		{
-			title = "Enable/Disable Gravity Flip";
-			prefix = "(433)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Return to normal";
-		}
-
-		434
-		{
-			title = "Award Power-Up";
-			prefix = "(434)";
-			flags2text = "[1] Use back upper texture";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] No time limit";
-		}
-
-		437
-		{
-			title = "Disable Player Control";
-			prefix = "(437)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Allow jumping";
-		}
-
-		438
-		{
-			title = "Change Object Size";
-			prefix = "(438)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		442
-		{
-			title = "Change Object Type State";
-			prefix = "(442)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		457
-		{
-			title = "Track Object's Angle";
-			prefix = "(457)";
-			flags8text = "[3] Set delay by backside sector";
-			flags128text = "[7] Don't stop after first fail";
-		}
-
-		458
-		{
-			title = "Stop Tracking Object's Angle";
-			prefix = "(458)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		460
-		{
-			title = "Award Rings";
-			prefix = "(460)";
-		}
-
-		461
-		{
-			title = "Spawn Object";
-			prefix = "(461)";
-			flags64text = "[6] Spawn inside a range";
-		}
-
-		462
-		{
-			title = "Stop Timer/Exit Stage in Record Attack";
-			prefix = "(462)";
-		}
-	}
-
-	linedefexecmisc
-	{
-		title = "Linedef Executor (misc.)";
-
-		413
-		{
-			title = "Change Music";
-			prefix = "(413)";
-			flags2text = "[1] Keep after death";
-			flags8text = "[3] Set delay by backside sector";
-			flags32text = "[5] Seek to current song position";
-			flags64text = "[6] For everyone";
-			flags128text = "[7] Fade to custom volume";
-			flags512text = "[9] Don't loop";
-			flags16384text = "[14] Force music reload";
-		}
-
-		414
-		{
-			title = "Play Sound Effect";
-			prefix = "(414)";
-			flags2text = "[1] From calling sector";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] From nowhere for triggerer";
-			flags512text = "[9] For everyone";
-			flags1024text = "[10] From tagged sectors";
-		}
-
-		415
-		{
-			title = "Run Script";
-			prefix = "(415)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		422
-		{
-			title = "Switch to Cut-Away View";
-			prefix = "(422)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Adjust pitch";
-		}
-
-		423
-		{
-			title = "Change Sky";
-			prefix = "(423)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] For everyone";
-		}
-
-		424
-		{
-			title = "Change Weather";
-			prefix = "(424)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] For everyone";
-		}
-
-		436
-		{
-			title = "Shatter FOF";
-			prefix = "(436)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		439
-		{
-			title = "Change Tagged Linedef's Textures";
-			prefix = "(439)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Only existing";
-		}
-
-		440
-		{
-			title = "Start Metal Sonic Race";
-			prefix = "(440)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		441
-		{
-			title = "Condition Set Trigger";
-			prefix = "(441)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		443
-		{
-			title = "Call Lua Function";
-			prefix = "(443)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		444
-		{
-			title = "Earthquake";
-			prefix = "(444)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-
-		445
-		{
-			title = "Make FOF Disappear/Reappear";
-			prefix = "(445)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Reappear";
-		}
-
-		446
-		{
-			title = "Make FOF Crumble";
-			prefix = "(446)";
-			flags2text = "[1] Flags determine respawn";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Don't respawn";
-		}
-
-		447
-		{
-			title = "Change Tagged Sector's Colormap";
-			prefix = "(447)";
-			flags8text = "[3] Set delay by backside sector";
-			flags16text = "[4] Front X/Y = Alpha";
-			flags32text = "[5] Subtract Red value";
-			flags64text = "[6] Subtract Green value";
-			flags128text = "[7] Subtract Blue value";
-			flags256text = "[8] Calc relative values";
-			flags32768text = "[15] Use back side colormap";
-		}
-
-		448
-		{
-			title = "Change Skybox";
-			prefix = "(448)";
-			flags2text = "[1] Change centerpoint";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] For everyone";
-			flags512text = "[9] Don't change viewpoint";
-		}
-
-		450
-		{
-			title = "Execute Linedef Executor (specific tag)";
-			prefix = "(450)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		451
-		{
-			title = "Execute Linedef Executor (random tag in range)";
-			prefix = "(451)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		452
-		{
-			title = "Set FOF Translucency";
-			prefix = "(452)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Do not handle FF_TRANS";
-			flags256text = "[8] Set relative to current val";
-		}
-
-		453
-		{
-			title = "Fade FOF";
-			prefix = "(453)";
-			flags2text = "[1] Do not handle FF_EXISTS";
-			flags8text = "[3] Set delay by backside sector";
-			flags32text = "[5] No collision during fade";
-			flags64text = "[6] Do not handle FF_TRANS";
-			flags128text = "[7] Do not handle lighting";
-			flags256text = "[8] Set relative to current val";
-			flags512text = "[9] Speed = Tic Duration";
-			flags1024text = "[10] Override existing fade";
-			flags16384text = "[14] Do not handle collision";
-			flags32768text = "[15] Use exact alpha in OGL";
-		}
-
-		454
-		{
-			title = "Stop Fading FOF";
-			prefix = "(454)";
-			flags2text = "[1] Do not finalize collision";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		455
-		{
-			title = "Fade Tagged Sector's Colormap";
-			prefix = "(455)";
-			flags8text = "[3] Set delay by backside sector";
-			flags16text = "[4] Front X/Y = Alpha";
-			flags32text = "[5] Subtract Red value";
-			flags64text = "[6] Subtract Green value";
-			flags128text = "[7] Subtract Blue value";
-			flags256text = "[8] Calc relative values";
-			flags512text = "[9] Speed = Tic Duration";
-			flags1024text = "[10] Override existing fade";
-			flags16384text = "[14] Fade from invisible black";
-			flags32768text = "[15] Use back side colormap";
-		}
-
-		456
-		{
-			title = "Stop Fading Tagged Sector's Colormap";
-			prefix = "(456)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		459
-		{
-			title = "Control Text Prompt";
-			prefix = "(459)";
-			flags2text = "[1] Close text prompt";
-			flags8text = "[3] Set delay by backside sector";
-			flags32text = "[5] Run executor tag on close";
-			flags64text = "[6] For everyone";
-			flags128text = "[7] Do not block controls";
-			flags256text = "[8] Do not freeze time";
-			flags32768text = "[15] Find prompt by name";
-		}
-	}
-
-	linedefexecpoly
-	{
-		title = "Linedef Executor (polyobject)";
-
-		480
-		{
-			title = "Door Slide";
-			prefix = "(480)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		481
-		{
-			title = "Door Swing";
-			prefix = "(481)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		482
-		{
-			title = "Move";
-			prefix = "(482)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		483
-		{
-			title = "Move, Override";
-			prefix = "(483)";
-			flags8text = "[3] Set delay by backside sector";
-		}
-
-		484
-		{
-			title = "Rotate Right";
-			prefix = "(484)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Don't turn players";
-			flags512text = "[9] Turn all objects";
-		}
-
-		485
-		{
-			title = "Rotate Right, Override";
-			prefix = "(485)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Don't turn players";
-			flags512text = "[9] Turn all objects";
-		}
-
-		486
-		{
-			title = "Rotate Left";
-			prefix = "(486)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Don't turn players";
-			flags512text = "[9] Turn all objects";
-		}
-
-		487
-		{
-			title = "Rotate Left, Override";
-			prefix = "(487)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Don't turn players";
-			flags512text = "[9] Turn all objects";
-		}
-
-		488
-		{
-			title = "Move by Waypoints";
-			prefix = "(488)";
-			flags8text = "[3] Set delay by backside sector";
-			flags32text = "[5] Reverse order";
-			flags128text = "[7] There and back";
-			flags256text = "[8] Return when done";
-			flags512text = "[9] Loop movement";
-		}
-
-		489
-		{
-			title = "Turn Invisible, Intangible";
-			prefix = "(489)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Only invisible";
-		}
-
-		490
-		{
-			title = "Turn Visible, Tangible";
-			prefix = "(490)";
-			flags8text = "[3] Set delay by backside sector";
-			flags64text = "[6] Only visible";
-		}
-
-		491
-		{
-			title = "Set Translucency";
-			prefix = "(491)";
-			flags8text = "[3] Set delay by backside sector";
-			flags16text = "[4] Set raw alpha by Front X";
-			flags256text = "[8] Calc relative values";
-		}
-
-		492
-		{
-			title = "Fade Translucency";
-			prefix = "(492)";
-			flags8text = "[3] Set delay by backside sector";
-			flags16text = "[4] Set raw alpha by Front X";
-			flags32text = "[5] No collision during fade";
-			flags256text = "[8] Calc relative values";
-			flags512text = "[9] Speed = Tic Duration";
-			flags1024text = "[10] Override existing fade";
-			flags16384text = "[14] Do not handle collision";
-		}
-	}
-
-	wallscroll
-	{
-		title = "Wall Scrolling";
-
-		500
-		{
-			title = "Scroll Wall Front Side Left";
-			prefix = "(500)";
-		}
-
-		501
-		{
-			title = "Scroll Wall Front Side Right";
-			prefix = "(501)";
-		}
-
-		502
-		{
-			title = "Scroll Wall According to Linedef";
-			prefix = "(502)";
-		}
-
-		503
-		{
-			title = "Scroll Wall According to Linedef (Accelerative)";
-			prefix = "(503)";
-		}
-
-		504
-		{
-			title = "Scroll Wall According to Linedef (Displacement)";
-			prefix = "(504)";
-		}
-
-		505
-		{
-			title = "Scroll Texture by Front Side Offsets";
-			prefix = "(505)";
-		}
-
-		506
-		{
-			title = "Scroll Texture by Back Side Offsets";
-			prefix = "(506)";
-		}
-	}
-
-	planescroll
-	{
-		title = "Plane Scrolling";
-
-		510
-		{
-			title = "Scroll Floor Texture";
-			prefix = "(510)";
-		}
-
-		511
-		{
-			title = "Scroll Floor Texture (Accelerative)";
-			prefix = "(511)";
-		}
-
-		512
-		{
-			title = "Scroll Floor Texture (Displacement)";
-			prefix = "(512)";
-		}
-
-		513
-		{
-			title = "Scroll Ceiling Texture";
-			prefix = "(513)";
-		}
-
-		514
-		{
-			title = "Scroll Ceiling Texture (Accelerative)";
-			prefix = "(514)";
-		}
-
-		515
-		{
-			title = "Scroll Ceiling Texture (Displacement)";
-			prefix = "(515)";
-		}
-
-		520
-		{
-			title = "Carry Objects on Floor";
-			prefix = "(520)";
-		}
-
-		521
-		{
-			title = "Carry Objects on Floor (Accelerative)";
-			prefix = "(521)";
-			flags64text = "[6] Even across edges";
-		}
-
-		522
-		{
-			title = "Carry Objects on Floor (Displacement)";
-			prefix = "(522)";
-		}
-
-		523
-		{
-			title = "Carry Objects on Ceiling";
-			prefix = "(523)";
-			flags64text = "[6] Even across edges";
-		}
-
-		524
-		{
-			title = "Carry Objects on Ceiling (Accelerative)";
-			prefix = "(524)";
-		}
-
-		525
-		{
-			title = "Carry Objects on Ceiling (Displacement)";
-			prefix = "(525)";
-		}
-
-		530
-		{
-			title = "Scroll Floor Texture and Carry Objects";
-			prefix = "(530)";
-			flags64text = "[6] Even across edges";
-		}
-
-		531
-		{
-			title = "Scroll Floor Texture and Carry Objects (Accelerative)";
-			prefix = "(531)";
-		}
-
-		532
-		{
-			title = "Scroll Floor Texture and Carry Objects (Displacement)";
-			prefix = "(532)";
-		}
-
-		533
-		{
-			title = "Scroll Ceiling Texture and Carry Objects";
-			prefix = "(533)";
-			flags64text = "[6] Even across edges";
-		}
-
-		534
-		{
-			title = "Scroll Ceiling Texture and Carry Objects (Accelerative)";
-			prefix = "(534)";
-		}
-
-		535
-		{
-			title = "Scroll Ceiling Texture and Carry Objects (Displacement)";
-			prefix = "(535)";
-		}
-	}
-
-	pusher
-	{
-		title = "Pusher";
-
-		541
-		{
-			title = "Wind";
-			prefix = "(541)";
-			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
-		}
-
-		542
-		{
-			title = "Upwards Wind";
-			prefix = "(542)";
-			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
-		}
-
-		543
-		{
-			title = "Downwards Wind";
-			prefix = "(543)";
-			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
-		}
-
-		544
-		{
-			title = "Current";
-			prefix = "(544)";
-			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
-		}
-
-		545
-		{
-			title = "Upwards Current";
-			prefix = "(545)";
-			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
-		}
-
-		546
-		{
-			title = "Downwards Current";
-			prefix = "(546)";
-			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
-		}
-
-		547
-		{
-			title = "Push/Pull";
-			prefix = "(547)";
-		}
-	}
-
-	light
-	{
-		title = "Lighting";
-
-		600
-		{
-			title = "Floor Lighting";
-			prefix = "(600)";
-		}
-
-		601
-		{
-			title = "Ceiling Lighting";
-			prefix = "(601)";
-		}
-
-		602
-		{
-			title = "Adjustable Pulsating Light";
-			prefix = "(602)";
-		}
-
-		603
-		{
-			title = "Adjustable Flickering Light";
-			prefix = "(603)";
-		}
-
-		604
-		{
-			title = "Adjustable Blinking Light (unsynchronized)";
-			prefix = "(604)";
-		}
-
-		605
-		{
-			title = "Adjustable Blinking Light (synchronized)";
-			prefix = "(605)";
-		}
-
-		606
-		{
-			title = "Colormap";
-			prefix = "(606)";
-		}
-	}
-
-	slope
-	{
-		title = "Slope";
-
-		700
-		{
-			title = "Slope Frontside Floor";
-			prefix = "(700)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			slope = "regular";
-			slopeargs = 1;
-		}
-
-		701
-		{
-			title = "Slope Frontside Ceiling";
-			prefix = "(701)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			slope = "regular";
-			slopeargs = 2;
-		}
-
-		702
-		{
-			title = "Slope Frontside Floor and Ceiling";
-			prefix = "(702)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			slope = "regular";
-			slopeargs = 3;
-		}
-
-		703
-		{
-			title = "Slope Frontside Floor and Backside Ceiling";
-			prefix = "(703)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			slope = "regular";
-			slopeargs = 9;
-		}
-
-		704
-		{
-			title = "Slope Frontside Floor by 3 Tagged Vertex Things";
-			prefix = "(704)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			flags8192text = "[13] Use tag and offsets";
-			slope = "vertex";
-			slopeargs = 0;
-		}
-
-		705
-		{
-			title = "Slope Frontside Ceiling by 3 Tagged Vertex Things";
-			prefix = "(705)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			flags8192text = "[13] Use tag and offsets";
-			slope = "vertex";
-			slopeargs = 1;
-		}
-
-		710
-		{
-			title = "Slope Backside Floor";
-			prefix = "(710)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			slope = "regular";
-			slopeargs = 4;
-		}
-
-		711
-		{
-			title = "Slope Backside Ceiling";
-			prefix = "(711)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			slope = "regular";
-			slopeargs = 8;
-		}
-
-		712
-		{
-			title = "Slope Backside Floor and Ceiling";
-			prefix = "(712)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			slope = "regular";
-			slopeargs = 12;
-		}
-
-		713
-		{
-			title = "Slope Backside Floor and Frontside Ceiling";
-			prefix = "(713)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			slope = "regular";
-			slopeargs = 6;
-		}
-
-		714
-		{
-			title = "Slope Backside Floor by 3 Tagged Vertex Things";
-			prefix = "(714)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			flags8192text = "[13] Use tag and offsets";
-			slope = "vertex";
-			slopeargs = 2;
-		}
-
-		715
-		{
-			title = "Slope Backside Ceiling by 3 Tagged Vertex Things";
-			prefix = "(715)";
-			flags2048text = "[11] No physics";
-			flags4096text = "[12] Dynamic";
-			flags8192text = "[13] Use tag and offsets";
-			slope = "vertex";
-			slopeargs = 3;
-		}
-
-		720
-		{
-			title = "Copy Frontside Floor Slope from Line Tag";
-			prefix = "(720)";
-			slope = "copy";
-			slopeargs = 1;
-		}
-
-		721
-		{
-			title = "Copy Frontside Ceiling Slope from Line Tag";
-			prefix = "(721)";
-			slope = "copy";
-			slopeargs = 2;
-		}
-
-		722
-		{
-			title = "Copy Frontside Floor and Ceiling Slope from Line Tag";
-			prefix = "(722)";
-			slope = "copy";
-			slopeargs = 3;
-		}
-
-		799
-		{
-			title = "Set Tagged Dynamic Slope Vertex to Front Sector Height";
-			prefix = "(799)";
-		}
-	}
-
-	transwall
-	{
-		title = "Translucent Wall";
-
-		900
-		{
-			title = "90% Opaque";
-			prefix = "(900)";
-		}
-
-		901
-		{
-			title = "80% Opaque";
-			prefix = "(901)";
-		}
-
-		902
-		{
-			title = "70% Opaque";
-			prefix = "(902)";
-		}
-
-		903
-		{
-			title = "60% Opaque";
-			prefix = "(903)";
-		}
-
-		904
-		{
-			title = "50% Opaque";
-			prefix = "(904)";
-		}
-
-		905
-		{
-			title = "40% Opaque";
-			prefix = "(905)";
-		}
-
-		906
-		{
-			title = "30% Opaque";
-			prefix = "(906)";
-		}
-
-		907
-		{
-			title = "20% Opaque";
-			prefix = "(907)";
-		}
-
-		908
-		{
-			title = "10% Opaque";
-			prefix = "(908)";
-		}
-
-		909
-		{
-			title = "Fog Wall";
-			prefix = "(909)";
-		}
-	}
-}
-
-udmf
-{
-	misc
-	{
-		title = "Miscellaneous";
-
-		0
-		{
-			title = "None";
-			prefix = "(0)";
-		}
-	}
-}
\ No newline at end of file
diff --git a/extras/conf/Includes/SRB222_misc.cfg b/extras/conf/Includes/SRB222_misc.cfg
deleted file mode 100644
index ce23388b2..000000000
--- a/extras/conf/Includes/SRB222_misc.cfg
+++ /dev/null
@@ -1,726 +0,0 @@
-linedefflags
-{
-	1 = "[0] Impassable";
-	2 = "[1] Block Enemies";
-	4 = "[2] Double-Sided";
-	8 = "[3] Upper Unpegged";
-	16 = "[4] Lower Unpegged";
-	32 = "[5] Slope Skew (E1)";
-	64 = "[6] Not Climbable";
-	128 = "[7] No Midtexture Skew (E2)";
-	256 = "[8] Peg Midtexture (E3)";
-	512 = "[9] Solid Midtexture (E4)";
-	1024 = "[10] Repeat Midtexture (E5)";
-	2048 = "[11] Netgame Only";
-	4096 = "[12] No Netgame";
-	8192 = "[13] Effect 6";
-	16384 = "[14] Bouncy Wall";
-	32768 = "[15] Transfer Line";
-}
-
-
-// LINEDEF ACTIVATIONS
-// Make sure these are in order from lowest value to highest value
-linedefactivations
-{
-}
-
-
-// Linedef flags UDMF translation table
-// This is needed for copy/paste and prefabs to work properly
-// When the UDMF field name is prefixed with ! it is inverted
-linedefflagstranslation
-{
-	1 = "blocking";
-	2 = "blockmonsters";
-	4 = "twosided";
-	8 = "dontpegtop";
-	16 = "dontpegbottom";
-	32 = "skewtd";
-	64 = "noclimb";
-	128 = "noskew";
-	256 = "midpeg";
-	512 = "midsolid";
-	1024 = "wrapmidtex";
-	2048 = "netonly";
-	4096 = "nonet";
-	8192 = "effect6";
-	16384 = "bouncy";
-	32768 = "transfer";
-}
-
-
-linedefflags_udmf
-{
-	blocking = "Impassable";
-	blockmonsters = "Block Enemies";
-	twosided = "Double-Sided";
-	dontpegtop = "Upper Unpegged";
-	dontpegbottom = "Lower Unpegged";
-	skewtd = "Slope Skew";
-	noclimb = "Not Climbable";
-	noskew = "No Midtexture Skew";
-	midpeg = "Peg Midtexture";
-	midsolid = "Solid Midtexture";
-	wrapmidtex = "Repeat Midtexture";
-//	netonly = "Netgame-Only special";
-//	nonet = "No netgame special";
-//	effect6 = "Effect 6";
-	bouncy = "Bouncy Wall";
-//	transfer = "Transfer Line";
-}
-
-
-linedefactivations_udmf
-{
-	notriggerorder = "Out of Order";
-	netonly = "Netgame-Only";
-	nonet = "No netgame";
-}
-
-sidedefflags
-{
-	clipmidtex = "Clip middle texture";
-	wrapmidtex = "Wrap middle texture";
-	smoothlighting = "Smooth lighting";
-	nofakecontrast = "Even lighting";
-	nodecals = "No decals";
-	lightfog = "Use sidedef brightness on fogged walls";
-}
-
-//RENDER STYLES
-thingrenderstyles
-{
-}
-
-linedefrenderstyles
-{
-	translucent = "Translucent";
-	fog = "Fog";
-}
-
-sectorrenderstyles
-{
-}
-
-thingflags
-{
-	1 = "[1] Extra";
-	2 = "[2] Flip";
-	4 = "[4] Special";
-	8 = "[8] Ambush";
-}
-
-// THING FLAGS
-thingflags_udmf
-{
-	extra = "Extra";
-	flip = "Flip";
-	special = "Special";
-	ambush = "Ambush";
-}
-
-
-// Thing flags UDMF translation table
-// This is needed for copy/paste and prefabs to work properly
-// When the UDMF field name is prefixed with ! it is inverted
-thingflagstranslation
-{
-	1 = "extra";
-	2 = "flip";
-	4 = "special";
-	8 = "ambush";
-}
-
-
-// DEFAULT SECTOR BRIGHTNESS LEVELS
-sectorbrightness
-{
-	255;
-	248;
-	240;
-	232;
-	224;
-	216;
-	208;
-	200;
-	192;
-	184;
-	176;
-	168;
-	160;
-	152;
-	144;
-	136;
-	128;
-	120;
-	112;
-	104;
-	96;
-	88;
-	80;
-	72;
-	64;
-	56;
-	48;
-	40;
-	32;
-	24;
-	16;
-	8;
-	0;
-}
-
-/*
-TEXTURES AND FLAT SOURCES
-This tells Doom Builder where to find the information for textures
-and flats in the IWAD file, Addition WAD file and Map WAD file.
-
-Start and end lumps must be given in a structure (of which the
-key name doesnt matter) and any textures or flats in between them
-are loaded in either the textures category or flats category.
-
-For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default.
-*/
-textures
-{
-	zdoom1
-	{
-		start = "TX_START";
-		end = "TX_END";
-	}
-}
-
-/*
-ADDITIONAL UNIVERSAL DOOM MAP FORMAT FIELD DEFINITIONS
-Only add fields here that Doom Builder does not edit with its own user-interface!
-The "default" field must match the UDMF specifications!
-
-Field data types:
-0 = integer *
-1 = float
-2 = string
-3 = bool
-4 = linedef action (integer) *
-5 = sector effect (integer) *
-6 = texture (string)
-7 = flat (string)
-8 = angle in degrees (integer)
-9 = angle in radians (float)
-10 = XXRRGGBB color (integer)
-11 = enum option (integer) *
-12 = enum bits (integer) *
-13 = sector tag (integer) *
-14 = thing tag (integer) *
-15 = linedef tag (integer) *
-16 = enum option (string)
-17 = angle in degrees (float)
-22 = byte angle (integer)
-*/
-universalfields
-{
-	sector
-	{
-		friction
-		{
-			name = "Friction";
-			type = 1;
-			default = 1;
-		}
-
-		specialeffectplanes
-		{
-			type = 11;
-			enum = "floorceiling";
-			default = 0;
-		}
-
-		colormapbegin
-		{
-			type = 0;
-			default = 0;
-		}
-
-		colormapend
-		{
-			type = 0;
-			default = 33;
-		}
-
-		foglighting
-		{
-			type = 3;
-			default = false;
-		}
-
-		teambase
-		{
-			type = 11;
-			enum = "ctfteam";
-			default = 0;
-		}
-
-		triggersector
-		{
-			type = 3;
-			default = false;
-		}
-
-		triggerobject
-		{
-			type = 11;
-			enum = "triggerobjects";
-			default = 0;
-		}
-
-		triggersurface
-		{
-			type = 11;
-			enum = "triggersurfaces";
-			default = 0;
-		}
-
-		ringdrain
-		{
-			type = 1;
-			default = 0;
-		}
-	}
-
-	linedef
-	{
-		executordelay
-		{
-			type = 0;
-			default = 0;
-		}
-		midtexrepetitions
-		{
-			type = 0;
-			default = 0;
-		}
-		arg5
-		{
-			type = 0;
-			default = 0;
-		}
-		arg1str
-		{
-			type = 2;
-			default = "";
-		}
-	}
-
-	thing
-	{
-	}
-}
-
-/*
-MAP LUMP NAMES
-Map lumps are loaded with the map as long as they are right after each other. When the editor
-meets a lump which is not defined in this list it will ignore the map if not satisfied.
-The order of items defines the order in which lumps will be written to WAD file on save.
-To indicate the map header lump, use ~MAP
-
-Legenda:
-required = Lump is required to exist.
-blindcopy = Lump will be copied along with the map blindly. (useful for lumps Doom Builder doesn't use)
-nodebuild = The nodebuilder generates this lump.
-allowempty = The nodebuilder is allowed to leave this lump empty.
-scriptbuild = This lump is a text-based script, which should be compiled using current script compiler;
-script = This lump is a text-based script. Specify the filename of the script configuration to use.
-*/
-
-doommaplumpnames
-{
-	~MAP
-	{
-		required = true;
-		blindcopy = true;
-		nodebuild = false;
-	}
-
-	THINGS
-	{
-		required = true;
-		nodebuild = true;
-		allowempty = true;
-	}
-
-	LINEDEFS
-	{
-		required = true;
-		nodebuild = true;
-		allowempty = false;
-	}
-
-	SIDEDEFS
-	{
-		required = true;
-		nodebuild = true;
-		allowempty = false;
-	}
-
-	VERTEXES
-	{
-		required = true;
-		nodebuild = true;
-		allowempty = false;
-	}
-
-	SEGS
-	{
-		required = false;
-		nodebuild = true;
-		allowempty = false;
-	}
-
-	SSECTORS
-	{
-		required = false;
-		nodebuild = true;
-		allowempty = false;
-	}
-
-	NODES
-	{
-		required = false;
-		nodebuild = true;
-		allowempty = false;
-	}
-
-	SECTORS
-	{
-		required = true;
-		nodebuild = true;
-		allowempty = false;
-	}
-
-	REJECT
-	{
-		required = false;
-		nodebuild = true;
-		allowempty = false;
-	}
-
-	BLOCKMAP
-	{
-		required = false;
-		nodebuild = true;
-		allowempty = true;
-	}
-}
-
-udmfmaplumpnames
-{
-	ZNODES
-	{
-		required = false;
-		nodebuild = true;
-		allowempty = false;
-	}
-
-	REJECT
-	{
-		required = false;
-		nodebuild = true;
-		allowempty = false;
-	}
-
-	BLOCKMAP
-	{
-		required = false;
-		nodebuild = true;
-		allowempty = true;
-	}
-}
-
-// ENUMERATIONS
-// These are enumerated lists for linedef types and UDMF fields.
-// Reserved names are: angledeg, anglerad, color, texture, flat
-enums
-{
-	falsetrue
-	{
-		0 = "False";
-		1 = "True";
-	}
-
-	yesno
-	{
-		0 = "Yes";
-		1 = "No";
-	}
-
-	noyes
-	{
-		0 = "No";
-		1 = "Yes";
-	}
-
-	onoff
-	{
-		0 = "On";
-		1 = "Off";
-	}
-
-	offon
-	{
-		0 = "Off";
-		1 = "On";
-	}
-
-	updown
-	{
-		0 = "Up";
-		1 = "Down";
-	}
-
-	downup
-	{
-		0 = "Down";
-		1 = "Up";
-	}
-
-	addset
-	{
-		0 = "Add";
-		1 = "Set";
-	}
-
-	floorceiling
-	{
-		0 = "Floor";
-		1 = "Ceiling";
-		2 = "Floor and ceiling";
-	}
-
-	triggertype
-	{
-		0 = "Continuous";
-		1 = "Each Time (Enter)";
-		2 = "Each Time (Enter and leave)";
-		3 = "Once";
-	}
-
-	frontback
-	{
-		0 = "None";
-		1 = "Front";
-		2 = "Back";
-	}
-
-	ctfteam
-	{
-		0 = "None";
-		1 = "Red";
-		2 = "Blue";
-	}
-
-	triggerobjects
-	{
-		0 = "Any player";
-		1 = "All players";
-		2 = "Pushable object";
-		3 = "Any object with thinker";
-	}
-
-	triggersurfaces
-	{
-		0 = "Floor touch";
-		1 = "Ceiling touch";
-		2 = "Floor or ceiling touch";
-		3 = "Anywhere in sector";
-	}
-
-	tangibility
-	{
-		1 = "Intangible from top";
-		2 = "Intangible from bottom";
-		4 = "Don't block players";
-		8 = "Don't block non-players";
-	}
-}
-
-//Default things filters
-thingsfilters
-{
-
-	filter0
-	{
-		name = "Player starts";
-		category = "starts";
-		type = -1;
-	}
-
-
-	filter1
-	{
-		name = "Enemies";
-		category = "enemies";
-		type = -1;
-
-	}
-
-
-	filter2
-	{
-		name = "NiGHTS Track";
-		category = "nightstrk";
-		type = -1;
-
-	}
-
-
-	filter3
-	{
-		name = "Normal Gravity";
-		category = "";
-		type = -1;
-
-		fields
-		{
-			2 = false;
-		}
-
-	}
-
-
-	filter4
-	{
-		name = "Reverse Gravity";
-		category = "";
-		type = -1;
-
-		fields
-		{
-			2 = true;
-		}
-
-	}
-}
-
-thingsfilters_udmf
-{
-}
-
-// Special linedefs
-speciallinedefs
-{
-	soundlinedefflag = 64;	// See linedefflags
-	singlesidedflag = 1;	// See linedefflags
-	doublesidedflag = 4;	// See linedefflags
-	impassableflag = 1;
-	upperunpeggedflag = 8;
-	lowerunpeggedflag = 16;
-	repeatmidtextureflag = 1024;
-	pegmidtextureflag = 256;
-}
-
-speciallinedefs_udmf
-{
-	soundlinedefflag = "noclimb";
-	singlesidedflag = "blocking";
-	doublesidedflag = "twosided";
-	impassableflag = "blocking";
-	upperunpeggedflag = "dontpegtop";
-	lowerunpeggedflag = "dontpegbottom";
-	repeatmidtextureflag = "wrapmidtex";
-	pegmidtextureflag = "midpeg";
-}
-
-scriptlumpnames
-{
-	MAINCFG
-	{
-		script = "SOC.cfg";
-	}
-
-	OBJCTCFG
-	{
-		script = "SOC.cfg";
-	}
-
-	SOC_
-	{
-		script = "SOC.cfg";
-		isprefix = true;
-	}
-
-	LUA_
-	{
-		script = "Lua.cfg";
-		isprefix = true;
-	}
-}
-
-// Texture sources
-textures
-{
-	zdoom1
-	{
-		start = "TX_START";
-		end = "TX_END";
-	}
-}
-
-// Patch sources
-patches
-{
-	standard1
-	{
-		start = "P_START";
-		end = "P_END";
-	}
-
-	standard2
-	{
-		start = "PP_START";
-		end = "PP_END";
-	}
-}
-
-// Sprite sources
-sprites
-{
-	standard1
-	{
-		start = "S_START";
-		end = "S_END";
-	}
-
-	standard2
-	{
-		start = "SS_START";
-		end = "SS_END";
-	}
-}
-
-// Flat sources
-flats
-{
-	standard1
-	{
-		start = "F_START";
-		end = "F_END";
-	}
-
-	standard2
-	{
-		start = "FF_START";
-		end = "FF_END";
-	}
-
-	standard3
-	{
-		start = "FF_START";
-		end = "F_END";
-	}
-
-	standard4
-	{
-		start = "F_START";
-		end = "FF_END";
-	}
-}
\ No newline at end of file
diff --git a/extras/conf/Includes/SRB222_sectors.cfg b/extras/conf/Includes/SRB222_sectors.cfg
deleted file mode 100644
index 3bcbeb1b1..000000000
--- a/extras/conf/Includes/SRB222_sectors.cfg
+++ /dev/null
@@ -1,109 +0,0 @@
-sectortypes
-{
-	0 = "Normal";
-	1 = "Damage";
-	2 = "Damage (Water)";
-	3 = "Damage (Fire)";
-	4 = "Damage (Electrical)";
-	5 = "Spikes";
-	6 = "Death Pit (Camera Tilt)";
-	7 = "Death Pit (No Camera Tilt)";
-	8 = "Instant Kill";
-	9 = "Ring Drainer (Floor Touch)";
-	10 = "Ring Drainer (Anywhere in Sector)";
-	11 = "Special Stage Damage";
-	12 = "Space Countdown";
-	13 = "Ramp Sector (double step-up/down)";
-	14 = "Non-Ramp Sector (no step-down)";
-	15 = "Bouncy FOF";
-	16 = "Trigger Line Ex. (Pushable Objects)";
-	32 = "Trigger Line Ex. (Anywhere, All Players)";
-	48 = "Trigger Line Ex. (Floor Touch, All Players)";
-	64 = "Trigger Line Ex. (Anywhere in Sector)";
-	80 = "Trigger Line Ex. (Floor Touch)";
-	96 = "Trigger Line Ex. (Emerald Check)";
-	112 = "Trigger Line Ex. (NiGHTS Mare)";
-	128 = "Check for Linedef Executor on FOFs";
-	144 = "Egg Capsule";
-	160 = "Special Stage Time/Rings Parameters";
-	176 = "Custom Global Gravity";
-	512 = "Wind/Current";
-	1024 = "Conveyor Belt";
-	1280 = "Speed Pad";
-	4096 = "Star Post Activator";
-	8192 = "Exit/Special Stage Pit/Return Flag";
-	12288 = "CTF Red Team Base";
-	16384 = "CTF Blue Team Base";
-	20480 = "Fan Sector";
-	24576 = "Super Sonic Transform";
-	28672 = "Force Spin";
-	32768 = "Zoom Tube Start";
-	36864 = "Zoom Tube End";
-	40960 = "Circuit Finish Line";
-	45056 = "Rope Hang";
-	49152 = "Intangible to the Camera";
-}
-
-gen_sectortypes
-{
-	first
-	{
-		0 = "Normal";
-		1 = "Damage";
-		2 = "Damage (Water)";
-		3 = "Damage (Fire)";
-		4 = "Damage (Electrical)";
-		5 = "Spikes";
-		6 = "Death Pit (Camera Tilt)";
-		7 = "Death Pit (No Camera Tilt)";
-		8 = "Instant Kill";
-		9 = "Ring Drainer (Floor Touch)";
-		10 = "Ring Drainer (Anywhere in Sector)";
-		11 = "Special Stage Damage";
-		12 = "Space Countdown";
-		13 = "Ramp Sector (double step-up/down)";
-		14 = "Non-Ramp Sector (no step-down)";
-		15 = "Bouncy FOF";
-	}
-
-	second
-	{
-		0 = "Normal";
-		16 = "Trigger Line Ex. (Pushable Objects)";
-		32 = "Trigger Line Ex. (Anywhere, All Players)";
-		48 = "Trigger Line Ex. (Floor Touch, All Players)";
-		64 = "Trigger Line Ex. (Anywhere in Sector)";
-		80 = "Trigger Line Ex. (Floor Touch)";
-		96 = "Trigger Line Ex. (Emerald Check)";
-		112 = "Trigger Line Ex. (NiGHTS Mare)";
-		128 = "Check for Linedef Executor on FOFs";
-		144 = "Egg Capsule";
-		160 = "Special Stage Time/Rings Parameters";
-		176 = "Custom Global Gravity";
-	}
-
-	third
-	{
-		0 = "Normal";
-		512 = "Wind/Current";
-		1024 = "Conveyor Belt";
-		1280 = "Speed Pad";
-	}
-
-	fourth
-	{
-		0 = "Normal";
-		4096 = "Star Post Activator";
-		8192 = "Exit/Special Stage Pit/Return Flag";
-		12288 = "CTF Red Team Base";
-		16384 = "CTF Blue Team Base";
-		20480 = "Fan Sector";
-		24576 = "Super Sonic Transform";
-		28672 = "Force Spin";
-		32768 = "Zoom Tube Start";
-		36864 = "Zoom Tube End";
-		40960 = "Circuit Finish Line";
-		45056 = "Rope Hang";
-		49152 = "Intangible to the Camera";
-	}
-}
\ No newline at end of file
diff --git a/extras/conf/Includes/SRB222_things.cfg b/extras/conf/Includes/SRB222_things.cfg
deleted file mode 100644
index 194e43630..000000000
--- a/extras/conf/Includes/SRB222_things.cfg
+++ /dev/null
@@ -1,3398 +0,0 @@
-// THING TYPES------------------------------------------------------------------
-// Color values: 1-Dark_Blue 2-Dark_Green 3-Turqoise 4-Dark_Red 5-Purple 6-Brown 7-Gray
-// 8-Dark_Gray 9-Blue 10-Green 11-Cyan 12-Red 13-Magenta
-// 14-Yellow 15-White 16-Pink 17-Orange 18-Gold 19-Cream
-
-editor
-{
-	color = 15; // White
-	arrow = 1;
-	title = "<Editor Things>";
-	error = -1;
-	width = 8;
-	height = 16;
-	sort = 1;
-
-	3328 = "3D Mode Start";
-}
-
-starts
-{
-	color = 1; // Blue
-	arrow = 1;
-	title = "Player Starts";
-	width = 16;
-	height = 48;
-	flags8text = "[8] Spawn on ceiling";
-	sprite = "PLAYA0";
-
-	1
-	{
-		title = "Player 01 Start";
-		sprite = "PLAYA0";
-	}
-	2
-	{
-		title = "Player 02 Start";
-		sprite = "PLAYA0";
-	}
-	3
-	{
-		title = "Player 03 Start";
-		sprite = "PLAYA0";
-	}
-	4
-	{
-		title = "Player 04 Start";
-		sprite = "PLAYA0";
-	}
-	5
-	{
-		title = "Player 05 Start";
-		sprite = "PLAYA0";
-	}
-	6
-	{
-		title = "Player 06 Start";
-		sprite = "PLAYA0";
-	}
-	7
-	{
-		title = "Player 07 Start";
-		sprite = "PLAYA0";
-	}
-	8
-	{
-		title = "Player 08 Start";
-		sprite = "PLAYA0";
-	}
-	9
-	{
-		title = "Player 09 Start";
-		sprite = "PLAYA0";
-	}
-	10
-	{
-		title = "Player 10 Start";
-		sprite = "PLAYA0";
-	}
-	11
-	{
-		title = "Player 11 Start";
-		sprite = "PLAYA0";
-	}
-	12
-	{
-		title = "Player 12 Start";
-		sprite = "PLAYA0";
-	}
-	13
-	{
-		title = "Player 13 Start";
-		sprite = "PLAYA0";
-	}
-	14
-	{
-		title = "Player 14 Start";
-		sprite = "PLAYA0";
-	}
-	15
-	{
-		title = "Player 15 Start";
-		sprite = "PLAYA0";
-	}
-	16
-	{
-		title = "Player 16 Start";
-		sprite = "PLAYA0";
-	}
-	17
-	{
-		title = "Player 17 Start";
-		sprite = "PLAYA0";
-	}
-	18
-	{
-		title = "Player 18 Start";
-		sprite = "PLAYA0";
-	}
-	19
-	{
-		title = "Player 19 Start";
-		sprite = "PLAYA0";
-	}
-	20
-	{
-		title = "Player 20 Start";
-		sprite = "PLAYA0";
-	}
-	21
-	{
-		title = "Player 21 Start";
-		sprite = "PLAYA0";
-	}
-	22
-	{
-		title = "Player 22 Start";
-		sprite = "PLAYA0";
-	}
-	23
-	{
-		title = "Player 23 Start";
-		sprite = "PLAYA0";
-	}
-	24
-	{
-		title = "Player 24 Start";
-		sprite = "PLAYA0";
-	}
-	25
-	{
-		title = "Player 25 Start";
-		sprite = "PLAYA0";
-	}
-	26
-	{
-		title = "Player 26 Start";
-		sprite = "PLAYA0";
-	}
-	27
-	{
-		title = "Player 27 Start";
-		sprite = "PLAYA0";
-	}
-	28
-	{
-		title = "Player 28 Start";
-		sprite = "PLAYA0";
-	}
-	29
-	{
-		title = "Player 29 Start";
-		sprite = "PLAYA0";
-	}
-	30
-	{
-		title = "Player 30 Start";
-		sprite = "PLAYA0";
-	}
-	31
-	{
-		title = "Player 31 Start";
-		sprite = "PLAYA0";
-	}
-	32
-	{
-		title = "Player 32 Start";
-		sprite = "PLAYA0";
-	}
-	33
-	{
-		title = "Match Start";
-		sprite = "NDRNA2A8";
-	}
-	34
-	{
-		title = "CTF Red Team Start";
-		sprite = "SIGNG0";
-	}
-	35
-	{
-		title = "CTF Blue Team Start";
-		sprite = "SIGNE0";
-	}
-}
-
-enemies
-{
-	color = 9; // Light_Blue
-	arrow = 1;
-	title = "Enemies";
-
-	100
-	{
-		title = "Crawla (Blue)";
-		sprite = "POSSA1";
-		width = 24;
-		height = 32;
-	}
-	101
-	{
-		title = "Crawla (Red)";
-		sprite = "SPOSA1";
-		width = 24;
-		height = 32;
-	}
-	102
-	{
-		title = "Stupid Dumb Unnamed RoboFish";
-		sprite = "FISHA0";
-		width = 8;
-		height = 28;
-		angletext = "Jump strength";
-	}
-	103
-	{
-		title = "Buzz (Gold)";
-		sprite = "BUZZA1";
-		width = 28;
-		height = 40;
-		flags8text = "[8] Cannot move";
-	}
-	104
-	{
-		title = "Buzz (Red)";
-		sprite = "RBUZA1";
-		width = 28;
-		height = 40;
-		flags8text = "[8] Cannot move";
-	}
-	108
-	{
-		title = "Deton";
-		sprite = "DETNA1";
-		width = 20;
-		height = 32;
-	}
-	110
-	{
-		title = "Turret";
-		sprite = "TRETA1";
-		width = 16;
-		height = 32;
-	}
-	111
-	{
-		title = "Pop-up Turret";
-		sprite = "TURRI1";
-		width = 12;
-		height = 64;
-		angletext = "Firing delay";
-	}
-	122
-	{
-		title = "Spring Shell (Green)";
-		sprite = "SSHLA1";
-		width = 24;
-		height = 40;
-	}
-	125
-	{
-		title = "Spring Shell (Yellow)";
-		sprite = "SSHLI1";
-		width = 24;
-		height = 40;
-	}
-	109
-	{
-		title = "Skim";
-		sprite = "SKIMA1";
-		width = 16;
-		height = 24;
-	}
-	113
-	{
-		title = "Jet Jaw";
-		sprite = "JJAWA3A7";
-		width = 12;
-		height = 20;
-	}
-	126
-	{
-		title = "Crushstacean";
-		sprite = "CRABA0";
-		width = 24;
-		height = 32;
-		flags8text = "[8] Move left from spawn";
-	}
-	138
-	{
-		title = "Banpyura";
-		sprite = "CR2BA0";
-		width = 24;
-		height = 32;
-		flags8text = "[8] Move left from spawn";
-	}
-	117
-	{
-		title = "Robo-Hood";
-		sprite = "ARCHA1";
-		width = 24;
-		height = 32;
-	}
-	118
-	{
-		title = "Lance-a-Bot";
-		sprite = "CBFSA1";
-		width = 32;
-		height = 72;
-	}
-	1113
-	{
-		title = "Suspicious Lance-a-Bot Statue";
-		sprite = "CBBSA1";
-		width = 32;
-		height = 72;
-	}
-	119
-	{
-		title = "Egg Guard";
-		sprite = "ESHIA1";
-		width = 16;
-		height = 48;
-		flags1text = "[1] 90 degrees counter-clockwise";
-		flags4text = "[4] 90 degrees clockwise";
-		flags8text = "[8] Double speed";
-	}
-	115
-	{
-		title = "Bird Aircraft Strike Hazard";
-		sprite = "VLTRF1";
-		width = 12;
-		height = 24;
-	}
-	120
-	{
-		title = "Green Snapper";
-		sprite = "GSNPA1";
-		width = 24;
-		height = 24;
-	}
-	121
-	{
-		title = "Minus";
-		sprite = "MNUSA0";
-		width = 24;
-		height = 32;
-	}
-	134
-	{
-		title = "Canarivore";
-		sprite = "CANAA0";
-		width = 12;
-		height = 80;
-		hangs = 1;
-	}
-	123
-	{
-		title = "Unidus";
-		sprite = "UNIDA1";
-		width = 18;
-		height = 36;
-	}
-	135
-	{
-		title = "Pterabyte Spawner";
-		sprite = "PTERA2A8";
-		width = 16;
-		height = 16;
-		parametertext = "No. Pterabytes";
-	}
-	136
-	{
-		title = "Pyre Fly";
-		sprite = "PYREA0";
-		width = 24;
-		height = 34;
-		flags8text = "[8] Start on fire";
-	}
-	137
-	{
-		title = "Dragonbomber";
-		sprite = "DRABA1";
-		width = 28;
-		height = 48;
-	}
-	105
-	{
-		title = "Jetty-Syn Bomber";
-		sprite = "JETBB1";
-		width = 20;
-		height = 50;
-		flags8text = "[8] Cannot move";
-	}
-	106
-	{
-		title = "Jetty-Syn Gunner";
-		sprite = "JETGB1";
-		width = 20;
-		height = 48;
-		flags8text = "[8] Cannot move";
-	}
-	112
-	{
-		title = "Spincushion";
-		sprite = "SHRPA1";
-		width = 16;
-		height = 24;
-	}
-	114
-	{
-		title = "Snailer";
-		sprite = "SNLRA3A7";
-		width = 24;
-		height = 48;
-	}
-	129
-	{
-		title = "Penguinator";
-		sprite = "PENGA1";
-		width = 24;
-		height = 32;
-	}
-	130
-	{
-		title = "Pophat";
-		sprite = "POPHA1";
-		width = 24;
-		height = 32;
-	}
-	107
-	{
-		title = "Crawla Commander";
-		sprite = "CCOMA1";
-		width = 16;
-		height = 32;
-	}
-	131
-	{
-		title = "Spinbobert";
-		sprite = "SBOBB0";
-		width = 32;
-		height = 32;
-	}
-	132
-	{
-		title = "Cacolantern";
-		sprite = "CACOA0";
-		width = 32;
-		height = 32;
-		flags8text = "[8] Cannot move";
-	}
-	133
-	{
-		title = "Hangster";
-		sprite = "HBATC1";
-		width = 24;
-		height = 24;
-		hangs = 1;
-	}
-	127
-	{
-		title = "Hive Elemental";
-		sprite = "HIVEA0";
-		width = 32;
-		height = 80;
-		parametertext = "No. bees";
-	}
-	128
-	{
-		title = "Bumblebore";
-		sprite = "BUMBA1";
-		width = 16;
-		height = 32;
-	}
-	124
-	{
-		title = "Buggle";
-		sprite = "BBUZA1";
-		width = 20;
-		height = 24;
-	}
-	116
-	{
-		title = "Pointy";
-		sprite = "PNTYA1";
-		width = 8;
-		height = 16;
-	}
-}
-
-bosses
-{
-	color = 8; // Dark_Gray
-	arrow = 1;
-	title = "Bosses";
-
-	200
-	{
-		title = "Egg Mobile";
-		sprite = "EGGMA1";
-		width = 24;
-		height = 76;
-		flags4text = "[4] End level on death";
-		flags8text = "[8] Alternate laser attack";
-	}
-	201
-	{
-		title = "Egg Slimer";
-		sprite = "EGGNA1";
-		width = 24;
-		height = 76;
-		flags4text = "[4] End level on death";
-		flags8text = "[8] Speed up when hit";
-	}
-	202
-	{
-		title = "Sea Egg";
-		sprite = "EGGOA1";
-		width = 32;
-		height = 116;
-		flags4text = "[4] End level on death";
-	}
-	203
-	{
-		title = "Egg Colosseum";
-		sprite = "EGGPA1";
-		width = 24;
-		height = 76;
-		flags4text = "[4] End level on death";
-	}
-	204
-	{
-		title = "Fang";
-		sprite = "FANGA1";
-		width = 24;
-		height = 60;
-		flags1text = "[1] Grayscale mode";
-		flags4text = "[4] End level on death";
-	}
-	206
-	{
-		title = "Brak Eggman (Old)";
-		sprite = "BRAKB1";
-		width = 48;
-		height = 160;
-		flags4text = "[4] End level on death";
-	}
-	207
-	{
-		title = "Metal Sonic (Race)";
-		sprite = "METLI1";
-		width = 16;
-		height = 48;
-		flags1text = "[1] Grayscale mode";
-	}
-	208
-	{
-		title = "Metal Sonic (Battle)";
-		sprite = "METLC1";
-		width = 16;
-		height = 48;
-		flags1text = "[1] Grayscale mode";
-		flags4text = "[4] End level on death";
-	}
-	209
-	{
-		title = "Brak Eggman";
-		sprite = "BRAK01";
-		width = 48;
-		height = 160;
-		flags1text = "[1] No origin-fling death";
-		flags4text = "[4] End level on death";
-		flags8text = "[8] Electric barrier";
-	}
-	290
-	{
-		arrow = 0;
-		title = "Boss Escape Point";
-		width = 8;
-		height = 16;
-		sprite = "internal:eggmanend";
-	}
-	291
-	{
-		arrow = 0;
-		title = "Egg Capsule Center";
-		width = 8;
-		height = 16;
-		sprite = "internal:capsule";
-	}
-	292
-	{
-		arrow = 0;
-		title = "Boss Waypoint";
-		width = 8;
-		height = 16;
-		flags8text = "[8] Sea Egg shooting point";
-		sprite = "internal:eggmanway";
-		angletext = "No. (Sea Egg)";
-		flagsvaluetext = "No. (Brak)";
-		parametertext = "Next";
-	}
-	293
-	{
-		title = "Metal Sonic Gather Point";
-		sprite = "internal:metal";
-		width = 8;
-		height = 16;
-	}
-	294
-	{
-		title = "Fang Waypoint";
-		flags8text = "[8] Center waypoint";
-		sprite = "internal:eggmanway";
-		width = 8;
-		height = 16;
-	}
-}
-
-rings
-{
-	color = 14; // Yellow
-	title = "Rings and Weapon Panels";
-	width = 24;
-	height = 24;
-	flags8height = 24;
-	flags8text = "[8] Float";
-	sprite = "RINGA0";
-
-	300
-	{
-		title = "Ring";
-		sprite = "RINGA0";
-		width = 16;
-	}
-	301
-	{
-		title = "Bounce Ring";
-		sprite = "internal:RNGBA0";
-	}
-	302
-	{
-		title = "Rail Ring";
-		sprite = "internal:RNGRA0";
-	}
-	303
-	{
-		title = "Infinity Ring";
-		sprite = "internal:RNGIA0";
-	}
-	304
-	{
-		title = "Automatic Ring";
-		sprite = "internal:RNGAA0";
-	}
-	305
-	{
-		title = "Explosion Ring";
-		sprite = "internal:RNGEA0";
-	}
-	306
-	{
-		title = "Scatter Ring";
-		sprite = "internal:RNGSA0";
-	}
-	307
-	{
-		title = "Grenade Ring";
-		sprite = "internal:RNGGA0";
-	}
-	308
-	{
-		title = "CTF Team Ring (Red)";
-		sprite = "internal:RRNGA0";
-		width = 16;
-	}
-	309
-	{
-		title = "CTF Team Ring (Blue)";
-		sprite = "internal:BRNGA0";
-		width = 16;
-	}
-	330
-	{
-		title = "Bounce Ring Panel";
-		sprite = "internal:PIKBA0";
-	}
-	331
-	{
-		title = "Rail Ring Panel";
-		sprite = "internal:PIKRA0";
-	}
-	332
-	{
-		title = "Automatic Ring Panel";
-		sprite = "internal:PIKAA0";
-	}
-	333
-	{
-		title = "Explosion Ring Panel";
-		sprite = "internal:PIKEA0";
-	}
-	334
-	{
-		title = "Scatter Ring Panel";
-		sprite = "internal:PIKSA0";
-	}
-	335
-	{
-		title = "Grenade Ring Panel";
-		sprite = "internal:PIKGA0";
-	}
-}
-
-collectibles
-{
-	color = 10; // Light_Green
-	title = "Other Collectibles";
-	width = 16;
-	height = 32;
-	sort = 1;
-	sprite = "CEMGA0";
-
-	310
-	{
-		title = "CTF Red Flag";
-		sprite = "RFLGA0";
-		width = 24;
-		height = 64;
-	}
-	311
-	{
-		title = "CTF Blue Flag";
-		sprite = "BFLGA0";
-		width = 24;
-		height = 64;
-	}
-	312
-	{
-		title = "Emerald Token";
-		sprite = "TOKEA0";
-		width = 16;
-		height = 32;
-		flags8height = 24;
-		flags8text = "[8] Float";
-	}
-	313
-	{
-		title = "Chaos Emerald 1 (Green)";
-		sprite = "CEMGA0";
-	}
-	314
-	{
-		title = "Chaos Emerald 2 (Purple)";
-		sprite = "CEMGB0";
-	}
-	315
-	{
-		title = "Chaos Emerald 3 (Blue)";
-		sprite = "CEMGC0";
-	}
-	316
-	{
-		title = "Chaos Emerald 4 (Cyan)";
-		sprite = "CEMGD0";
-	}
-	317
-	{
-		title = "Chaos Emerald 5 (Orange)";
-		sprite = "CEMGE0";
-	}
-	318
-	{
-		title = "Chaos Emerald 6 (Red)";
-		sprite = "CEMGF0";
-	}
-	319
-	{
-		title = "Chaos Emerald 7 (Gray)";
-		sprite = "CEMGG0";
-	}
-	320
-	{
-		title = "Emerald Hunt Location";
-		sprite = "SHRDA0";
-	}
-	321
-	{
-		title = "Match Chaos Emerald Spawn";
-		sprite = "CEMGA0";
-		flags8height = 24;
-		flags8text = "[8] Float";
-	}
-	322
-	{
-		title = "Emblem";
-		sprite = "EMBMA0";
-		width = 16;
-		height = 30;
-		flags8height = 24;
-		flags8text = "[8] Float";
-		angletext = "Tag";
-	}
-}
-
-boxes
-{
-	color = 7; // Gray
-	blocking = 2;
-	title = "Monitors";
-	width = 18;
-	height = 40;
-	flags1text = "[1] Run Linedef Executor on pop";
-	flags4text = "[4] Random (Strong)";
-	flags8text = "[8] Random (Weak)";
-
-	400
-	{
-		title = "Super Ring (10 Rings)";
-		sprite = "TVRIA0";
-	}
-	401
-	{
-		title = "Pity Shield";
-		sprite = "TVPIA0";
-	}
-	402
-	{
-		title = "Attraction Shield";
-		sprite = "TVATA0";
-	}
-	403
-	{
-		title = "Force Shield";
-		sprite = "TVFOA0";
-	}
-	404
-	{
-		title = "Armageddon Shield";
-		sprite = "TVARA0";
-	}
-	405
-	{
-		title = "Whirlwind Shield";
-		sprite = "TVWWA0";
-	}
-	406
-	{
-		title = "Elemental Shield";
-		sprite = "TVELA0";
-	}
-	407
-	{
-		title = "Super Sneakers";
-		sprite = "TVSSA0";
-	}
-	408
-	{
-		title = "Invincibility";
-		sprite = "TVIVA0";
-	}
-	409
-	{
-		title = "Extra Life";
-		sprite = "TV1UA0";
-		flags4text = "[4] Random (Strong) / 10k points";
-		flags8text = "[8] Random (Weak) / 10k points";
-	}
-	410
-	{
-		title = "Eggman";
-		sprite = "TVEGA0";
-		flags4text = "[4] Special";
-		flags8text = "[8] Ambush";
-	}
-	411
-	{
-		title = "Teleporter";
-		sprite = "TVMXA0";
-	}
-	413
-	{
-		title = "Gravity Boots";
-		sprite = "TVGVA0";
-		flags4text = "[4] Special";
-		flags8text = "[8] Ambush";
-	}
-	414
-	{
-		title = "CTF Team Ring Monitor (Red)";
-		sprite = "TRRIA0";
-		flags4text = "[4] Special";
-		flags8text = "[8] Ambush";
-	}
-	415
-	{
-		title = "CTF Team Ring Monitor (Blue)";
-		sprite = "TBRIA0";
-		flags4text = "[4] Special";
-		flags8text = "[8] Ambush";
-	}
-	416
-	{
-		title = "Recycler";
-		sprite = "TVRCA0";
-	}
-	418
-	{
-		title = "Score (1,000 Points)";
-		sprite = "TV1KA0";
-		flags4text = "[4] Special";
-		flags8text = "[8] Ambush";
-	}
-	419
-	{
-		title = "Score (10,000 Points)";
-		sprite = "TVTKA0";
-		flags4text = "[4] Special";
-		flags8text = "[8] Ambush";
-	}
-	420
-	{
-		title = "Flame Shield";
-		sprite = "TVFLA0";
-	}
-	421
-	{
-		title = "Water Shield";
-		sprite = "TVBBA0";
-	}
-	422
-	{
-		title = "Lightning Shield";
-		sprite = "TVZPA0";
-	}
-}
-
-boxes2
-{
-	color = 18; // Gold
-	blocking = 2;
-	title = "Monitors (Respawning)";
-	width = 20;
-	height = 44;
-	flags1text = "[1] Run Linedef Executor on pop";
-
-	431
-	{
-		title = "Pity Shield (Respawn)";
-		sprite = "TVPIB0";
-	}
-	432
-	{
-		title = "Attraction Shield (Respawn)";
-		sprite = "TVATB0";
-	}
-	433
-	{
-		title = "Force Shield (Respawn)";
-		sprite = "TVFOB0";
-	}
-	434
-	{
-		title = "Armageddon Shield (Respawn)";
-		sprite = "TVARB0";
-	}
-	435
-	{
-		title = "Whirlwind Shield (Respawn)";
-		sprite = "TVWWB0";
-	}
-	436
-	{
-		title = "Elemental Shield (Respawn)";
-		sprite = "TVELB0";
-	}
-	437
-	{
-		title = "Super Sneakers (Respawn)";
-		sprite = "TVSSB0";
-	}
-	438
-	{
-		title = "Invincibility (Respawn)";
-		sprite = "TVIVB0";
-	}
-	440
-	{
-		title = "Eggman (Respawn)";
-		sprite = "TVEGB0";
-	}
-	443
-	{
-		title = "Gravity Boots (Respawn)";
-		sprite = "TVGVB0";
-	}
-	450
-	{
-		title = "Flame Shield (Respawn)";
-		sprite = "TVFLB0";
-	}
-	451
-	{
-		title = "Water Shield (Respawn)";
-		sprite = "TVBBB0";
-	}
-	452
-	{
-		title = "Lightning Shield (Respawn)";
-		sprite = "TVZPB0";
-	}
-}
-
-generic
-{
-	color = 11; // Light_Cyan
-	title = "Generic Items & Hazards";
-
-	500
-	{
-		title = "Air Bubble Patch";
-		sprite = "BUBLE0";
-		width = 8;
-		height = 16;
-		flags8text = "[8] No distance check";
-	}
-	501
-	{
-		title = "Signpost";
-		sprite = "SIGND0";
-		width = 8;
-		height = 32;
-	}
-	502
-	{
-		arrow = 1;
-		title = "Star Post";
-		sprite = "STPTA0M0";
-		width = 64;
-		height = 128;
-		angletext = "Angle/Order";
-	}
-	520
-	{
-		title = "Bomb Sphere";
-		sprite = "SPHRD0";
-		width = 16;
-		height = 24;
-		flags8height = 24;
-		flags8text = "[8] Float";
-		unflippable = true;
-	}
-	521
-	{
-		title = "Spikeball";
-		sprite = "SPIKA0";
-		width = 12;
-		height = 8;
-		flags8height = 24;
-		flags8text = "[8] Float";
-	}
-	522
-	{
-		title = "Wall Spike";
-		sprite = "WSPKALAR";
-		width = 16;
-		height = 14;
-		flags1text = "[1] Start retracted";
-		flags4text = "[4] Retractable";
-		flags8text = "[8] Intangible";
-		parametertext = "Initial delay";
-	}
-	523
-	{
-		title = "Spike";
-		sprite = "USPKA0";
-		width = 8;
-		height = 32;
-		flags1text = "[1] Start retracted";
-		flags4text = "[4] Retractable";
-		flags8text = "[8] Intangible";
-		angletext = "Retraction interval";
-		parametertext = "Initial delay";
-	}
-	1130
-	{
-		title = "Small Mace";
-		sprite = "SMCEA0";
-		width = 17;
-		height = 34;
-	}
-	1131
-	{
-		title = "Big Mace";
-		sprite = "BMCEA0";
-		width = 34;
-		height = 68;
-	}
-	1136
-	{
-		title = "Small Fireball";
-		sprite = "SFBRA0";
-		width = 17;
-		height = 34;
-	}
-	1137
-	{
-		title = "Large Fireball";
-		sprite = "BFBRA0";
-		width = 34;
-		height = 68;
-	}
-}
-
-springs
-{
-	color = 12; // Light_Red
-	title = "Springs and Fans";
-	width = 20;
-	height = 16;
-	sprite = "RSPRD2";
-
-	540
-	{
-		title = "Fan";
-		sprite = "FANSA0D0";
-		width = 16;
-		height = 8;
-		flags4text = "[4] Invisible";
-		flags8text = "[8] No distance check";
-		angletext = "Lift height";
-	}
-	541
-	{
-		title = "Gas Jet";
-		sprite = "STEMD0";
-		flags8text = "[8] No sounds";
-		width = 32;
-	}
-	542
-	{
-		title = "Bumper";
-		sprite = "BUMPA0";
-		width = 32;
-		height = 64;
-		angletext = "Strength";
-	}
-	543
-	{
-		title = "Balloon";
-		sprite = "BLONA0";
-		width = 32;
-		height = 64;
-		flags8text = "[8] Respawn";
-		angletext = "Color";
-	}
-	550
-	{
-		title = "Yellow Spring";
-		sprite = "SPRYA0";
-	}
-	551
-	{
-		title = "Red Spring";
-		sprite = "SPRRA0";
-	}
-	552
-	{
-		title = "Blue Spring";
-		sprite = "SPRBA0";
-	}
-	555
-	{
-		arrow = 1;
-		title = "Diagonal Yellow Spring";
-		sprite = "YSPRD2";
-		width = 16;
-		flags4text = "[4] Ignore gravity";
-		flags8text = "[8] Rotate 22.5° CCW";
-	}
-	556
-	{
-		arrow = 1;
-		title = "Diagonal Red Spring";
-		sprite = "RSPRD2";
-		width = 16;
-		flags4text = "[4] Ignore gravity";
-		flags8text = "[8] Rotate 22.5° CCW";
-	}
-	557
-	{
-		arrow = 1;
-		title = "Diagonal Blue Spring";
-		sprite = "BSPRD2";
-		width = 16;
-		flags4text = "[4] Ignore gravity";
-		flags8text = "[8] Rotate 22.5° CCW";
-	}
-	558
-	{
-		arrow = 1;
-		title = "Horizontal Yellow Spring";
-		sprite = "SSWYD2D8";
-		flags8height = 16;
-		flags8text = "[8] Float";
-		width = 16;
-		height = 32;
-	}
-	559
-	{
-		arrow = 1;
-		title = "Horizontal Red Spring";
-		sprite = "SSWRD2D8";
-		flags8height = 16;
-		flags8text = "[8] Float";
-		width = 16;
-		height = 32;
-	}
-	560
-	{
-		arrow = 1;
-		title = "Horizontal Blue Spring";
-		sprite = "SSWBD2D8";
-		flags8height = 16;
-		flags8text = "[8] Float";
-		width = 16;
-		height = 32;
-	}
-	1134
-	{
-		title = "Yellow Spring Ball";
-		sprite = "YSPBA0";
-		width = 17;
-		height = 34;
-	}
-	1135
-	{
-		title = "Red Spring Ball";
-		sprite = "RSPBA0";
-		width = 17;
-		height = 34;
-	}
-	544
-	{
-		arrow = 1;
-		title = "Yellow Boost Panel";
-		sprite = "BSTYA0";
-		flags8text = "[8] Force spin";
-		width = 28;
-		height = 2;
-	}
-	545
-	{
-		arrow = 1;
-		title = "Red Boost Panel";
-		sprite = "BSTRA0";
-		flags8text = "[8] Force spin";
-		width = 28;
-		height = 2;
-	}
-}
-
-patterns
-{
-	color = 5; // Magenta
-	arrow = 1;
-	title = "Special Placement Patterns";
-	width = 16;
-	height = 384;
-	sprite = "RINGA0";
-
-	600
-	{
-		arrow = 0;
-		title = "5 Vertical Rings (Yellow Spring)";
-		sprite = "RINGA0";
-	}
-	601
-	{
-		arrow = 0;
-		title = "5 Vertical Rings (Red Spring)";
-		sprite = "RINGA0";
-		height = 1024;
-	}
-	602
-	{
-		title = "5 Diagonal Rings (Yellow Spring)";
-		sprite = "RINGA0";
-		height = 32;
-	}
-	603
-	{
-		title = "10 Diagonal Rings (Red Spring)";
-		sprite = "RINGA0";
-		height = 32;
-	}
-	604
-	{
-		title = "Circle of Rings";
-		sprite = "RINGA0";
-		width = 96;
-		height = 192;
-		unflippable = true;
-		centerHitbox = true;
-	}
-	605
-	{
-		title = "Circle of Rings (Big)";
-		sprite = "RINGA0";
-		width = 192;
-		unflippable = true;
-		centerHitbox = true;
-	}
-	606
-	{
-		title = "Circle of Blue Spheres";
-		sprite = "SPHRA0";
-		width = 96;
-		height = 192;
-		unflippable = true;
-		centerHitbox = true;
-	}
-	607
-	{
-		title = "Circle of Blue Spheres (Big)";
-		sprite = "SPHRA0";
-		width = 192;
-		unflippable = true;
-		centerHitbox = true;
-	}
-	608
-	{
-		title = "Circle of Rings and Spheres";
-		sprite = "SPHRA0";
-		width = 96;
-		height = 192;
-		unflippable = true;
-		centerHitbox = true;
-	}
-	609
-	{
-		title = "Circle of Rings and Spheres (Big)";
-		sprite = "SPHRA0";
-		width = 192;
-		unflippable = true;
-		centerHitbox = true;
-	}
-}
-
-invisible
-{
-	color = 15; // White
-	title = "Misc. Invisible";
-	width = 0;
-	height = 0;
-	sprite = "UNKNA0";
-	sort = 1;
-	fixedsize = true;
-	blocking = 0;
-
-	700
-	{
-		title = "Water Ambience A (Large)";
-		sprite = "internal:ambiance";
-	}
-
-	701
-	{
-		title = "Water Ambience B (Large)";
-		sprite = "internal:ambiance";
-	}
-
-	702
-	{
-		title = "Water Ambience C (Medium)";
-		sprite = "internal:ambiance";
-	}
-
-	703
-	{
-		title = "Water Ambience D (Medium)";
-		sprite = "internal:ambiance";
-	}
-
-	704
-	{
-		title = "Water Ambience E (Small)";
-		sprite = "internal:ambiance";
-	}
-
-	705
-	{
-		title = "Water Ambience F (Small)";
-		sprite = "internal:ambiance";
-	}
-
-	706
-	{
-		title = "Water Ambience G (Extra Large)";
-		sprite = "internal:ambiance";
-	}
-
-	707
-	{
-		title = "Water Ambience H (Extra Large)";
-		sprite = "internal:ambiance";
-	}
-
-	708
-	{
-		title = "Disco Ambience";
-		sprite = "internal:ambiance";
-	}
-
-	709
-	{
-		title = "Volcano Ambience";
-		sprite = "internal:ambiance";
-	}
-
-	710
-	{
-		title = "Machine Ambience";
-		sprite = "internal:ambiance";
-	}
-
-	750
-	{
-		title = "Slope Vertex";
-		sprite = "internal:vertexslope";
-		angletext = "Tag";
-	}
-
-	751
-	{
-		arrow = 1;
-		title = "Teleport Destination";
-		sprite = "internal:tele";
-	}
-
-	752
-	{
-		arrow = 1;
-		title = "Alternate View Point";
-		sprite = "internal:view";
-	}
-
-	753
-	{
-		title = "Zoom Tube Waypoint";
-		sprite = "internal:zoom";
-		angletext = "Order";
-	}
-
-	754
-	{
-		title = "Push Point";
-		flags4text = "[4] Fades using XY";
-		flags8text = "[8] Push using XYZ";
-		sprite = "GWLGA0";
-		angletext = "Radius";
-	}
-	755
-	{
-		title = "Pull Point";
-		flags4text = "[4] Fades using XY";
-		flags8text = "[8] Pull using XYZ";
-		sprite = "GWLRA0";
-		angletext = "Radius";
-	}
-	756
-	{
-		title = "Blast Linedef Executor";
-		sprite = "TOADA0";
-		width = 32;
-		height = 16;
-	}
-	757
-	{
-		title = "Fan Particle Generator";
-		sprite = "PRTLA0";
-		width = 8;
-		height = 16;
-		angletext = "Tag";
-	}
-	758
-	{
-		title = "Object Angle Anchor";
-		sprite = "internal:view";
-	}
-	760
-	{
-		title = "PolyObject Anchor";
-		sprite = "internal:polyanchor";
-		angletext = "ID";
-	}
-
-	761
-	{
-		title = "PolyObject Spawn Point";
-		sprite = "internal:polycenter";
-		angletext = "ID";
-	}
-
-	762
-	{
-		title = "PolyObject Spawn Point (Crush)";
-		sprite = "internal:polycentercrush";
-		angletext = "ID";
-	}
-	780
-	{
-		title = "Skybox View Point";
-		sprite = "internal:skyb";
-		flags4text = "[4] In-map centerpoint";
-		parametertext = "ID";
-	}
-}
-
-greenflower
-{
-	color = 10; // Green
-	title = "Greenflower";
-
-	800
-	{
-		title = "GFZ Flower";
-		sprite = "FWR1A0";
-		width = 16;
-		height = 40;
-	}
-	801
-	{
-		title = "Sunflower";
-		sprite = "FWR2A0";
-		width = 16;
-		height = 96;
-	}
-	802
-	{
-		title = "Budding Flower";
-		sprite = "FWR3A0";
-		width = 8;
-		height = 32;
-	}
-	803
-	{
-		title = "Blueberry Bush";
-		sprite = "BUS3A0";
-		width = 16;
-		height = 32;
-	}
-	804
-	{
-		title = "Berry Bush";
-		sprite = "BUS1A0";
-		width = 16;
-		height = 32;
-	}
-	805
-	{
-		title = "Bush";
-		sprite = "BUS2A0";
-		width = 16;
-		height = 32;
-	}
-	806
-	{
-		title = "GFZ Tree";
-		sprite = "TRE1A0";
-		width = 20;
-		height = 128;
-	}
-	807
-	{
-		title = "GFZ Berry Tree";
-		sprite = "TRE1B0";
-		width = 20;
-		height = 128;
-	}
-	808
-	{
-		title = "GFZ Cherry Tree";
-		sprite = "TRE1C0";
-		width = 20;
-		height = 128;
-	}
-	809
-	{
-		title = "Checkered Tree";
-		sprite = "TRE2A0";
-		width = 20;
-		height = 200;
-	}
-	810
-	{
-		title = "Checkered Tree (Sunset)";
-		sprite = "TRE2B0";
-		width = 20;
-		height = 200;
-	}
-	811
-	{
-		title = "Polygon Tree";
-		sprite = "TRE4A0";
-		width = 20;
-		height = 200;
-	}
-	812
-	{
-		title = "Bush Tree";
-		sprite = "TRE5A0";
-		width = 20;
-		height = 200;
-	}
-	813
-	{
-		title = "Red Bush Tree";
-		sprite = "TRE5B0";
-		width = 20;
-		height = 200;
-	}
-}
-
-technohill
-{
-	color = 10; // Green
-	title = "Techno Hill";
-
-	900
-	{
-		title = "THZ Steam Flower";
-		sprite = "THZPA0";
-		width = 8;
-		height = 32;
-	}
-	901
-	{
-		title = "Alarm";
-		sprite = "ALRMA0";
-		width = 8;
-		height = 16;
-		hangs = 1;
-	}
-	902
-	{
-		title = "THZ Spin Flower (Red)";
-		sprite = "FWR5A0";
-		width = 16;
-		height = 64;
-	}
-	903
-	{
-		title = "THZ Spin Flower (Yellow)";
-		sprite = "FWR6A0";
-		width = 16;
-		height = 64;
-	}
-	904
-	{
-		arrow = 1;
-		title = "Whistlebush";
-		sprite = "THZTA0";
-		width = 16;
-		height = 64;
-	}
-}
-
-deepsea
-{
-	color = 10; // Green
-	title = "Deep Sea";
-
-	1000
-	{
-		arrow = 1;
-		blocking = 2;
-		title = "Gargoyle";
-		sprite = "GARGA1";
-		width = 16;
-		height = 40;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1009
-	{
-		arrow = 1;
-		blocking = 2;
-		title = "Gargoyle (Big)";
-		sprite = "GARGB1";
-		width = 32;
-		height = 80;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1001
-	{
-		title = "Seaweed";
-		sprite = "SEWEA0";
-		width = 24;
-		height = 56;
-	}
-	1002
-	{
-		title = "Dripping Water";
-		sprite = "DRIPD0";
-		width = 8;
-		height = 16;
-		hangs = 1;
-		angletext = "Dripping interval";
-	}
-	1003
-	{
-		title = "Coral (Green)";
-		sprite = "CORLA0";
-		width = 29;
-		height = 40;
-	}
-	1004
-	{
-		title = "Coral (Red)";
-		sprite = "CORLB0";
-		width = 30;
-		height = 53;
-	}
-	1005
-	{
-		title = "Coral (Orange)";
-		sprite = "CORLC0";
-		width = 28;
-		height = 41;
-	}
-	1006
-	{
-		title = "Blue Crystal";
-		sprite = "BCRYA1";
-		width = 8;
-		height = 16;
-	}
-	1007
-	{
-		title = "Kelp";
-		sprite = "KELPA0";
-		width = 16;
-		height = 292;
-		flags4text = "[4] Double size";
-	}
-	1008
-	{
-		title = "Stalagmite (DSZ1)";
-		sprite = "DSTGA0";
-		width = 8;
-		height = 116;
-		flags4text = "[4] Double size";
-	}
-	1010
-	{
-		arrow = 1;
-		title = "Light Beam";
-		sprite = "LIBEARAL";
-		width = 16;
-		height = 16;
-	}
-	1011
-	{
-		title = "Stalagmite (DSZ2)";
-		sprite = "DSTGA0";
-		width = 8;
-		height = 116;
-		flags4text = "[4] Double size";
-	}
-	1012
-	{
-		arrow = 1;
-		title = "Big Floating Mine";
-		width = 28;
-		height = 56;
-		sprite = "BMNEA1";
-	}
-	1013
-	{
-		title = "Animated Kelp";
-		sprite = "ALGAA0";
-		width = 48;
-		height = 120;
-	}
-	1014
-	{
-		title = "Large Coral (Brown)";
-		sprite = "CORLD0";
-		width = 56;
-		height = 112;
-	}
-	1015
-	{
-		title = "Large Coral (Beige)";
-		sprite = "CORLE0";
-		width = 56;
-		height = 112;
-	}
-}
-
-castleeggman
-{
-	color = 10; // Green
-	title = "Castle Eggman";
-
-	1100
-	{
-		title = "Chain (Decorative)";
-		sprite = "CHANA0";
-		width = 4;
-		height = 128;
-		hangs = 1;
-	}
-	1101
-	{
-		title = "Torch";
-		sprite = "FLAMA0E0";
-		width = 8;
-		height = 32;
-		flags1text = "[1] Add corona";
-	}
-	1102
-	{
-		arrow = 1;
-		blocking = 2;
-		title = "Eggman Statue";
-		sprite = "ESTAA1";
-		width = 32;
-		height = 240;
-		flags1text = "[1] Solid gold";
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1103
-	{
-		title = "CEZ Flower";
-		sprite = "FWR4A0";
-		width = 16;
-		height = 40;
-	}
-	1104
-	{
-		title = "Mace Spawnpoint";
-		sprite = "SMCEA0";
-		width = 17;
-		height = 34;
-		flags4text = "[4] No sounds";
-		flags8text = "[8] Double size";
-		angletext = "Tag";
-	}
-	1105
-	{
-		title = "Chain with Maces Spawnpoint";
-		sprite = "SMCEA0";
-		width = 17;
-		height = 34;
-		flags4text = "[4] No sounds";
-		flags8text = "[8] Double size";
-		angletext = "Tag";
-	}
-	1106
-	{
-		title = "Chained Spring Spawnpoint";
-		sprite = "YSPBA0";
-		width = 17;
-		height = 34;
-		flags4text = "[4] No sounds";
-		flags8text = "[8] Red spring";
-		angletext = "Tag";
-	}
-	1107
-	{
-		title = "Chain Spawnpoint";
-		sprite = "BMCHA0";
-		width = 17;
-		height = 34;
-		flags8text = "[8] Double size";
-		angletext = "Tag";
-	}
-	1108
-	{
-		arrow = 1;
-		title = "Hidden Chain Spawnpoint";
-		sprite = "internal:chain3";
-		width = 17;
-		height = 34;
-		flags8text = "[8] Double size";
-	}
-	1109
-	{
-		title = "Firebar Spawnpoint";
-		sprite = "BFBRA0";
-		width = 17;
-		height = 34;
-		flags4text = "[4] No sounds";
-		flags8text = "[8] Double size";
-		angletext = "Tag";
-	}
-	1110
-	{
-		title = "Custom Mace Spawnpoint";
-		sprite = "SMCEA0";
-		width = 17;
-		height = 34;
-		flags4text = "[4] No sounds";
-		angletext = "Tag";
-	}
-	1111
-	{
-		arrow = 1;
-		blocking = 2;
-		title = "Crawla Statue";
-		sprite = "CSTAA1";
-		width = 16;
-		height = 40;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1112
-	{
-		arrow = 1;
-		blocking = 2;
-		title = "Lance-a-Bot Statue";
-		sprite = "CBBSA1";
-		width = 32;
-		height = 72;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1114
-	{
-		title = "Pine Tree";
-		sprite = "PINEA0";
-		width = 16;
-		height = 628;
-	}
-	1115
-	{
-		title = "CEZ Shrub (Small)";
-		sprite = "CEZBA0";
-		width = 16;
-		height = 24;
-	}
-	1116
-	{
-		title = "CEZ Shrub (Large)";
-		sprite = "CEZBB0";
-		width = 32;
-		height = 48;
-	}
-	1117
-	{
-		arrow = 1;
-		title = "Pole Banner (Red)";
-		sprite = "BANRA0";
-		width = 40;
-		height = 224;
-	}
-	1118
-	{
-		arrow = 1;
-		title = "Pole Banner (Blue)";
-		sprite = "BANRA0";
-		width = 40;
-		height = 224;
-	}
-	1119
-	{
-		title = "Candle";
-		sprite = "CNDLA0";
-		width = 8;
-		height = 48;
-		flags1text = "[1] Add corona";
-	}
-	1120
-	{
-		title = "Candle Pricket";
-		sprite = "CNDLB0";
-		width = 8;
-		height = 176;
-		flags1text = "[1] Add corona";
-	}
-	1121
-	{
-		title = "Flame Holder";
-		sprite = "FLMHA0";
-		width = 24;
-		height = 80;
-		flags1text = "[1] Add corona";
-		flags4text = "[4] No flame";
-	}
-	1122
-	{
-		title = "Fire Torch";
-		sprite = "CTRCA0";
-		width = 16;
-		height = 80;
-	}
-	1123
-	{
-		title = "Cannonball Launcher";
-		sprite = "internal:cannonball";
-		width = 8;
-		height = 16;
-	}
-	1124
-	{
-		blocking = 2;
-		title = "Cannonball";
-		sprite = "CBLLA0";
-		width = 20;
-		height = 40;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1125
-	{
-		title = "Brambles";
-		sprite = "CABRALAR";
-		width = 48;
-		height = 32;
-	}
-	1126
-	{
-		title = "Invisible Lockon Object";
-		sprite = "LCKNC0";
-		width = 16;
-		height = 32;
-	}
-	1127
-	{
-		title = "Spectator Eggrobo";
-		sprite = "EGR1A1";
-		width = 20;
-		height = 72;
-	}
-	1128
-	{
-		arrow = 1;
-		title = "Waving Flag (Red)";
-		sprite = "CFLGA0";
-		width = 8;
-		height = 208;
-	}
-	1129
-	{
-		arrow = 1;
-		title = "Waving Flag (Blue)";
-		sprite = "CFLGA0";
-		width = 8;
-		height = 208;
-	}
-}
-
-aridcanyon
-{
-	color = 10; // Green
-	title = "Arid Canyon";
-
-	1200
-	{
-		title = "Tumbleweed (Big)";
-		sprite = "BTBLA0";
-		width = 24;
-		height = 48;
-		flags8text = "[8] Moves perpetually";
-	}
-	1201
-	{
-		title = "Tumbleweed (Small)";
-		sprite = "STBLA0";
-		width = 12;
-		height = 24;
-		flags8text = "[8] Moves perpetually";
-	}
-	1202
-	{
-		arrow = 1;
-		title = "Rock Spawner";
-		sprite = "ROIAA0";
-		width = 8;
-		height = 16;
-		angletext = "Tag";
-	}
-	1203
-	{
-		title = "Tiny Red Flower Cactus";
-		sprite = "CACTA0";
-		width = 13;
-		height = 24;
-	}
-	1204
-	{
-		title = "Small Red Flower Cactus";
-		sprite = "CACTB0";
-		width = 15;
-		height = 52;
-	}
-	1205
-	{
-		title = "Tiny Blue Flower Cactus";
-		sprite = "CACTC0";
-		width = 13;
-		height = 24;
-	}
-	1206
-	{
-		title = "Small Blue Flower Cactus";
-		sprite = "CACTD0";
-		width = 15;
-		height = 52;
-	}
-	1207
-	{
-		title = "Prickly Pear";
-		sprite = "CACTE0";
-		width = 32;
-		height = 96;
-	}
-	1208
-	{
-		title = "Barrel Cactus";
-		sprite = "CACTF0";
-		width = 20;
-		height = 128;
-	}
-	1209
-	{
-		title = "Tall Barrel Cactus";
-		sprite = "CACTG0";
-		width = 24;
-		height = 224;
-	}
-	1210
-	{
-		title = "Armed Cactus";
-		sprite = "CACTH0";
-		width = 24;
-		height = 256;
-	}
-	1211
-	{
-		title = "Ball Cactus";
-		sprite = "CACTI0";
-		width = 48;
-		height = 96;
-	}
-	1212
-	{
-		title = "Caution Sign";
-		sprite = "WWSGAR";
-		width = 22;
-		height = 64;
-	}
-	1213
-	{
-		title = "Cacti Sign";
-		sprite = "WWS2AR";
-		width = 22;
-		height = 64;
-	}
-	1214
-	{
-		title = "Sharp Turn Sign";
-		sprite = "WWS3ALAR";
-		width = 16;
-		height = 192;
-	}
-	1215
-	{
-		title = "Mine Oil Lamp";
-		sprite = "OILLA0";
-		width = 22;
-		height = 64;
-		hangs = 1;
-	}
-	1216
-	{
-		title = "TNT Barrel";
-		sprite = "BARRA1";
-		width = 24;
-		height = 63;
-	}
-	1217
-	{
-		title = "TNT Proximity Shell";
-		sprite = "REMTA0";
-		width = 64;
-		height = 40;
-	}
-	1218
-	{
-		title = "Dust Devil";
-		sprite = "TAZDCR";
-		width = 80;
-		height = 416;
-	}
-	1219
-	{
-		title = "Minecart Spawner";
-		sprite = "MCRTCLFR";
-		width = 22;
-		height = 32;
-	}
-	1220
-	{
-		title = "Minecart Stopper";
-		sprite = "MCRTIR";
-		width = 32;
-		height = 32;
-	}
-	1221
-	{
-		title = "Minecart Saloon Door";
-		sprite = "SALDARAL";
-		width = 96;
-		height = 160;
-		flags8text = "[8] Allow non-minecart players";
-	}
-	1222
-	{
-		title = "Train Cameo Spawner";
-		sprite = "TRAEBRBL";
-		width = 28;
-		height = 32;
-	}
-	1223
-	{
-		title = "Train Dust Spawner";
-		sprite = "ADSTA0";
-		width = 4;
-		height = 4;
-	}
-	1224
-	{
-		title = "Train Steam Spawner";
-		sprite = "STEAA0";
-		width = 4;
-		height = 4;
-	}
-	1229
-	{
-		title = "Minecart Switch Point";
-		sprite = "internal:zoom";
-		width = 8;
-		height = 16;
-		flags8text = "[8] Enable switching";
-	}
-	1230
-	{
-		title = "Tiny Cactus";
-		sprite = "CACTJ0";
-		width = 13;
-		height = 28;
-	}
-	1231
-	{
-		title = "Small Cactus";
-		sprite = "CACTK0";
-		width = 15;
-		height = 60;
-	}
-}
-
-redvolcano
-{
-	color = 10; // Green
-	title = "Red Volcano";
-
-	1300
-	{
-		arrow = 1;
-		title = "Flame Jet (Horizontal)";
-		sprite = "internal:flameh";
-		width = 16;
-		height = 40;
-		flags8text = "[8] Waves vertically";
-		angletext = "On/Off time";
-		parametertext = "Strength";
-	}
-	1301
-	{
-		title = "Flame Jet (Vertical)";
-		sprite = "internal:flamev";
-		width = 16;
-		height = 40;
-		flags8text = "[8] Shoot downwards";
-		angletext = "On/Off time";
-		parametertext = "Strength";
-	}
-	1302
-	{
-		title = "Spinning Flame Jet (Counter-Clockwise)";
-		sprite = "internal:flame2";
-		width = 16;
-		height = 24;
-	}
-	1303
-	{
-		title = "Spinning Flame Jet (Clockwise)";
-		sprite = "internal:flame1";
-		width = 16;
-		height = 24;
-	}
-	1304
-	{
-		title = "Lavafall";
-		sprite = "LFALF0";
-		width = 30;
-		height = 32;
-		angletext = "Initial delay";
-		flags8text = "[8] Double size";
-	}
-	1305
-	{
-		title = "Rollout Rock";
-		sprite = "PUMIA1A5";
-		width = 30;
-		height = 60;
-		flags8text = "[8] Non-buoyant";
-	}
-	1306
-	{
-		title = "Big Fern";
-		sprite = "JPLAB0";
-		width = 32;
-		height = 48;
-	}
-	1307
-	{
-		title = "Jungle Palm";
-		sprite = "JPLAC0";
-		width = 32;
-		height = 48;
-	}
-	1308
-	{
-		title = "Torch Flower";
-		sprite = "TFLOA0";
-		width = 14;
-		height = 110;
-	}
-	1309
-	{
-		title = "RVZ1 Wall Vine (Long)";
-		sprite = "WVINALAR";
-		width = 1;
-		height = 288;
-	}
-	1310
-	{
-		title = "RVZ1 Wall Vine (Short)";
-		sprite = "WVINBLBR";
-		width = 1;
-		height = 288;
-	}
-}
-
-botanicserenity
-{
-	color = 10; // Green
-	title = "Botanic Serenity";
-	width = 16;
-	height = 32;
-	sprite = "BSZ1A0";
-	1400
-	{
-		title = "Tall Flower (Red)";
-		sprite = "BSZ1A0";
-	}
-	1401
-	{
-		title = "Tall Flower (Purple)";
-		sprite = "BSZ1B0";
-	}
-	1402
-	{
-		title = "Tall Flower (Blue)";
-		sprite = "BSZ1C0";
-	}
-	1403
-	{
-		title = "Tall Flower (Cyan)";
-		sprite = "BSZ1D0";
-	}
-	1404
-	{
-		title = "Tall Flower (Yellow)";
-		sprite = "BSZ1E0";
-	}
-	1405
-	{
-		title = "Tall Flower (Orange)";
-		sprite = "BSZ1F0";
-	}
-	1410
-	{
-		title = "Medium Flower (Red)";
-		sprite = "BSZ2A0";
-	}
-	1411
-	{
-		title = "Medium Flower (Purple)";
-		sprite = "BSZ2B0";
-	}
-	1412
-	{
-		title = "Medium Flower (Blue)";
-		sprite = "BSZ2C0";
-	}
-	1413
-	{
-		title = "Medium Flower (Cyan)";
-		sprite = "BSZ2D0";
-	}
-	1414
-	{
-		title = "Medium Flower (Yellow)";
-		sprite = "BSZ2E0";
-	}
-	1415
-	{
-		title = "Medium Flower (Orange)";
-		sprite = "BSZ2F0";
-	}
-	1420
-	{
-		title = "Short Flower (Red)";
-		sprite = "BSZ3A0";
-	}
-	1421
-	{
-		title = "Short Flower (Purple)";
-		sprite = "BSZ3B0";
-	}
-	1422
-	{
-		title = "Short Flower (Blue)";
-		sprite = "BSZ3C0";
-	}
-	1423
-	{
-		title = "Short Flower (Cyan)";
-		sprite = "BSZ3D0";
-	}
-	1424
-	{
-		title = "Short Flower (Yellow)";
-		sprite = "BSZ3E0";
-	}
-	1425
-	{
-		title = "Short Flower (Orange)";
-		sprite = "BSZ3F0";
-	}
-	1430
-	{
-		title = "Tulip (Red)";
-		sprite = "BST1A0";
-	}
-	1431
-	{
-		title = "Tulip (Purple)";
-		sprite = "BST2A0";
-	}
-	1432
-	{
-		title = "Tulip (Blue)";
-		sprite = "BST3A0";
-	}
-	1433
-	{
-		title = "Tulip (Cyan)";
-		sprite = "BST4A0";
-	}
-	1434
-	{
-		title = "Tulip (Yellow)";
-		sprite = "BST5A0";
-	}
-	1435
-	{
-		title = "Tulip (Orange)";
-		sprite = "BST6A0";
-	}
-	1440
-	{
-		title = "Cluster (Red)";
-		sprite = "BSZ5A0";
-	}
-	1441
-	{
-		title = "Cluster (Purple)";
-		sprite = "BSZ5B0";
-	}
-	1442
-	{
-		title = "Cluster (Blue)";
-		sprite = "BSZ5C0";
-	}
-	1443
-	{
-		title = "Cluster (Cyan)";
-		sprite = "BSZ5D0";
-	}
-	1444
-	{
-		title = "Cluster (Yellow)";
-		sprite = "BSZ5E0";
-	}
-	1445
-	{
-		title = "Cluster (Orange)";
-		sprite = "BSZ5F0";
-	}
-	1450
-	{
-		title = "Bush (Red)";
-		sprite = "BSZ6A0";
-	}
-	1451
-	{
-		title = "Bush (Purple)";
-		sprite = "BSZ6B0";
-	}
-	1452
-	{
-		title = "Bush (Blue)";
-		sprite = "BSZ6C0";
-	}
-	1453
-	{
-		title = "Bush (Cyan)";
-		sprite = "BSZ6D0";
-	}
-	1454
-	{
-		title = "Bush (Yellow)";
-		sprite = "BSZ6E0";
-	}
-	1455
-	{
-		title = "Bush (Orange)";
-		sprite = "BSZ6F0";
-	}
-	1460
-	{
-		title = "Vine (Red)";
-		sprite = "BSZ7A0";
-	}
-	1461
-	{
-		title = "Vine (Purple)";
-		sprite = "BSZ7B0";
-	}
-	1462
-	{
-		title = "Vine (Blue)";
-		sprite = "BSZ7C0";
-	}
-	1463
-	{
-		title = "Vine (Cyan)";
-		sprite = "BSZ7D0";
-	}
-	1464
-	{
-		title = "Vine (Yellow)";
-		sprite = "BSZ7E0";
-	}
-	1465
-	{
-		title = "Vine (Orange)";
-		sprite = "BSZ7F0";
-	}
-	1470
-	{
-		title = "BSZ Shrub";
-		sprite = "BSZ8A0";
-	}
-	1471
-	{
-		title = "BSZ Clover";
-		sprite = "BSZ8B0";
-	}
-	1473
-	{
-		title = "Palm Tree (Big)";
-		width = 16;
-		height = 160;
-		sprite = "BSZ8D0";
-	}
-	1475
-	{
-		title = "Palm Tree (Small)";
-		width = 16;
-		height = 80;
-		sprite = "BSZ8F0";
-	}
-}
-
-azuretemple
-{
-	color = 10; // Green
-	title = "Azure Temple";
-
-	1500
-	{
-		arrow = 1;
-		blocking = 2;
-		title = "Glaregoyle";
-		sprite = "BGARA1";
-		width = 16;
-		height = 40;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1501
-	{
-		arrow = 1;
-		blocking = 2;
-		title = "Glaregoyle (Up)";
-		sprite = "BGARA1";
-		width = 16;
-		height = 40;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1502
-	{
-		arrow = 1;
-		blocking = 2;
-		title = "Glaregoyle (Down)";
-		sprite = "BGARA1";
-		width = 16;
-		height = 40;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1503
-	{
-		arrow = 1;
-		blocking = 2;
-		title = "Glaregoyle (Long)";
-		sprite = "BGARA1";
-		width = 16;
-		height = 40;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1504
-	{
-		title = "ATZ Target";
-		sprite = "RCRYB0";
-		width = 24;
-		height = 32;
-	}
-	1505
-	{
-		title = "Green Flame";
-		sprite = "CFLMA0E0";
-		width = 8;
-		height = 32;
-	}
-	1506
-	{
-		arrow = 1;
-		blocking = 2;
-		title = "Blue Gargoyle";
-		sprite = "BGARD1";
-		width = 16;
-		height = 40;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-}
-
-dreamhill
-{
-	color = 10; // Green
-	title = "Dream Hill";
-
-	1600
-	{
-		title = "Spring Tree";
-		sprite = "TRE6A0";
-		width = 16;
-		height = 32;
-	}
-	1601
-	{
-		title = "Shleep";
-		sprite = "SHLPA0";
-		width = 24;
-		height = 32;
-	}
-	1602
-	{
-		title = "Pian";
-		sprite = "NTPNALAR";
-		width = 16;
-		height = 32;
-	}
-}
-
-nightstrk
-{
-	color = 13; // Pink
-	title = "NiGHTS Track";
-	width = 8;
-	height = 4096;
-	sprite = "UNKNA0";
-
-	1700
-	{
-		title = "Axis";
-		sprite = "internal:axis1";
-		circle = 1;
-		unflippable = true;
-		ignoreZ = true;
-		flagsvaluetext = "Order";
-		angletext = "Radius/Direction";
-		parametertext = "Mare";
-	}
-	1701
-	{
-		title = "Axis Transfer";
-		sprite = "internal:axis2";
-		unflippable = true;
-		ignoreZ = true;
-		flagsvaluetext = "Order";
-		parametertext = "Mare";
-	}
-	1702
-	{
-		title = "Axis Transfer Line";
-		sprite = "internal:axis3";
-		unflippable = true;
-		ignoreZ = true;
-		flagsvaluetext = "Order";
-		parametertext = "Mare";
-	}
-	1710
-	{
-		title = "Ideya Capture";
-		sprite = "CAPSA0";
-		width = 72;
-		height = 144;
-		angletext = "Rings";
-		parametertext = "Mare";
-	}
-}
-
-nights
-{
-	color = 13; // Pink
-	title = "NiGHTS Items";
-	width = 16;
-	height = 32;
-
-	1703
-	{
-		title = "Ideya Drone";
-		sprite = "NDRNA1";
-		width = 16;
-		height = 56;
-		flags1text = "[1] Align player to middle";
-		flags4text = "[4] Align player to top";
-		flags8text = "[8] Die upon time up";
-		angletext = "Time limit";
-		parametertext = "Height";
-	}
-	1704
-	{
-		arrow = 1;
-		title = "NiGHTS Bumper";
-		sprite = "NBMPG3G7";
-		width = 32;
-		height = 64;
-		unflippable = true;
-		flagsvaluetext = "Pitch";
-		angletext = "Yaw";
-	}
-	1705
-	{
-		arrow = 1;
-		title = "Hoop (Generic)";
-		sprite = "HOOPA0";
-		width = 80;
-		height = 160;
-		unflippable = true;
-		centerHitbox = true;
-		flagsvaluetext = "Height";
-		angletext = "Pitch/Yaw";
-	}
-	1706
-	{
-		title = "Blue Sphere";
-		sprite = "SPHRA0";
-		width = 16;
-		height = 24;
-		flags8height = 24;
-		flags8text = "[8] Float";
-		unflippable = true;
-	}
-	1707
-	{
-		title = "Super Paraloop";
-		sprite = "NPRUA0";
-		flags4text = "[4] Bonus time only";
-		flags8text = "[8] Spawn immediately";
-	}
-	1708
-	{
-		title = "Drill Refill";
-		sprite = "NPRUB0";
-		flags4text = "[4] Bonus time only";
-		flags8text = "[8] Spawn immediately";
-	}
-	1709
-	{
-		title = "Nightopian Helper";
-		sprite = "NPRUC0";
-		flags4text = "[4] Bonus time only";
-		flags8text = "[8] Spawn immediately";
-	}
-	1711
-	{
-		title = "Extra Time";
-		sprite = "NPRUD0";
-		flags4text = "[4] Bonus time only";
-		flags8text = "[8] Spawn immediately";
-	}
-	1712
-	{
-		title = "Link Freeze";
-		sprite = "NPRUE0";
-		flags4text = "[4] Bonus time only";
-		flags8text = "[8] Spawn immediately";
-	}
-	1713
-	{
-		arrow = 1;
-		title = "Hoop (Customizable)";
-		flags1text = "[1] Radius +16";
-		flags2text = "[2] Radius +32";
-		flags4text = "[4] Radius +64";
-		flags8text = "[8] Radius +128";
-		sprite = "HOOPA0";
-		width = 80;
-		height = 160;
-		unflippable = true;
-		centerHitbox = true;
-	}
-	1714
-	{
-		title = "Ideya Anchor Point";
-		sprite = "internal:axis1";
-		width = 8;
-		height = 16;
-		parametertext = "Ideya";
-	}
-}
-
-mario
-{
-	color = 6; // Brown
-	title = "Mario";
-
-	1800
-	{
-		title = "Coin";
-		sprite = "COINA0";
-		width = 16;
-		height = 24;
-		flags8height = 24;
-		flags8text = "[8] Float";
-	}
-	1801
-	{
-		arrow = 1;
-		title = "Goomba";
-		sprite = "GOOMA0";
-		width = 24;
-		height = 32;
-	}
-	1802
-	{
-		arrow = 1;
-		title = "Goomba (Blue)";
-		sprite = "BGOMA0";
-		width = 24;
-		height = 32;
-	}
-	1803
-	{
-		title = "Fire Flower";
-		sprite = "FFWRB0";
-		width = 16;
-		height = 32;
-	}
-	1804
-	{
-		title = "Koopa Shell";
-		sprite = "SHLLA1";
-		width = 16;
-		height = 20;
-	}
-	1805
-	{
-		title = "Puma (Jumping Fireball)";
-		sprite = "PUMAA0";
-		width = 8;
-		height = 16;
-		angletext = "Jump strength";
-	}
-	1806
-	{
-		title = "King Bowser";
-		sprite = "KOOPA0";
-		width = 16;
-		height = 48;
-	}
-	1807
-	{
-		title = "Axe";
-		sprite = "MAXEA0";
-		width = 8;
-		height = 16;
-	}
-	1808
-	{
-		title = "Bush (Short)";
-		sprite = "MUS1A0";
-		width = 16;
-		height = 32;
-	}
-	1809
-	{
-		title = "Bush (Tall)";
-		sprite = "MUS2A0";
-		width = 16;
-		height = 32;
-	}
-	1810
-	{
-		title = "Toad";
-		sprite = "TOADA0";
-		width = 8;
-		height = 32;
-	}
-}
-
-christmasdisco
-{
-	color = 10; // Green
-	title = "Christmas & Disco";
-
-	1850
-	{
-		title = "Christmas Pole";
-		sprite = "XMS1A0";
-		width = 16;
-		height = 40;
-	}
-	1851
-	{
-		title = "Candy Cane";
-		sprite = "XMS2A0";
-		width = 8;
-		height = 32;
-	}
-	1852
-	{
-		blocking = 2;
-		title = "Snowman";
-		sprite = "XMS3A0";
-		width = 16;
-		height = 64;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1853
-	{
-		blocking = 2;
-		title = "Snowman (With Hat)";
-		sprite = "XMS3B0";
-		width = 16;
-		height = 80;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-	1854
-	{
-		title = "Lamp Post";
-		sprite = "XMS4A0";
-		width = 8;
-		height = 120;
-	}
-	1855
-	{
-		title = "Lamp Post (Snow)";
-		sprite = "XMS4B0";
-		width = 8;
-		height = 120;
-	}
-	1856
-	{
-		title = "Hanging Star";
-		sprite = "XMS5A0";
-		width = 4;
-		height = 80;
-		hangs = 1;
-	}
-	1857
-	{
-		title = "Berry Bush (Snow)";
-		sprite = "BUS1B0";
-		width = 16;
-		height = 32;
-	}
-	1858
-	{
-		title = "Bush (Snow)";
-		sprite = "BUS2B0";
-		width = 16;
-		height = 32;
-	}
-	1859
-	{
-		title = "Blueberry Bush (Snow)";
-		sprite = "BUS3B0";
-		width = 16;
-		height = 32;
-	}
-	1875
-	{
-		title = "Disco Ball";
-		sprite = "DBALA0";
-		width = 16;
-		height = 54;
-		hangs = 1;
-	}
-	1876
-	{
-		arrow = 1;
-		blocking = 2;
-		title = "Eggman Disco Statue";
-		sprite = "ESTAB1";
-		width = 20;
-		height = 96;
-		flags4text = "[4] Slides when pushed";
-		flags8text = "[8] Not pushable";
-	}
-}
-
-stalagmites
-{
-	color = 10; // Green
-	title = "Stalagmites";
-	width = 16;
-	height = 40;
-
-	1900
-	{
-		title = "Brown Stalagmite (Tall)";
-		sprite = "STLGA0";
-		width = 16;
-		height = 40;
-	}
-	1901
-	{
-		title = "Brown Stalagmite";
-		sprite = "STLGB0";
-		width = 16;
-		height = 40;
-	}
-	1902
-	{
-		title = "Orange Stalagmite (Tall)";
-		sprite = "STLGC0";
-		width = 16;
-		height = 40;
-	}
-	1903
-	{
-		title = "Orange Stalagmite";
-		sprite = "STLGD0";
-		width = 16;
-		height = 40;
-	}
-	1904
-	{
-		title = "Red Stalagmite (Tall)";
-		sprite = "STLGE0";
-		width = 16;
-		height = 40;
-	}
-	1905
-	{
-		title = "Red Stalagmite";
-		sprite = "STLGF0";
-		width = 16;
-		height = 40;
-	}
-	1906
-	{
-		title = "Gray Stalagmite (Tall)";
-		sprite = "STLGG0";
-		width = 24;
-		height = 96;
-	}
-	1907
-	{
-		title = "Gray Stalagmite";
-		sprite = "STLGH0";
-		width = 16;
-		height = 40;
-	}
-	1908
-	{
-		title = "Blue Stalagmite (Tall)";
-		sprite = "STLGI0";
-		width = 16;
-		height = 40;
-	}
-	1909
-	{
-		title = "Blue Stalagmite";
-		sprite = "STLGJ0";
-		width = 16;
-		height = 40;
-	}
-}
-
-hauntedheights
-{
-	color = 10; // Green
-	title = "Haunted Heights";
-
-	2000
-	{
-		title = "Smashing Spikeball";
-		sprite = "FMCEA0";
-		width = 18;
-		height = 28;
-		angletext = "Initial delay";
-	}
-	2001
-	{
-		title = "HHZ Grass";
-		sprite = "HHZMA0";
-		width = 16;
-		height = 40;
-	}
-	2002
-	{
-		title = "HHZ Tentacle 1";
-		sprite = "HHZMB0";
-		width = 16;
-		height = 40;
-	}
-	2003
-	{
-		title = "HHZ Tentacle 2";
-		sprite = "HHZMC0";
-		width = 16;
-		height = 40;
-	}
-	2004
-	{
-		title = "HHZ Stalagmite (Tall)";
-		sprite = "HHZME0";
-		width = 16;
-		height = 40;
-	}
-	2005
-	{
-		title = "HHZ Stalagmite (Short)";
-		sprite = "HHZMF0";
-		width = 16;
-		height = 40;
-	}
-	2006
-	{
-		title = "Jack-o'-lantern 1";
-		sprite = "PUMKA0";
-		width = 16;
-		height = 40;
-		flags1text = "Don't flicker";
-	}
-	2007
-	{
-		title = "Jack-o'-lantern 2";
-		sprite = "PUMKB0";
-		width = 16;
-		height = 40;
-		flags1text = "Don't flicker";
-	}
-	2008
-	{
-		title = "Jack-o'-lantern 3";
-		sprite = "PUMKC0";
-		width = 16;
-		height = 40;
-		flags1text = "Don't flicker";
-	}
-	2009
-	{
-		title = "Purple Mushroom";
-		sprite = "SHRMD0";
-		width = 16;
-		height = 48;
-	}
-	2010
-	{
-		title = "HHZ Tree";
-		sprite = "HHPLC0";
-		width = 12;
-		height = 40;
-	}
-}
-
-frozenhillside
-{
-	color = 10; // Green
-	title = "Frozen Hillside";
-
-	2100
-	{
-		title = "Ice Shard (Small)";
-		sprite = "FHZIA0";
-		width = 8;
-		height = 32;
-	}
-	2101
-	{
-		title = "Ice Shard (Large)";
-		sprite = "FHZIB0";
-		width = 8;
-		height = 32;
-	}
-	2102
-	{
-		title = "Crystal Tree (Aqua)";
-		sprite = "TRE3A0";
-		width = 20;
-		height = 200;
-	}
-	2103
-	{
-		title = "Crystal Tree (Pink)";
-		sprite = "TRE3B0";
-		width = 20;
-		height = 200;
-	}
-	2104
-	{
-		title = "Amy Cameo";
-		sprite = "ROSYA1";
-		width = 16;
-		height = 48;
-		flags1text = "[1] Grayscale mode";
-	}
-	2105
-	{
-		title = "Mistletoe";
-		sprite = "XMS6A0";
-		width = 52;
-		height = 106;
-	}
-}
-
-flickies
-{
-	color = 10; // Green
-	title = "Flickies";
-	width = 8;
-	height = 20;
-	flags1text = "[1] Move aimlessly";
-	flags4text = "[4] No movement";
-	flags8text = "[8] Hop";
-	angletext = "Radius";
-
-	2200
-	{
-		title = "Bluebird";
-		sprite = "FL01A1";
-	}
-	2201
-	{
-		title = "Rabbit";
-		sprite = "FL02A1";
-	}
-	2202
-	{
-		title = "Chicken";
-		sprite = "FL03A1";
-	}
-	2203
-	{
-		title = "Seal";
-		sprite = "FL04A1";
-	}
-	2204
-	{
-		title = "Pig";
-		sprite = "FL05A1";
-	}
-	2205
-	{
-		title = "Chipmunk";
-		sprite = "FL06A1";
-	}
-	2206
-	{
-		title = "Penguin";
-		sprite = "FL07A1";
-	}
-	2207
-	{
-		title = "Fish";
-		sprite = "FL08A1";
-		parametertext = "Color";
-	}
-	2208
-	{
-		title = "Ram";
-		sprite = "FL09A1";
-	}
-	2209
-	{
-		title = "Puffin";
-		sprite = "FL10A1";
-	}
-	2210
-	{
-		title = "Cow";
-		sprite = "FL11A1";
-	}
-	2211
-	{
-		title = "Rat";
-		sprite = "FL12A1";
-	}
-	2212
-	{
-		title = "Bear";
-		sprite = "FL13A1";
-	}
-	2213
-	{
-		title = "Dove";
-		sprite = "FL14A1";
-	}
-	2214
-	{
-		title = "Cat";
-		sprite = "FL15A1";
-	}
-	2215
-	{
-		title = "Canary";
-		sprite = "FL16A1";
-	}
-	2216
-	{
-		title = "Spider";
-		sprite = "FS01A1";
-	}
-	2217
-	{
-		title = "Bat";
-		sprite = "FS02A0";
-	}
-}
\ No newline at end of file
diff --git a/extras/conf/SRB2_22Doom.cfg b/extras/conf/SRB2_22Doom.cfg
deleted file mode 100644
index 65e49d387..000000000
--- a/extras/conf/SRB2_22Doom.cfg
+++ /dev/null
@@ -1,38 +0,0 @@
-/************************************************************************\
-	Zone Builder Game Configuration for Sonic Robo Blast 2 Version 2.2
-\************************************************************************/
-
-// This is required to prevent accidental use of a different configuration
-type = "Doom Builder 2 Game Configuration";
-
-// This is the title to show for this game
-game = "Sonic Robo Blast 2 - 2.2 (Doom format)";
-
-// This is the simplified game engine/sourceport name
-engine = "zdoom";
-
-// Settings common to all games and all map formats
-include("Includes\\SRB222_common.cfg", "common");
-
-// Settings common to Doom map format
-include("Includes\\SRB222_common.cfg", "mapformat_doom");
-
-include("Includes\\Game_SRB222.cfg");
-
-// Script lumps detection
-scriptlumpnames
-{
-	include("Includes\\SRB222_misc.cfg", "scriptlumpnames");
-}
-
-// THING TYPES
-thingtypes
-{
-	include("Includes\\SRB222_things.cfg");
-}
-
-//Default things filters
-thingsfilters
-{
-	include("Includes\\SRB222_misc.cfg", "thingsfilters");
-}
\ No newline at end of file
diff --git a/extras/conf/SRB2_22UDMF.cfg b/extras/conf/SRB2_22UDMF.cfg
deleted file mode 100644
index 52104ed09..000000000
--- a/extras/conf/SRB2_22UDMF.cfg
+++ /dev/null
@@ -1,47 +0,0 @@
-/************************************************************************\
-	Zone Builder Game Configuration for Sonic Robo Blast 2 Version 2.2
-\************************************************************************/
-
-// This is required to prevent accidental use of a different configuration
-type = "Doom Builder 2 Game Configuration";
-
-// This is the title to show for this game
-game = "Sonic Robo Blast 2 - 2.2 (UDMF)";
-
-// This is the simplified game engine/sourceport name
-engine = "zdoom";
-
-// Settings common to all games and all map formats
-include("Includes\\SRB222_common.cfg", "common");
-
-// Settings common to Doom map format
-include("Includes\\SRB222_common.cfg", "mapformat_udmf");
-
-include("Includes\\Game_SRB222.cfg");
-
-// Script lumps detection
-scriptlumpnames
-{
-	include("Includes\\SRB222_misc.cfg", "scriptlumpnames");
-}
-
-// THING TYPES
-thingtypes
-{
-	include("Includes\\SRB222_things.cfg");
-}
-
-//Default things filters
-thingsfilters
-{
-	include("Includes\\SRB222_misc.cfg", "thingsfilters");
-}
-
-// ENUMERATIONS
-// Each engine has its own additional thing types
-// These are enumerated lists for linedef types and UDMF fields.
-enums
-{
-	// Basic game enums
-	include("Includes\\SRB222_misc.cfg", "enums");
-}
\ No newline at end of file

From 06f9246fd36b1dde74f0cd1d3248aa7aadb2ae97 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 21 Mar 2020 12:06:52 +0100
Subject: [PATCH 137/251] Updates and fixes for the ZB config

---
 extras/conf/SRB2-22.cfg | 109 +++++++++++++++++++++++++++-------------
 1 file changed, 74 insertions(+), 35 deletions(-)

diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg
index ec318321d..5119c1234 100644
--- a/extras/conf/SRB2-22.cfg
+++ b/extras/conf/SRB2-22.cfg
@@ -435,7 +435,7 @@ sectortypes
 	112 = "Trigger Line Ex. (NiGHTS Mare)";
 	128 = "Check for Linedef Executor on FOFs";
 	144 = "Egg Capsule";
-	160 = "Special Stage Time/Rings Parameters";
+	160 = "Special Stage Time/Spheres Parameters";
 	176 = "Custom Global Gravity";
 	512 = "Wind/Current";
 	1024 = "Conveyor Belt";
@@ -490,7 +490,7 @@ gen_sectortypes
 		112 = "Trigger Line Ex. (NiGHTS Mare)";
 		128 = "Check for Linedef Executor on FOFs";
 		144 = "Egg Capsule";
-		160 = "Special Stage Time/Rings Parameters";
+		160 = "Special Stage Time/Spheres Parameters";
 		176 = "Custom Global Gravity";
 	}
 
@@ -766,6 +766,7 @@ linedeftypes
 		{
 			title = "Parameters";
 			prefix = "(22)";
+			flags32text = "[5] Render outer sides only";
 			flags64text = "[6] Trigger linedef executor";
 			flags128text = "[7] Intangible";
 			flags256text = "[8] Stopped by pushables";
@@ -788,7 +789,6 @@ linedeftypes
 		{
 			title = "Angular Displacement by Front Sector";
 			prefix = "(32)";
-			flags8text = "[3] Set delay by backside sector";
 			flags64text = "[6] Don't turn players";
 			flags512text = "[9] Turn all objects";
 		}
@@ -1136,7 +1136,6 @@ linedeftypes
 		{
 			title = "Goo Water, Translucent, No Sides";
 			prefix = "(125)";
-			flags8text = "[3] Slope skew sides";
 			flags64text = "[6] Use two light levels";
 			flags512text = "[9] Use target light level";
 			flags1024text = "[10] Ripple effect";
@@ -1227,6 +1226,18 @@ linedeftypes
 			3dfloorflags = "19F";
 		}
 
+		153
+		{
+			title = "Dynamically Sinking Platform";
+			prefix = "(153)";
+			flags8text = "[3] Slope skew sides";
+			flags32text = "[5] Only block player";
+			flags64text = "[6] Spindash to move";
+			flags128text = "[7] Only block non-players";
+			3dfloor = true;
+			3dfloorflags = "19F";
+		}
+
 		160
 		{
 			title = "Floating, Bobbing";
@@ -1282,7 +1293,6 @@ linedeftypes
 			title = "Rising Platform, Solid, Invisible";
 			prefix = "(193)";
 			flags2text = "[1] Sink when stepped on";
-			flags8text = "[3] Slope skew sides";
 			flags32text = "[5] Only block player";
 			flags64text = "[6] Spindash to move";
 			flags128text = "[7] Only block non-players";
@@ -1488,16 +1498,22 @@ linedeftypes
 		{
 			title = "Mario Block";
 			prefix = "(250)";
+			flags8text = "[3] Slope skew sides";
 			flags32text = "[5] Invisible block";
 			flags64text = "[6] Brick block";
 			3dfloor = true;
 			3dfloorflags = "40019F";
+			flags323dfloorflagsremove = "19E";
+			flags643dfloorflagsadd = "200000";
 		}
 
 		251
 		{
 			title = "Thwomp Block";
 			prefix = "(251)";
+			flags8text = "[3] Slope skew sides";
+			flags32text = "[5] Only block player";
+			flags128text = "[7] Only block non-players";
 			flags512text = "[9] Custom crushing sound";
 			flags1024text = "[10] Custom speed";
 			3dfloor = true;
@@ -1513,8 +1529,8 @@ linedeftypes
 			flags512text = "[9] Shattered by pushables";
 			flags1024text = "[10] Trigger linedef executor";
 			3dfloor = true;
-			3dfloorflags = "8800019";
-			flags643dfloorflagsadd = "200006";
+			3dfloorflags = "880001D";
+			flags643dfloorflagsadd = "200002";
 		}
 
 		253
@@ -1525,7 +1541,7 @@ linedeftypes
 			flags512text = "[9] Shattered by pushables";
 			flags1024text = "[10] Trigger linedef executor";
 			3dfloor = true;
-			3dfloorflags = "8801019";
+			3dfloorflags = "880101D";
 		}
 
 		254
@@ -1533,6 +1549,7 @@ linedeftypes
 			title = "Bustable Block";
 			prefix = "(254)";
 			flags8text = "[3] Slope skew sides";
+			flags32text = "[5] Only block player";
 			flags64text = "[6] Strong characters only";
 			flags128text = "[7] Only block non-players";
 			flags512text = "[9] Shattered by pushables";
@@ -1593,6 +1610,7 @@ linedeftypes
 		{
 			title = "Custom FOF";
 			prefix = "(259)";
+			flags8text = "[3] Slope skew sides";
 			flags32text = "[5] Only block player";
 			flags128text = "[7] Only block non-players";
 			flags512text = "[9] Shattered by pushables";
@@ -2161,6 +2179,14 @@ linedeftypes
 			flags8text = "[3] Set delay by backside sector";
 		}
 
+		449
+		{
+			title = "Enable Bosses with Parameter";
+			prefix = "(449)";
+			flags8text = "[3] Set delay by backside sector";
+			flags64text = "[6] Disable bosses";
+		}
+
 		457
 		{
 			title = "Track Object's Angle";
@@ -2180,12 +2206,14 @@ linedeftypes
 		{
 			title = "Award Rings";
 			prefix = "(460)";
+			flags8text = "[3] Set delay by backside sector";
 		}
 
 		461
 		{
 			title = "Spawn Object";
 			prefix = "(461)";
+			flags8text = "[3] Set delay by backside sector";
 			flags64text = "[6] Spawn inside a range";
 		}
 
@@ -2193,6 +2221,7 @@ linedeftypes
 		{
 			title = "Stop Timer/Exit Stage in Record Attack";
 			prefix = "(462)";
+			flags8text = "[3] Set delay by backside sector";
 		}
 	}
 
@@ -2206,7 +2235,7 @@ linedeftypes
 			prefix = "(413)";
 			flags2text = "[1] Keep after death";
 			flags8text = "[3] Set delay by backside sector";
-			flags32text = "[5] Seek to current song position";
+			flags32text = "[5] Seek from current position";
 			flags64text = "[6] For everyone";
 			flags128text = "[7] Fade to custom volume";
 			flags512text = "[9] Don't loop";
@@ -2220,7 +2249,7 @@ linedeftypes
 			flags2text = "[1] From calling sector";
 			flags8text = "[3] Set delay by backside sector";
 			flags64text = "[6] From nowhere for triggerer";
-			flags512text = "[9] For everyone";
+			flags512text = "[9] From nowhere for everyone";
 			flags1024text = "[10] From tagged sectors";
 		}
 
@@ -2298,7 +2327,6 @@ linedeftypes
 			flags8text = "[3] Set delay by backside sector";
 		}
 
-
 		445
 		{
 			title = "Make FOF Disappear/Reappear";
@@ -2325,8 +2353,8 @@ linedeftypes
 			flags32text = "[5] Subtract Red value";
 			flags64text = "[6] Subtract Green value";
 			flags128text = "[7] Subtract Blue value";
-			flags256text = "[8] Calc relative values";
-			flags32768text = "[15] Use back side colormap";
+			flags256text = "[8] Set relative to current";
+			flags32768text = "[15] Use backside colormap";
 		}
 
 		448
@@ -2359,7 +2387,7 @@ linedeftypes
 			prefix = "(452)";
 			flags8text = "[3] Set delay by backside sector";
 			flags64text = "[6] Do not handle FF_TRANS";
-			flags256text = "[8] Set relative to current val";
+			flags256text = "[8] Set relative to current";
 		}
 
 		453
@@ -2371,7 +2399,7 @@ linedeftypes
 			flags32text = "[5] No collision during fade";
 			flags64text = "[6] Do not handle FF_TRANS";
 			flags128text = "[7] Do not handle lighting";
-			flags256text = "[8] Set relative to current val";
+			flags256text = "[8] Set relative to current";
 			flags512text = "[9] Speed = Tic Duration";
 			flags1024text = "[10] Override existing fade";
 			flags16384text = "[14] Do not handle collision";
@@ -2395,11 +2423,11 @@ linedeftypes
 			flags32text = "[5] Subtract Red value";
 			flags64text = "[6] Subtract Green value";
 			flags128text = "[7] Subtract Blue value";
-			flags256text = "[8] Calc relative values";
+			flags256text = "[8] Set relative to current";
 			flags512text = "[9] Speed = Tic Duration";
 			flags1024text = "[10] Override existing fade";
 			flags16384text = "[14] Fade from invisible black";
-			flags32768text = "[15] Use back side colormap";
+			flags32768text = "[15] Use backside colormap";
 		}
 
 		456
@@ -2416,9 +2444,7 @@ linedeftypes
 			flags2text = "[1] Close text prompt";
 			flags8text = "[3] Set delay by backside sector";
 			flags32text = "[5] Run executor tag on close";
-			flags64text = "[6] For everyone";
-			flags128text = "[7] Do not block controls";
-			flags256text = "[8] Do not freeze time";
+			flags128text = "[7] Don't disable controls";
 			flags32768text = "[15] Find prompt by name";
 		}
 	}
@@ -2524,7 +2550,7 @@ linedeftypes
 			prefix = "(491)";
 			flags8text = "[3] Set delay by backside sector";
 			flags16text = "[4] Set raw alpha by Front X";
-			flags256text = "[8] Calc relative values";
+			flags256text = "[8] Set relative to current";
 		}
 
 		492
@@ -2534,7 +2560,7 @@ linedeftypes
 			flags8text = "[3] Set delay by backside sector";
 			flags16text = "[4] Set raw alpha by Front X";
 			flags32text = "[5] No collision during fade";
-			flags256text = "[8] Calc relative values";
+			flags256text = "[8] Set relative to current";
 			flags512text = "[9] Speed = Tic Duration";
 			flags1024text = "[10] Override existing fade";
 			flags16384text = "[14] Do not handle collision";
@@ -2632,76 +2658,84 @@ linedeftypes
 		{
 			title = "Carry Objects on Floor";
 			prefix = "(520)";
+			flags64text = "[6] Exclusive";
 		}
 
 		521
 		{
 			title = "Carry Objects on Floor (Accelerative)";
 			prefix = "(521)";
-			flags64text = "[6] Even across edges";
+			flags64text = "[6] Exclusive";
 		}
 
 		522
 		{
 			title = "Carry Objects on Floor (Displacement)";
 			prefix = "(522)";
+			flags64text = "[6] Exclusive";
 		}
 
 		523
 		{
 			title = "Carry Objects on Ceiling";
 			prefix = "(523)";
-			flags64text = "[6] Even across edges";
+			flags64text = "[6] Exclusive";
 		}
 
 		524
 		{
 			title = "Carry Objects on Ceiling (Accelerative)";
 			prefix = "(524)";
+			flags64text = "[6] Exclusive";
 		}
 
 		525
 		{
 			title = "Carry Objects on Ceiling (Displacement)";
 			prefix = "(525)";
+			flags64text = "[6] Exclusive";
 		}
 
 		530
 		{
 			title = "Scroll Floor Texture and Carry Objects";
 			prefix = "(530)";
-			flags64text = "[6] Even across edges";
+			flags64text = "[6] Exclusive";
 		}
 
 		531
 		{
 			title = "Scroll Floor Texture and Carry Objects (Accelerative)";
 			prefix = "(531)";
+			flags64text = "[6] Exclusive";
 		}
 
 		532
 		{
 			title = "Scroll Floor Texture and Carry Objects (Displacement)";
 			prefix = "(532)";
+			flags64text = "[6] Exclusive";
 		}
 
 		533
 		{
 			title = "Scroll Ceiling Texture and Carry Objects";
 			prefix = "(533)";
-			flags64text = "[6] Even across edges";
+			flags64text = "[6] Exclusive";
 		}
 
 		534
 		{
 			title = "Scroll Ceiling Texture and Carry Objects (Accelerative)";
 			prefix = "(534)";
+			flags64text = "[6] Exclusive";
 		}
 
 		535
 		{
 			title = "Scroll Ceiling Texture and Carry Objects (Displacement)";
 			prefix = "(535)";
+			flags64text = "[6] Exclusive";
 		}
 	}
 
@@ -2714,7 +2748,7 @@ linedeftypes
 			title = "Wind";
 			prefix = "(541)";
 			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
+			flags64text = "[6] Exclusive";
 		}
 
 		542
@@ -2722,7 +2756,7 @@ linedeftypes
 			title = "Upwards Wind";
 			prefix = "(542)";
 			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
+			flags64text = "[6] Exclusive";
 		}
 
 		543
@@ -2730,7 +2764,7 @@ linedeftypes
 			title = "Downwards Wind";
 			prefix = "(543)";
 			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
+			flags64text = "[6] Exclusive";
 		}
 
 		544
@@ -2738,7 +2772,7 @@ linedeftypes
 			title = "Current";
 			prefix = "(544)";
 			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
+			flags64text = "[6] Exclusive";
 		}
 
 		545
@@ -2746,7 +2780,7 @@ linedeftypes
 			title = "Upwards Current";
 			prefix = "(545)";
 			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
+			flags64text = "[6] Exclusive";
 		}
 
 		546
@@ -2754,13 +2788,14 @@ linedeftypes
 			title = "Downwards Current";
 			prefix = "(546)";
 			flags512text = "[9] Player slides";
-			flags64text = "[6] Even across edges";
+			flags64text = "[6] Exclusive";
 		}
 
 		547
 		{
 			title = "Push/Pull";
 			prefix = "(547)";
+			flags64text = "[6] Exclusive";
 		}
 	}
 
@@ -3897,9 +3932,10 @@ thingtypes
 		title = "Monitors";
 		width = 18;
 		height = 40;
-		flags1text = "[1] Run Linedef Executor on pop";
+		flags1text = "[1] Run linedef executor on pop";
 		flags4text = "[4] Random (Strong)";
 		flags8text = "[8] Random (Weak)";
+		angletext = "Tag";
 
 		400
 		{
@@ -4029,7 +4065,8 @@ thingtypes
 		title = "Monitors (Respawning)";
 		width = 20;
 		height = 44;
-		flags1text = "[1] Run Linedef Executor on pop";
+		flags1text = "[1] Run linedef executor on pop";
+		angletext = "Tag";
 
 		431
 		{
@@ -4126,6 +4163,7 @@ thingtypes
 			width = 64;
 			height = 128;
 			angletext = "Angle/Order";
+			parametertext = "Order";
 		}
 		520
 		{
@@ -4558,6 +4596,7 @@ thingtypes
 			sprite = "TOADA0";
 			width = 32;
 			height = 16;
+			angletext = "Tag";
 		}
 		757
 		{
@@ -5832,7 +5871,7 @@ thingtypes
 			sprite = "CAPSA0";
 			width = 72;
 			height = 144;
-			angletext = "Rings";
+			angletext = "Spheres";
 			parametertext = "Mare";
 		}
 	}

From f32ab5918ec39181e238ebf5333499718f73e4b5 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Sat, 21 Mar 2020 07:47:29 -0500
Subject: [PATCH 138/251] Define SERVER_URL_PROTOCOL const for easy
 reconfiguration

---
 src/d_main.c  | 2 +-
 src/doomdef.h | 3 +++
 src/m_argv.c  | 5 +++--
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/src/d_main.c b/src/d_main.c
index d954fa4d1..ec63242b8 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -895,7 +895,7 @@ static void IdentifyVersion(void)
 	{
 		size_t i;
 
-		CONS_Printf("srb2:// connect links load game files from the SRB2 application's stored directory. Switching to ");
+		CONS_Printf("%s connect links load game files from the SRB2 application's stored directory. Switching to ", SERVER_URL_PROTOCOL);
 		strlcpy(srb2path, myargv[0], sizeof(srb2path));
 
 		// Get just the directory, minus the EXE name
diff --git a/src/doomdef.h b/src/doomdef.h
index 71c885019..5a5c933e3 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -150,6 +150,9 @@ extern char logfilename[1024];
 // Otherwise we can't force updates!
 #endif
 
+/* A custom URL protocol for server links. */
+#define SERVER_URL_PROTOCOL "srb2://"
+
 // Does this version require an added patch file?
 // Comment or uncomment this as necessary.
 #define USE_PATCH_DTA
diff --git a/src/m_argv.c b/src/m_argv.c
index d7d1f4463..7d43d96bc 100644
--- a/src/m_argv.c
+++ b/src/m_argv.c
@@ -41,12 +41,13 @@ static INT32 found;
 const char *M_GetUrlProtocolArg(void)
 {
 	INT32 i;
+	const size_t len = strlen(SERVER_URL_PROTOCOL);
 
 	for (i = 1; i < myargc; i++)
 	{
-		if (!strnicmp(myargv[i], "srb2://", 7))
+		if (strlen(myargv[i]) > len && !strnicmp(myargv[i], SERVER_URL_PROTOCOL, len))
 		{
-			return &myargv[i][7];
+			return &myargv[i][len];
 		}
 	}
 

From d2c83e1cdae12e0cd02493a4e6f4786b93a5a471 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 21 Mar 2020 15:16:07 +0100
Subject: [PATCH 139/251] Add Object Special text for Star Post

---
 extras/conf/SRB2-22.cfg | 1 +
 1 file changed, 1 insertion(+)

diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg
index 5119c1234..0168cf210 100644
--- a/extras/conf/SRB2-22.cfg
+++ b/extras/conf/SRB2-22.cfg
@@ -4162,6 +4162,7 @@ thingtypes
 			sprite = "STPTA0M0";
 			width = 64;
 			height = 128;
+			flags4text = "[4] Respawn at center";
 			angletext = "Angle/Order";
 			parametertext = "Order";
 		}

From c806d8a5e8c6572d0acabcb4e9f2e1ce1d243693 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 21 Mar 2020 20:17:28 +0100
Subject: [PATCH 140/251] Another ZB config fix

---
 extras/conf/SRB2-22.cfg | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg
index 0168cf210..57805a528 100644
--- a/extras/conf/SRB2-22.cfg
+++ b/extras/conf/SRB2-22.cfg
@@ -3442,8 +3442,8 @@ thingtypes
 			sprite = "ESHIA1";
 			width = 16;
 			height = 48;
-			flags1text = "[1] 90 degrees counter-clockwise";
-			flags4text = "[4] 90 degrees clockwise";
+			flags1text = "[1] 90 degrees clockwise";
+			flags4text = "[4] 90 degrees counter-clockwise";
 			flags8text = "[8] Double speed";
 		}
 		115

From 6911097b56afc99f8a0ef3329bcf9f3bf0e89230 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 22 Mar 2020 07:50:57 +0100
Subject: [PATCH 141/251] Minor ZB config fix

---
 extras/conf/SRB2-22.cfg | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg
index 57805a528..12287ec80 100644
--- a/extras/conf/SRB2-22.cfg
+++ b/extras/conf/SRB2-22.cfg
@@ -6313,7 +6313,7 @@ thingtypes
 			sprite = "PUMKA0";
 			width = 16;
 			height = 40;
-			flags1text = "Don't flicker";
+			flags1text = "[1] Don't flicker";
 		}
 		2007
 		{
@@ -6321,7 +6321,7 @@ thingtypes
 			sprite = "PUMKB0";
 			width = 16;
 			height = 40;
-			flags1text = "Don't flicker";
+			flags1text = "[1] Don't flicker";
 		}
 		2008
 		{
@@ -6329,7 +6329,7 @@ thingtypes
 			sprite = "PUMKC0";
 			width = 16;
 			height = 40;
-			flags1text = "Don't flicker";
+			flags1text = "[1] Don't flicker";
 		}
 		2009
 		{

From 48e8c9058a1ea98531e5887abd76cdbc13b550ac Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 22 Mar 2020 12:55:34 +0100
Subject: [PATCH 142/251] Add arrow to wall spike in ZB config

---
 extras/conf/SRB2-22.cfg | 1 +
 1 file changed, 1 insertion(+)

diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg
index 12287ec80..ec030b32f 100644
--- a/extras/conf/SRB2-22.cfg
+++ b/extras/conf/SRB2-22.cfg
@@ -4191,6 +4191,7 @@ thingtypes
 			sprite = "WSPKALAR";
 			width = 16;
 			height = 14;
+			arrow = 1;
 			flags1text = "[1] Start retracted";
 			flags4text = "[4] Retractable";
 			flags8text = "[8] Intangible";

From deff1565dc5945f56d9e45478e684dd868d27856 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Sun, 22 Mar 2020 12:13:59 -0500
Subject: [PATCH 143/251] GL horizon lines

---
 src/hardware/hw_main.c | 172 ++++++++++++++++++++++-------------------
 1 file changed, 92 insertions(+), 80 deletions(-)

diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index efed9b602..a3a1ba692 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -20,6 +20,7 @@
 
 #include "../doomstat.h"
 
+#define HWRENDER
 #ifdef HWRENDER
 #include "hw_glob.h"
 #include "hw_light.h"
@@ -469,7 +470,7 @@ static UINT8 HWR_FogBlockAlpha(INT32 light, UINT32 color) // Let's see if this c
 // -----------------+
 // HWR_RenderPlane  : Render a floor or ceiling convex polygon
 // -----------------+
-static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
+static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight,
                            FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, boolean fogplane, extracolormap_t *planecolormap)
 {
 	polyvertex_t *  pv;
@@ -493,8 +494,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 	static FOutVector *planeVerts = NULL;
 	static UINT16 numAllocedPlaneVerts = 0;
 
-	(void)sector; ///@TODO remove shitty unused variable
-
 	// no convex poly were generated for this subsector
 	if (!xsub->planepoly)
 		return;
@@ -593,8 +592,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 	flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatheight);
 
 	// transform
-	v3d = planeVerts;
-
 	if (FOFsector != NULL)
 	{
 		if (!isceiling) // it's a floor
@@ -637,46 +634,43 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 		flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
 	}
 
-	for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++)
-	{
-		// Hurdler: add scrolling texture on floor/ceiling
-		if (texflat)
-		{
-			v3d->sow = (float)(pv->x / fflatwidth) + scrollx;
-			v3d->tow = -(float)(pv->y / fflatheight) + scrolly;
-		}
-		else
-		{
-			v3d->sow = (float)((pv->x / fflatwidth) - flatxref + scrollx);
-			v3d->tow = (float)(flatyref - (pv->y / fflatheight) + scrolly);
-		}
+#define SETUP3DVERT(vert, vx, vy) {\
+		/* Hurdler: add scrolling texture on floor/ceiling */\
+		if (texflat)\
+		{\
+			vert->sow = (float)((vx) / fflatwidth) + scrollx;\
+			vert->tow = -(float)((vy) / fflatheight) + scrolly;\
+		}\
+		else\
+		{\
+			vert->sow = (float)(((vx) / fflatwidth) - flatxref + scrollx);\
+			vert->tow = (float)(flatyref - ((vy) / fflatheight) + scrolly);\
+		}\
+\
+		/* Need to rotate before translate */\
+		if (angle) /* Only needs to be done if there's an altered angle */\
+		{\
+			tempxsow = FLOAT_TO_FIXED(vert->sow);\
+			tempytow = FLOAT_TO_FIXED(vert->tow);\
+			if (texflat)\
+				tempytow = -tempytow;\
+			vert->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\
+			vert->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\
+		}\
+\
+		vert->x = (vx);\
+		vert->y = height;\
+		vert->z = (vy);\
+\
+		if (slope)\
+		{\
+			fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED((vx)), FLOAT_TO_FIXED((vy)));\
+			vert->y = FIXED_TO_FLOAT(fixedheight);\
+		}\
+}
 
-		// Need to rotate before translate
-		if (angle) // Only needs to be done if there's an altered angle
-		{
-			tempxsow = FLOAT_TO_FIXED(v3d->sow);
-			tempytow = FLOAT_TO_FIXED(v3d->tow);
-			if (texflat)
-				tempytow = -tempytow;
-			v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
-			v3d->tow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
-		}
-
-		//v3d->sow = (float)(v3d->sow - flatxref + scrollx);
-		//v3d->tow = (float)(flatyref - v3d->tow + scrolly);
-
-		v3d->x = pv->x;
-		v3d->y = height;
-		v3d->z = pv->y;
-
-#ifdef ESLOPE
-		if (slope)
-		{
-			fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED(pv->x), FLOAT_TO_FIXED(pv->y));
-			v3d->y = FIXED_TO_FLOAT(fixedheight);
-		}
-#endif
-	}
+	for (i = 0, v3d = planeVerts; i < nrPlaneVerts; i++,v3d++,pv++)
+		SETUP3DVERT(v3d, pv->x, pv->y);
 
 	// only useful for flat coloured triangles
 	//Surf.FlatColor = 0xff804020;
@@ -687,38 +681,6 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 	Surf.FlatColor.s.red = Surf.FlatColor.s.green =
 	Surf.FlatColor.s.blue = LightLevelToLum(lightlevel); //  Don't take from the frontsector, or the game will crash
 
-#if 0 // no colormap test
-	// colormap test
-	if (gr_frontsector)
-	{
-		sector_t *psector = gr_frontsector;
-
-#ifdef ESLOPE
-		if (slope)
-			fixedheight = P_GetZAt(slope, psector->soundorg.x, psector->soundorg.y);
-#endif
-
-		if (psector->ffloors)
-		{
-			ffloor_t *caster = psector->lightlist[R_GetPlaneLight(psector, fixedheight, false)].caster;
-			psector = caster ? &sectors[caster->secnum] : psector;
-
-			if (caster)
-			{
-				lightlevel = psector->lightlevel;
-				Surf.FlatColor.s.red = Surf.FlatColor.s.green = Surf.FlatColor.s.blue = LightLevelToLum(lightlevel);
-			}
-		}
-		if (psector->extra_colormap)
-			Surf.FlatColor.rgba = HWR_Lighting(lightlevel,psector->extra_colormap->rgba,psector->extra_colormap->fadergba, false, true);
-		else
-			Surf.FlatColor.rgba = HWR_Lighting(lightlevel,NORMALFOG,FADEFOG, false, true);
-	}
-	else
-		Surf.FlatColor.rgba = HWR_Lighting(lightlevel,NORMALFOG,FADEFOG, false, true);
-
-#endif // NOPE
-
 	if (planecolormap)
 	{
 		if (fogplane)
@@ -744,6 +706,56 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is
 
 	HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags);
 
+	if (subsector)
+	{
+		// Horizon lines
+		FOutVector horizonpts[5];
+		float dist, vx, vy;
+		const float renderdist = 60000.0f; // Well past the Z cutoff plane, but needed to fill out to that point at a wider angle
+
+		seg_t *line = &segs[subsector->firstline];
+
+		for (i = 0; i < subsector->numlines; i++, line++)
+		{
+			if (!line->glseg && line->linedef->special == HORIZONSPECIAL && R_PointOnSegSide(dup_viewx, dup_viewy, line) == 0)
+			{
+				//SETUP3DVERT(horizonpts[1], FIXED_TO_FLOAT(line->v1->x), FIXED_TO_FLOAT(line->v1->y));
+				//SETUP3DVERT(horizonpts[2], FIXED_TO_FLOAT(line->v2->x), FIXED_TO_FLOAT(line->v2->y));
+
+				// Left side
+				vx = ((polyvertex_t *)line->pv1)->x;
+				vy = ((polyvertex_t *)line->pv1)->y;
+				SETUP3DVERT((&horizonpts[1]), vx, vy);
+
+				dist = sqrtf(powf(vx - gr_viewx, 2) + powf(vy - gr_viewy, 2));
+				vx = (vx - gr_viewx) * renderdist / dist + gr_viewx;
+				vy = (vy - gr_viewy) * renderdist / dist + gr_viewy;
+				SETUP3DVERT((&horizonpts[0]), vx, vy);
+
+				// Right side
+				vx = ((polyvertex_t *)line->pv2)->x;
+				vy = ((polyvertex_t *)line->pv2)->y;
+				SETUP3DVERT((&horizonpts[2]), vx, vy);
+
+				dist = sqrtf(powf(vx - gr_viewx, 2) + powf(vy - gr_viewy, 2));
+				vx = (vx - gr_viewx) * renderdist / dist + gr_viewx;
+				vy = (vy - gr_viewy) * renderdist / dist + gr_viewy;
+				SETUP3DVERT((&horizonpts[3]), vx, vy);
+
+				// Midpoint for better filling
+				vx = (horizonpts[0].x + horizonpts[3].x)/2;
+				vy = (horizonpts[0].z + horizonpts[3].z)/2;
+				dist = sqrtf(powf(vx - gr_viewx, 2) + powf(vy - gr_viewy, 2));
+				vx = (vx - gr_viewx) * renderdist / dist + gr_viewx;
+				vy = (vy - gr_viewy) * renderdist / dist + gr_viewy;
+				SETUP3DVERT((&horizonpts[4]), vx, vy);
+
+				// Draw
+				HWD.pfnDrawPolygon(&Surf, horizonpts, 5, PolyFlags);
+			}
+		}
+	}
+
 #ifdef ALAM_LIGHTING
 	// add here code for dynamic lighting on planes
 	HWR_PlaneLighting(planeVerts, nrPlaneVerts);
@@ -3561,7 +3573,7 @@ static void HWR_Subsector(size_t num)
 			if (sub->validcount != validcount)
 			{
 				HWR_GetLevelFlat(&levelflats[gr_frontsector->floorpic]);
-				HWR_RenderPlane(gr_frontsector, &extrasubsectors[num], false,
+				HWR_RenderPlane(sub, &extrasubsectors[num], false,
 					// Hack to make things continue to work around slopes.
 					locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight,
 					// We now return you to your regularly scheduled rendering.
@@ -3583,7 +3595,7 @@ static void HWR_Subsector(size_t num)
 			if (sub->validcount != validcount)
 			{
 				HWR_GetLevelFlat(&levelflats[gr_frontsector->ceilingpic]);
-				HWR_RenderPlane(NULL, &extrasubsectors[num], true,
+				HWR_RenderPlane(sub, &extrasubsectors[num], true,
 					// Hack to make things continue to work around slopes.
 					locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight,
 					// We now return you to your regularly scheduled rendering.
@@ -3677,7 +3689,7 @@ static void HWR_Subsector(size_t num)
 				{
 					HWR_GetLevelFlat(&levelflats[*rover->bottompic]);
 					light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
-					HWR_RenderPlane(NULL, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic],
+					HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic],
 					                rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
 				}
 			}
@@ -3741,7 +3753,7 @@ static void HWR_Subsector(size_t num)
 				{
 					HWR_GetLevelFlat(&levelflats[*rover->toppic]);
 					light = R_GetPlaneLight(gr_frontsector, centerHeight, dup_viewz < cullHeight ? true : false);
-					HWR_RenderPlane(NULL, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic],
+					HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic],
 					                  rover->master->frontsector, 255, false, *gr_frontsector->lightlist[light].extra_colormap);
 				}
 			}

From 14d6a012928443ba8699f1a2834800193bb70c1f Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Sun, 22 Mar 2020 12:20:26 -0500
Subject: [PATCH 144/251] Distort far edges to viewz for a flat horizon line

---
 src/hardware/hw_main.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index a3a1ba692..253deb282 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -709,9 +709,10 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 	if (subsector)
 	{
 		// Horizon lines
-		FOutVector horizonpts[5];
+		FOutVector horizonpts[6];
 		float dist, vx, vy;
-		const float renderdist = 60000.0f; // Well past the Z cutoff plane, but needed to fill out to that point at a wider angle
+		const float renderdist = 30000.0f; // How far out to properly render the plane
+		const float farrenderdist = 32768.0f; // From here, raise plane to horizon level to fill in the line with some texture distortion
 
 		seg_t *line = &segs[subsector->firstline];
 
@@ -742,16 +743,19 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 				vy = (vy - gr_viewy) * renderdist / dist + gr_viewy;
 				SETUP3DVERT((&horizonpts[3]), vx, vy);
 
-				// Midpoint for better filling
-				vx = (horizonpts[0].x + horizonpts[3].x)/2;
-				vy = (horizonpts[0].z + horizonpts[3].z)/2;
-				dist = sqrtf(powf(vx - gr_viewx, 2) + powf(vy - gr_viewy, 2));
-				vx = (vx - gr_viewx) * renderdist / dist + gr_viewx;
-				vy = (vy - gr_viewy) * renderdist / dist + gr_viewy;
+				// Horizon fills
+				vx = (horizonpts[0].x - gr_viewx) * farrenderdist / renderdist + gr_viewx;
+				vy = (horizonpts[0].z - gr_viewy) * farrenderdist / renderdist + gr_viewy;
+				SETUP3DVERT((&horizonpts[5]), vx, vy);
+				horizonpts[5].y = gr_viewz;
+
+				vx = (horizonpts[3].x - gr_viewx) * farrenderdist / renderdist + gr_viewx;
+				vy = (horizonpts[3].z - gr_viewy) * farrenderdist / renderdist + gr_viewy;
 				SETUP3DVERT((&horizonpts[4]), vx, vy);
+				horizonpts[4].y = gr_viewz;
 
 				// Draw
-				HWD.pfnDrawPolygon(&Surf, horizonpts, 5, PolyFlags);
+				HWD.pfnDrawPolygon(&Surf, horizonpts, 6, PolyFlags);
 			}
 		}
 	}

From f9027ccaebcabed8b7b3de12b1c0efa0d098e22d Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Sun, 22 Mar 2020 12:52:17 -0500
Subject: [PATCH 145/251] Split horizon lines for minimal distortion

---
 src/hardware/hw_main.c | 78 ++++++++++++++++++++++++++----------------
 1 file changed, 48 insertions(+), 30 deletions(-)

diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 253deb282..9a0805d57 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -20,7 +20,6 @@
 
 #include "../doomstat.h"
 
-#define HWRENDER
 #ifdef HWRENDER
 #include "hw_glob.h"
 #include "hw_light.h"
@@ -711,6 +710,10 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 		// Horizon lines
 		FOutVector horizonpts[6];
 		float dist, vx, vy;
+		float x1, y1, xd, yd;
+		UINT8 numplanes, j;
+		vertex_t v; // For determining the closest distance from the line to the camera, to split render planes for minimum distortion;
+
 		const float renderdist = 30000.0f; // How far out to properly render the plane
 		const float farrenderdist = 32768.0f; // From here, raise plane to horizon level to fill in the line with some texture distortion
 
@@ -720,42 +723,57 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 		{
 			if (!line->glseg && line->linedef->special == HORIZONSPECIAL && R_PointOnSegSide(dup_viewx, dup_viewy, line) == 0)
 			{
-				//SETUP3DVERT(horizonpts[1], FIXED_TO_FLOAT(line->v1->x), FIXED_TO_FLOAT(line->v1->y));
-				//SETUP3DVERT(horizonpts[2], FIXED_TO_FLOAT(line->v2->x), FIXED_TO_FLOAT(line->v2->y));
+				P_ClosestPointOnLine(viewx, viewy, line->linedef, &v);
+				dist = FIXED_TO_FLOAT(R_PointToDist(v.x, v.y));
 
-				// Left side
-				vx = ((polyvertex_t *)line->pv1)->x;
-				vy = ((polyvertex_t *)line->pv1)->y;
-				SETUP3DVERT((&horizonpts[1]), vx, vy);
+				x1 = ((polyvertex_t *)line->pv1)->x;
+				y1 = ((polyvertex_t *)line->pv1)->y;
+				xd = ((polyvertex_t *)line->pv2)->x - x1;
+				yd = ((polyvertex_t *)line->pv2)->y - y1;
 
-				dist = sqrtf(powf(vx - gr_viewx, 2) + powf(vy - gr_viewy, 2));
-				vx = (vx - gr_viewx) * renderdist / dist + gr_viewx;
-				vy = (vy - gr_viewy) * renderdist / dist + gr_viewy;
-				SETUP3DVERT((&horizonpts[0]), vx, vy);
+				// Based on the seg length and the distance from the line, split horizon into multiple poly sets to reduce distortion
+				dist = sqrtf((xd*xd) + (yd*yd)) / dist / 16.0f;
+				if (dist > 100.0f)
+					numplanes = 100;
+				else
+					numplanes = (UINT8)dist + 1;
 
-				// Right side
-				vx = ((polyvertex_t *)line->pv2)->x;
-				vy = ((polyvertex_t *)line->pv2)->y;
-				SETUP3DVERT((&horizonpts[2]), vx, vy);
+				for (j = 0; j < numplanes; j++)
+				{
+					// Left side
+					vx = x1 + xd * j / numplanes;
+					vy = y1 + yd * j / numplanes;
+					SETUP3DVERT((&horizonpts[1]), vx, vy);
 
-				dist = sqrtf(powf(vx - gr_viewx, 2) + powf(vy - gr_viewy, 2));
-				vx = (vx - gr_viewx) * renderdist / dist + gr_viewx;
-				vy = (vy - gr_viewy) * renderdist / dist + gr_viewy;
-				SETUP3DVERT((&horizonpts[3]), vx, vy);
+					dist = sqrtf(powf(vx - gr_viewx, 2) + powf(vy - gr_viewy, 2));
+					vx = (vx - gr_viewx) * renderdist / dist + gr_viewx;
+					vy = (vy - gr_viewy) * renderdist / dist + gr_viewy;
+					SETUP3DVERT((&horizonpts[0]), vx, vy);
 
-				// Horizon fills
-				vx = (horizonpts[0].x - gr_viewx) * farrenderdist / renderdist + gr_viewx;
-				vy = (horizonpts[0].z - gr_viewy) * farrenderdist / renderdist + gr_viewy;
-				SETUP3DVERT((&horizonpts[5]), vx, vy);
-				horizonpts[5].y = gr_viewz;
+					// Right side
+					vx = x1 + xd * (j+1) / numplanes;
+					vy = y1 + yd * (j+1) / numplanes;
+					SETUP3DVERT((&horizonpts[2]), vx, vy);
 
-				vx = (horizonpts[3].x - gr_viewx) * farrenderdist / renderdist + gr_viewx;
-				vy = (horizonpts[3].z - gr_viewy) * farrenderdist / renderdist + gr_viewy;
-				SETUP3DVERT((&horizonpts[4]), vx, vy);
-				horizonpts[4].y = gr_viewz;
+					dist = sqrtf(powf(vx - gr_viewx, 2) + powf(vy - gr_viewy, 2));
+					vx = (vx - gr_viewx) * renderdist / dist + gr_viewx;
+					vy = (vy - gr_viewy) * renderdist / dist + gr_viewy;
+					SETUP3DVERT((&horizonpts[3]), vx, vy);
 
-				// Draw
-				HWD.pfnDrawPolygon(&Surf, horizonpts, 6, PolyFlags);
+					// Horizon fills
+					vx = (horizonpts[0].x - gr_viewx) * farrenderdist / renderdist + gr_viewx;
+					vy = (horizonpts[0].z - gr_viewy) * farrenderdist / renderdist + gr_viewy;
+					SETUP3DVERT((&horizonpts[5]), vx, vy);
+					horizonpts[5].y = gr_viewz;
+
+					vx = (horizonpts[3].x - gr_viewx) * farrenderdist / renderdist + gr_viewx;
+					vy = (horizonpts[3].z - gr_viewy) * farrenderdist / renderdist + gr_viewy;
+					SETUP3DVERT((&horizonpts[4]), vx, vy);
+					horizonpts[4].y = gr_viewz;
+
+					// Draw
+					HWD.pfnDrawPolygon(&Surf, horizonpts, 6, PolyFlags);
+				}
 			}
 		}
 	}

From 719f29d27e828c14eb4454ddbceaa056a66c3217 Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Mon, 23 Mar 2020 08:23:36 -0500
Subject: [PATCH 146/251] Reduce near renderdist to lessen visible texture
 distortion

---
 src/hardware/hw_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 9a0805d57..62464c951 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -714,7 +714,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
 		UINT8 numplanes, j;
 		vertex_t v; // For determining the closest distance from the line to the camera, to split render planes for minimum distortion;
 
-		const float renderdist = 30000.0f; // How far out to properly render the plane
+		const float renderdist = 27000.0f; // How far out to properly render the plane
 		const float farrenderdist = 32768.0f; // From here, raise plane to horizon level to fill in the line with some texture distortion
 
 		seg_t *line = &segs[subsector->firstline];

From 99a5192872b6ad9d827985a38de4dc9411c08e38 Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Tue, 24 Mar 2020 16:10:30 +0100
Subject: [PATCH 147/251] Hide record/NiGHTS attack if there are no available
 maps for them.

---
 src/m_menu.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index 6c22c6586..c6babc805 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -7990,12 +7990,18 @@ static void M_CustomLevelSelect(INT32 choice)
 static void M_SinglePlayerMenu(INT32 choice)
 {
 	(void)choice;
-	SP_MainMenu[sptutorial].status =
-		tutorialmap ? IT_CALL|IT_STRING : IT_NOTHING|IT_DISABLED;
-	SP_MainMenu[sprecordattack].status =
-		(M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET;
-	SP_MainMenu[spnightsmode].status =
-		(M_SecretUnlocked(SECRET_NIGHTSMODE)) ? IT_CALL|IT_STRING : IT_SECRET;
+
+	if (M_GametypeHasLevels(LLM_RECORDATTACK))
+		SP_MainMenu[sprecordattack].status = (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET;
+	else
+		SP_MainMenu[sprecordattack].status = IT_NOTHING|IT_DISABLED;
+
+	if (M_GametypeHasLevels(LLM_NIGHTSATTACK))
+		SP_MainMenu[spnightsmode].status = (M_SecretUnlocked(SECRET_NIGHTSMODE)) ? IT_CALL|IT_STRING : IT_SECRET;
+	else
+		SP_MainMenu[spnightsmode].status = IT_NOTHING|IT_DISABLED;
+
+	SP_MainMenu[sptutorial].status = tutorialmap ? IT_CALL|IT_STRING : IT_NOTHING|IT_DISABLED;
 
 	M_SetupNextMenu(&SP_MainDef);
 }

From 92c74814cf20a9351f8bc36887378531155dbf6b Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Wed, 25 Mar 2020 08:34:52 +0100
Subject: [PATCH 148/251] Standardize the behavior of FF_INVERTSIDES and
 FF_INVERTPLANES

---
 src/dehacked.c         |  4 ++--
 src/hardware/hw_main.c | 12 ++++++++----
 src/p_sight.c          |  4 ++--
 src/p_spec.c           |  2 +-
 src/r_bsp.c            |  8 ++++----
 src/r_defs.h           |  4 ++--
 src/r_segs.c           | 28 ++++++++++++++++------------
 7 files changed, 35 insertions(+), 27 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index c6cd0b9e5..20d23d680 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -9648,11 +9648,11 @@ struct {
 	{"FF_CUTEXTRA",FF_CUTEXTRA},               ///< Cuts out hidden translucent pixels.
 	{"FF_CUTLEVEL",FF_CUTLEVEL},               ///< Cuts out all hidden pixels.
 	{"FF_CUTSPRITES",FF_CUTSPRITES},           ///< Final step in making 3D water.
-	{"FF_BOTHPLANES",FF_BOTHPLANES},           ///< Renders both planes all the time.
+	{"FF_BOTHPLANES",FF_BOTHPLANES},           ///< Render inside and outside planes.
 	{"FF_EXTRA",FF_EXTRA},                     ///< Gets cut by ::FF_CUTEXTRA.
 	{"FF_TRANSLUCENT",FF_TRANSLUCENT},         ///< See through!
 	{"FF_FOG",FF_FOG},                         ///< Fog "brush."
-	{"FF_INVERTPLANES",FF_INVERTPLANES},       ///< Reverse the plane visibility rules.
+	{"FF_INVERTPLANES",FF_INVERTPLANES},       ///< Only render inside planes.
 	{"FF_ALLSIDES",FF_ALLSIDES},               ///< Render inside and outside sides.
 	{"FF_INVERTSIDES",FF_INVERTSIDES},         ///< Only render inside sides.
 	{"FF_DOUBLESHADOW",FF_DOUBLESHADOW},       ///< Make two lightlist entries to reset light?
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index c56f0ec06..51c6471ac 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -1902,7 +1902,9 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 		{
 			for (rover = gr_backsector->ffloors; rover; rover = rover->next)
 			{
-				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES) || (rover->flags & FF_INVERTSIDES))
+				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES))
+					continue;
+				if (!(rover->flags & FF_ALLSIDES) && rover->flags & FF_INVERTSIDES)
 					continue;
 				if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
 					continue;
@@ -2042,7 +2044,9 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 		{
 			for (rover = gr_frontsector->ffloors; rover; rover = rover->next)
 			{
-				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_ALLSIDES))
+				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES))
+					continue;
+				if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES))
 					continue;
 				if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
 					continue;
@@ -3427,7 +3431,7 @@ static void HWR_Subsector(size_t num)
 
 			if (centerHeight <= locCeilingHeight &&
 			    centerHeight >= locFloorHeight &&
-			    ((dup_viewz < cullHeight && !(rover->flags & FF_INVERTPLANES)) ||
+			    ((dup_viewz < cullHeight && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) ||
 			     (dup_viewz > cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
 			{
 				if (rover->flags & FF_FOG)
@@ -3488,7 +3492,7 @@ static void HWR_Subsector(size_t num)
 
 			if (centerHeight >= locFloorHeight &&
 			    centerHeight <= locCeilingHeight &&
-			    ((dup_viewz > cullHeight && !(rover->flags & FF_INVERTPLANES)) ||
+			    ((dup_viewz > cullHeight && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) ||
 			     (dup_viewz < cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
 			{
 				if (rover->flags & FF_FOG)
diff --git a/src/p_sight.c b/src/p_sight.c
index c9083b99b..3d1ee9e60 100644
--- a/src/p_sight.c
+++ b/src/p_sight.c
@@ -495,7 +495,7 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
 			if (rover->flags & FF_SOLID)
 				continue; // shortcut since neither mobj can be inside the 3dfloor
 
-			if (!(rover->flags & FF_INVERTPLANES))
+			if (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))
 			{
 				if (los.sightzstart >= topz1 && t2->z + t2->height < topz2)
 					return false; // blocked by upper outside plane
@@ -504,7 +504,7 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
 					return false; // blocked by lower outside plane
 			}
 
-			if (rover->flags & FF_INVERTPLANES || rover->flags & FF_BOTHPLANES)
+			if (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)
 			{
 				if (los.sightzstart < topz1 && t2->z >= topz2)
 					return false; // blocked by upper inside plane
diff --git a/src/p_spec.c b/src/p_spec.c
index cd26dcf9e..dee816e47 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -7069,7 +7069,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 				break;
 
 			case 202: // Fog
-				ffloorflags = FF_EXISTS|FF_RENDERALL|FF_FOG|FF_BOTHPLANES|FF_INVERTPLANES|FF_ALLSIDES|FF_INVERTSIDES|FF_CUTEXTRA|FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES;
+				ffloorflags = FF_EXISTS|FF_RENDERALL|FF_FOG|FF_INVERTPLANES|FF_INVERTSIDES|FF_CUTEXTRA|FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES;
 				sec = sides[*lines[i].sidenum].sector - sectors;
 				// SoM: Because it's fog, check for an extra colormap and set the fog flag...
 				if (sectors[sec].extra_colormap)
diff --git a/src/r_bsp.c b/src/r_bsp.c
index 85113be43..77ab2a82f 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -955,8 +955,8 @@ static void R_Subsector(size_t num)
 				*rover->bottomheight;
 			if (planecenterz <= ceilingcenterz
 				&& planecenterz >= floorcenterz
-				&& ((viewz < heightcheck && !(rover->flags & FF_INVERTPLANES))
-				|| (viewz > heightcheck && (rover->flags & FF_BOTHPLANES))))
+				&& ((viewz < heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES)))
+				|| (viewz > heightcheck && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
 			{
 				light = R_GetPlaneLight(frontsector, planecenterz,
 					viewz < heightcheck);
@@ -993,8 +993,8 @@ static void R_Subsector(size_t num)
 				*rover->topheight;
 			if (planecenterz >= floorcenterz
 				&& planecenterz <= ceilingcenterz
-				&& ((viewz > heightcheck && !(rover->flags & FF_INVERTPLANES))
-				|| (viewz < heightcheck && (rover->flags & FF_BOTHPLANES))))
+				&& ((viewz > heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES)))
+				|| (viewz < heightcheck && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
 			{
 				light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck);
 
diff --git a/src/r_defs.h b/src/r_defs.h
index 0c6ff1d30..5f62ec058 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -130,11 +130,11 @@ typedef enum
 	FF_CUTEXTRA          = 0x100,      ///< Cuts out hidden translucent pixels.
 	FF_CUTLEVEL          = 0x180,      ///< Cuts out all hidden pixels.
 	FF_CUTSPRITES        = 0x200,      ///< Final step in making 3D water.
-	FF_BOTHPLANES        = 0x400,      ///< Renders both planes all the time.
+	FF_BOTHPLANES        = 0x400,      ///< Render inside and outside planes.
 	FF_EXTRA             = 0x800,      ///< Gets cut by ::FF_CUTEXTRA.
 	FF_TRANSLUCENT       = 0x1000,     ///< See through!
 	FF_FOG               = 0x2000,     ///< Fog "brush."
-	FF_INVERTPLANES      = 0x4000,     ///< Reverse the plane visibility rules.
+	FF_INVERTPLANES      = 0x4000,     ///< Only render inside planes.
 	FF_ALLSIDES          = 0x8000,     ///< Render inside and outside sides.
 	FF_INVERTSIDES       = 0x10000,    ///< Only render inside sides.
 	FF_DOUBLESHADOW      = 0x20000,    ///< Make two lightlist entries to reset light?
diff --git a/src/r_segs.c b/src/r_segs.c
index d8f1981ee..d4b07ff13 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -2165,7 +2165,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 				{
 					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS))
 						continue;
-					if (rover->flags & FF_INVERTSIDES)
+					if (!(rover->flags & FF_ALLSIDES) && rover->flags & FF_INVERTSIDES)
 						continue;
 
 					if (rover->norender == leveltime)
@@ -2220,7 +2220,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 				{
 					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS))
 						continue;
-					if (!(rover->flags & FF_ALLSIDES))
+					if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES))
 						continue;
 
 					if (rover->norender == leveltime)
@@ -2275,7 +2275,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			{
 				for (rover = backsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next)
 				{
-					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || rover->flags & FF_INVERTSIDES)
+					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS))
+						continue;
+					if (!(rover->flags & FF_ALLSIDES) && rover->flags & FF_INVERTSIDES)
 						continue;
 					if (rover->norender == leveltime)
 						continue;
@@ -2295,7 +2297,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			{
 				for (rover = frontsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next)
 				{
-					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_ALLSIDES))
+					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS))
+						continue;
+					if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES))
 						continue;
 					if (rover->norender == leveltime)
 						continue;
@@ -2620,8 +2624,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
 					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
-					    ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) ||
-					     (viewz > planevistest && (rover->flags & FF_BOTHPLANES))))
+					    ((viewz < planevistest && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) ||
+					     (viewz > planevistest && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
 					{
 						//ffloor[i].slope = *rover->b_slope;
 						ffloor[i].b_pos = roverleft;
@@ -2643,8 +2647,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
 					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
-					    ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) ||
-					     (viewz < planevistest && (rover->flags & FF_BOTHPLANES))))
+					    ((viewz > planevistest && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) ||
+					     (viewz < planevistest && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
 					{
 						//ffloor[i].slope = *rover->t_slope;
 						ffloor[i].b_pos = roverleft;
@@ -2677,8 +2681,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
 					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
-					    ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) ||
-					     (viewz > planevistest && (rover->flags & FF_BOTHPLANES))))
+					    ((viewz < planevistest && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) ||
+					     (viewz > planevistest && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
 					{
 						//ffloor[i].slope = *rover->b_slope;
 						ffloor[i].b_pos = roverleft;
@@ -2700,8 +2704,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
 					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
-					    ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) ||
-					     (viewz < planevistest && (rover->flags & FF_BOTHPLANES))))
+					    ((viewz > planevistest && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) ||
+					     (viewz < planevistest && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
 					{
 						//ffloor[i].slope = *rover->t_slope;
 						ffloor[i].b_pos = roverleft;

From ce2a1aa3b24108691d7ba58ca6945a8653f0d7c7 Mon Sep 17 00:00:00 2001
From: toaster <rollerorbital@gmail.com>
Date: Sat, 11 Jan 2020 16:24:00 +0000
Subject: [PATCH 149/251] Minor optimisations surrounding
 R_DrawFlippedMaskedColumn.

* Replace the texheight parameter provided directly to it with a previously existing (now renamed) global used for the same purpose, so that it can be used as an interchangeable function pointer with R_DrawMaskedColumn.
* Using the above, optimise R_DrawVisSprite to call a function pointer in a tighter loop rather than check SC_VFLIP each time around.
* SHORT macro can involve repeated operations; calculate once and put in memory for both RANGECHECK and papersprite.
* Remove irrelevant range check (already covered by existing range check immediately above) from R_DrawFlippedMaskedColumn and R_DrawMaskedColumn.
* "Warning: avoiding a crash in %s %d" is a terrible error message, and it chips away at the tightness of the loop just for something most people will never see printed. Replace with a PARANOIA I_Error in case someone actively wants to go hunting for its cause.
---
 src/r_segs.c   | 22 ++++++----------
 src/r_things.c | 68 ++++++++++++++++++++++++--------------------------
 src/r_things.h |  3 ++-
 3 files changed, 41 insertions(+), 52 deletions(-)

diff --git a/src/r_segs.c b/src/r_segs.c
index 0233b1161..32a922147 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -240,14 +240,13 @@ static void R_DrawWallSplats(void)
 //  way we don't have to store extra post_t info with each column for
 //  multi-patch textures. They are not normally needed as multi-patch
 //  textures don't have holes in it. At least not for now.
-static INT32 column2s_length; // column->length : for multi-patch on 2sided wall = texture->height
 
 static void R_Render2sidedMultiPatchColumn(column_t *column)
 {
 	INT32 topscreen, bottomscreen;
 
 	topscreen = sprtopscreen; // + spryscale*column->topdelta;  topdelta is 0 for the wall
-	bottomscreen = topscreen + spryscale * column2s_length;
+	bottomscreen = topscreen + spryscale * lengthcol;
 
 	dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS;
 	dc_yh = (bottomscreen-1)>>FRACBITS;
@@ -279,13 +278,6 @@ static void R_Render2sidedMultiPatchColumn(column_t *column)
 	}
 }
 
-// quick wrapper for R_DrawFlippedMaskedColumn so it can be set as a colfunc_2s value
-// uses column2s_length for texture->height as above
-static void R_DrawFlippedMaskedSegColumn(column_t *column)
-{
-	R_DrawFlippedMaskedColumn(column, column2s_length);
-}
-
 void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 {
 	size_t pindex;
@@ -364,8 +356,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 	{
 		if (textures[texnum]->flip & 2) // vertically flipped?
 		{
-			colfunc_2s = R_DrawFlippedMaskedSegColumn;
-			column2s_length = textures[texnum]->height;
+			colfunc_2s = R_DrawFlippedMaskedColumn;
+			lengthcol = textures[texnum]->height;
 		}
 		else
 			colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture
@@ -373,7 +365,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 	else
 	{
 		colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info)
-		column2s_length = textures[texnum]->height;
+		lengthcol = textures[texnum]->height;
 	}
 
 	// Setup lighting based on the presence/lack-of 3D floors.
@@ -733,7 +725,7 @@ static void R_DrawRepeatMaskedColumn(column_t *col)
 static void R_DrawRepeatFlippedMaskedColumn(column_t *col)
 {
 	do {
-		R_DrawFlippedMaskedColumn(col, column2s_length);
+		R_DrawFlippedMaskedColumn(col);
 		sprtopscreen += dc_texheight*spryscale;
 	} while (sprtopscreen < sprbotscreen);
 }
@@ -1065,7 +1057,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 		if (textures[texnum]->flip & 2) // vertically flipped?
 		{
 			colfunc_2s = R_DrawRepeatFlippedMaskedColumn;
-			column2s_length = textures[texnum]->height;
+			lengthcol = textures[texnum]->height;
 		}
 		else
 			colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture
@@ -1073,7 +1065,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	else
 	{
 		colfunc_2s = R_Render2sidedMultiPatchColumn;        //render multipatch with no holes (no post_t info)
-		column2s_length = textures[texnum]->height;
+		lengthcol = textures[texnum]->height;
 	}
 
 #ifdef ESLOPE
diff --git a/src/r_things.c b/src/r_things.c
index 2fc44faf8..d2f3b4902 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -641,10 +641,10 @@ void R_DrawMaskedColumn(column_t *column)
 			dc_yl = mceilingclip[dc_x]+1;
 		if (dc_yl < 0)
 			dc_yl = 0;
-		if (dc_yh >= vid.height)
+		if (dc_yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop
 			dc_yh = vid.height - 1;
 
-		if (dc_yl <= dc_yh && dc_yl < vid.height && dc_yh > 0)
+		if (dc_yl <= dc_yh && dc_yh > 0)
 		{
 			dc_source = (UINT8 *)column + 3;
 			dc_texturemid = basetexturemid - (topdelta<<FRACBITS);
@@ -655,15 +655,10 @@ void R_DrawMaskedColumn(column_t *column)
 			// quick fix... something more proper should be done!!!
 			if (ylookup[dc_yl])
 				colfunc();
-			else if (colfunc == colfuncs[COLDRAWFUNC_BASE])
-			{
-				static INT32 first = 1;
-				if (first)
-				{
-					CONS_Debug(DBG_RENDER, "WARNING: avoiding a crash in %s %d\n", __FILE__, __LINE__);
-					first = 0;
-				}
-			}
+#ifdef PARANOIA
+			else
+				I_Error("R_DrawMaskedColumn: Invalid ylookup for dc_yl %d", dc_yl);
+#endif
 		}
 		column = (column_t *)((UINT8 *)column + column->length + 4);
 	}
@@ -671,7 +666,9 @@ void R_DrawMaskedColumn(column_t *column)
 	dc_texturemid = basetexturemid;
 }
 
-void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight)
+INT32 lengthcol; // column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height
+
+void R_DrawFlippedMaskedColumn(column_t *column)
 {
 	INT32 topscreen;
 	INT32 bottomscreen;
@@ -687,7 +684,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight)
 		if (topdelta <= prevdelta)
 			topdelta += prevdelta;
 		prevdelta = topdelta;
-		topdelta = texheight-column->length-topdelta;
+		topdelta = lengthcol-column->length-topdelta;
 		topscreen = sprtopscreen + spryscale*topdelta;
 		bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*column->length
 		                                      : sprbotscreen + spryscale*column->length;
@@ -709,10 +706,10 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight)
 			dc_yl = mceilingclip[dc_x]+1;
 		if (dc_yl < 0)
 			dc_yl = 0;
-		if (dc_yh >= vid.height)
+		if (dc_yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop
 			dc_yh = vid.height - 1;
 
-		if (dc_yl <= dc_yh && dc_yl < vid.height && dc_yh > 0)
+		if (dc_yl <= dc_yh && dc_yh > 0)
 		{
 			dc_source = ZZ_Alloc(column->length);
 			for (s = (UINT8 *)column+2+column->length, d = dc_source; d < dc_source+column->length; --s)
@@ -722,15 +719,10 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight)
 			// Still drawn by R_DrawColumn.
 			if (ylookup[dc_yl])
 				colfunc();
-			else if (colfunc == colfuncs[COLDRAWFUNC_BASE])
-			{
-				static INT32 first = 1;
-				if (first)
-				{
-					CONS_Debug(DBG_RENDER, "WARNING: avoiding a crash in %s %d\n", __FILE__, __LINE__);
-					first = 0;
-				}
-			}
+#ifdef PARANOIA
+			else
+				I_Error("R_DrawMaskedColumn: Invalid ylookup for dc_yl %d", dc_yl);
+#endif
 			Z_Free(dc_source);
 		}
 		column = (column_t *)((UINT8 *)column + column->length + 4);
@@ -746,7 +738,9 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight)
 static void R_DrawVisSprite(vissprite_t *vis)
 {
 	column_t *column;
+	void (*localcolfunc)(column_t *);
 	INT32 texturecolumn;
+	INT32 pwidth;
 	fixed_t frac;
 	patch_t *patch = vis->patch;
 	fixed_t this_scale = vis->mobj->scale;
@@ -895,50 +889,52 @@ static void R_DrawVisSprite(vissprite_t *vis)
 	if (vis->x2 >= vid.width)
 		vis->x2 = vid.width-1;
 
+	localcolfunc = (vis->cut & SC_VFLIP) ? R_DrawFlippedMaskedColumn : R_DrawMaskedColumn;
+	lengthcol = patch->height;
+
 	// Split drawing loops for paper and non-paper to reduce conditional checks per sprite
 	if (vis->scalestep)
 	{
-		// Papersprite drawing loop
+		pwidth = SHORT(patch->width);
 
+		// Papersprite drawing loop
 		for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += vis->scalestep)
 		{
 			angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF;
 			texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / this_scale;
 
-			if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
+			if (texturecolumn < 0 || texturecolumn >= pwidth)
 				continue;
 
 			if (vis->xiscale < 0) // Flipped sprite
-				texturecolumn = SHORT(patch->width) - 1 - texturecolumn;
+				texturecolumn = pwidth - 1 - texturecolumn;
 
 			sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale));
 			dc_iscale = (0xffffffffu / (unsigned)spryscale);
 
 			column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
 
-			if (vis->cut & SC_VFLIP)
-				R_DrawFlippedMaskedColumn(column, patch->height);
-			else
-				R_DrawMaskedColumn(column);
+			localcolfunc (column);
 		}
 	}
 	else
 	{
+#ifdef RANGECHECK
+		pwidth = SHORT(patch->width);
+#endif
+
 		// Non-paper drawing loop
 		for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan)
 		{
 #ifdef RANGECHECK
 			texturecolumn = frac>>FRACBITS;
-			if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
+			if (texturecolumn < 0 || texturecolumn >= pwidth)
 				I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x);
 			column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn]));
 #else
 			column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS]));
 #endif
-			if (vis->cut & SC_VFLIP)
-				R_DrawFlippedMaskedColumn(column, patch->height);
-			else
-				R_DrawMaskedColumn(column);
+			localcolfunc (column);
 		}
 	}
 
diff --git a/src/r_things.h b/src/r_things.h
index 05d6fb27b..7a0fe3a60 100644
--- a/src/r_things.h
+++ b/src/r_things.h
@@ -44,9 +44,10 @@ extern fixed_t sprtopscreen;
 extern fixed_t sprbotscreen;
 extern fixed_t windowtop;
 extern fixed_t windowbottom;
+extern INT32 lengthcol;
 
 void R_DrawMaskedColumn(column_t *column);
-void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight);
+void R_DrawFlippedMaskedColumn(column_t *column);
 
 // ----------------
 // SPRITE RENDERING

From da86c17ee112b833c6fe29192105e192be548656 Mon Sep 17 00:00:00 2001
From: toaster <rollerorbital@gmail.com>
Date: Thu, 26 Mar 2020 20:16:44 +0000
Subject: [PATCH 150/251] Disable continues outside of no-save/Ultimate by
 default, but allow SOC to re-enable them globally.

Please look at the merge request description for a full explanation, since I know the vanilla team has been hashing this out and I don't want to add fuel to the fire without at least presenting a solid case.
---
 src/dehacked.c |  4 +++
 src/doomstat.h |  2 ++
 src/f_finale.c |  6 ++--
 src/g_game.c   |  4 ++-
 src/m_cheat.c  |  6 ++++
 src/m_menu.c   | 84 +++++++++++++++++++++++++++++++++++++-------------
 src/m_menu.h   |  2 +-
 src/p_inter.c  |  5 ++-
 src/p_user.c   |  6 ++--
 src/y_inter.c  |  2 +-
 10 files changed, 90 insertions(+), 31 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index 20d23d680..6d6fdf838 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -4122,6 +4122,10 @@ static void readmaincfg(MYFILE *f)
 			{
 				maxXtraLife = (UINT8)get_number(word2);
 			}
+			else if (fastcmp(word, "USECONTINUES"))
+			{
+				useContinues = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y');
+			}
 
 			else if (fastcmp(word, "GAMEDATA"))
 			{
diff --git a/src/doomstat.h b/src/doomstat.h
index 893514b32..aedb120ff 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -575,6 +575,8 @@ extern UINT8 creditscutscene;
 
 extern UINT8 use1upSound;
 extern UINT8 maxXtraLife; // Max extra lives from rings
+extern UINT8 useContinues;
+#define continuesInSession (!multiplayer && (useContinues || ultimatemode || !(cursaveslot > 0)))
 
 extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations
 
diff --git a/src/f_finale.c b/src/f_finale.c
index 95535a7ea..825f646b0 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -3618,7 +3618,7 @@ void F_StartContinue(void)
 {
 	I_Assert(!netgame && !multiplayer);
 
-	if (players[consoleplayer].continues <= 0)
+	if (continuesInSession && players[consoleplayer].continues <= 0)
 	{
 		Command_ExitGame_f();
 		return;
@@ -3725,7 +3725,9 @@ void F_ContinueDrawer(void)
 	}
 
 	// Draw the continue markers! Show continues.
-	if (ncontinues > 10)
+	if (!continuesInSession)
+		;
+	else if (ncontinues > 10)
 	{
 		if (!(continuetime & 1) || continuetime > 17)
 			V_DrawContinueIcon(x, 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor);
diff --git a/src/g_game.c b/src/g_game.c
index 6dba6045a..92d71fbae 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -219,6 +219,7 @@ UINT8 ammoremovaltics = 2*TICRATE;
 
 UINT8 use1upSound = 0;
 UINT8 maxXtraLife = 2; // Max extra lives from rings
+UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scenarioes
 
 UINT8 introtoplay;
 UINT8 creditscutscene;
@@ -3859,7 +3860,8 @@ static void G_DoContinued(void)
 	I_Assert(!netgame && !multiplayer);
 	I_Assert(pl->continues > 0);
 
-	pl->continues--;
+	if (pl->continues)
+		pl->continues--;
 
 	// Reset score
 	pl->score = 0;
diff --git a/src/m_cheat.c b/src/m_cheat.c
index 4a1a4fb58..f6fdb63e9 100644
--- a/src/m_cheat.c
+++ b/src/m_cheat.c
@@ -934,6 +934,12 @@ void Command_Setcontinues_f(void)
 	REQUIRE_NOULTIMATE;
 	REQUIRE_PANDORA;
 
+	if (!continuesInSession)
+	{
+		CONS_Printf(M_GetText("This session does not use continues.\n"));
+		return;
+	}
+
 	if (COM_Argc() > 1)
 	{
 		INT32 numcontinues = atoi(COM_Argv(1));
diff --git a/src/m_menu.c b/src/m_menu.c
index f8240d403..a08b40909 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -6724,6 +6724,7 @@ static void M_PandorasBox(INT32 choice)
 	else
 		CV_StealthSetValue(&cv_dummylives, max(players[consoleplayer].lives, 1));
 	CV_StealthSetValue(&cv_dummycontinues, players[consoleplayer].continues);
+	SR_PandorasBox[3].status = (continuesInSession) ? (IT_STRING | IT_CVAR) : (IT_GRAYEDOUT);
 	SR_PandorasBox[6].status = (players[consoleplayer].charflags & SF_SUPER) ? (IT_GRAYEDOUT) : (IT_STRING | IT_CALL);
 	SR_PandorasBox[7].status = (emeralds == ((EMERALD7)*2)-1) ? (IT_GRAYEDOUT) : (IT_STRING | IT_CALL);
 	M_SetupNextMenu(&SR_PandoraDef);
@@ -6740,7 +6741,7 @@ static boolean M_ExitPandorasBox(void)
 	}
 	if (cv_dummylives.value != players[consoleplayer].lives)
 		COM_ImmedExecute(va("setlives %d", cv_dummylives.value));
-	if (cv_dummycontinues.value != players[consoleplayer].continues)
+	if (continuesInSession && cv_dummycontinues.value != players[consoleplayer].continues)
 		COM_ImmedExecute(va("setcontinues %d", cv_dummycontinues.value));
 	return true;
 }
@@ -8251,9 +8252,19 @@ static void M_DrawLoadGameData(void)
 				V_DrawRightAlignedThinString(x + 79, y, V_YELLOWMAP, savegameinfo[savetodraw].levelname);
 		}
 
-		if ((savegameinfo[savetodraw].lives == -42)
-		|| (savegameinfo[savetodraw].lives == -666))
+		if (savegameinfo[savetodraw].lives == -42)
+		{
+			if (!useContinues)
+				V_DrawRightAlignedThinString(x + 80, y+1+60+16, V_GRAYMAP, "00000000");
 			continue;
+		}
+
+		if (savegameinfo[savetodraw].lives == -666)
+		{
+			if (!useContinues)
+				V_DrawRightAlignedThinString(x + 80, y+1+60+16, V_REDMAP, "????????");
+			continue;
+		}
 
 		y += 64;
 
@@ -8270,7 +8281,7 @@ static void M_DrawLoadGameData(void)
 
 		y -= 4;
 
-		// character heads, lives, and continues
+		// character heads, lives, and continues/score
 		{
 			spritedef_t *sprdef;
 			spriteframe_t *sprframe;
@@ -8321,10 +8332,14 @@ skipbot:
 skipsign:
 			y += 16;
 
-			tempx = x + 10;
-			if (savegameinfo[savetodraw].lives != INFLIVES
-			&& savegameinfo[savetodraw].lives > 9)
-				tempx -= 4;
+			tempx = x;
+			if (useContinues)
+			{
+				tempx += 10;
+				if (savegameinfo[savetodraw].lives != INFLIVES
+				&& savegameinfo[savetodraw].lives > 9)
+					tempx -= 4;
+			}
 
 			if (!charskin) // shut up compiler
 				goto skiplife;
@@ -8354,22 +8369,45 @@ skiplife:
 			else
 				V_DrawString(tempx, y, 0, va("%d", savegameinfo[savetodraw].lives));
 
-			tempx = x + 47;
-			if (savegameinfo[savetodraw].continues > 9)
-				tempx -= 4;
-
-			// continues
-			if (savegameinfo[savetodraw].continues > 0)
+			if (!useContinues)
 			{
-				V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTSAVE", PU_PATCH));
-				V_DrawScaledPatch(tempx + 9, y + 2, 0, patch);
-				V_DrawString(tempx + 16, y, 0, va("%d", savegameinfo[savetodraw].continues));
+				INT32 workingscorenum = savegameinfo[savetodraw].continuescore;
+				char workingscorestr[11] = " 000000000\0";
+				SINT8 j = 9;
+				// Change the above two lines if MAXSCORE ever changes from 8 digits long.
+				workingscorestr[0] = '\x86'; // done here instead of in initialiser 'cuz compiler complains
+				if (!workingscorenum)
+					j--; // just so ONE digit is not greyed out
+				else
+				{
+					while (workingscorenum)
+					{
+						workingscorestr[j--] = '0' + (workingscorenum % 10);
+						workingscorenum /= 10;
+					}
+				}
+				workingscorestr[j] = (savegameinfo[savetodraw].continuescore == MAXSCORE) ? '\x83' : '\x80';
+				V_DrawRightAlignedThinString(x + 80, y+1, 0, workingscorestr);
 			}
 			else
 			{
-				V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTNONE", PU_PATCH));
-				V_DrawScaledPatch(tempx + 9, y + 2, 0, W_CachePatchName("STNONEX", PU_PATCH));
-				V_DrawString(tempx + 16, y, V_GRAYMAP, "0");
+				tempx = x + 47;
+				if (savegameinfo[savetodraw].continuescore > 9)
+					tempx -= 4;
+
+				// continues
+				if (savegameinfo[savetodraw].continuescore > 0)
+				{
+					V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTSAVE", PU_PATCH));
+					V_DrawScaledPatch(tempx + 9, y + 2, 0, patch);
+					V_DrawString(tempx + 16, y, 0, va("%d", savegameinfo[savetodraw].continuescore));
+				}
+				else
+				{
+					V_DrawSmallScaledPatch(tempx, y, 0, W_CachePatchName("CONTNONE", PU_PATCH));
+					V_DrawScaledPatch(tempx + 9, y + 2, 0, W_CachePatchName("STNONEX", PU_PATCH));
+					V_DrawString(tempx + 16, y, V_GRAYMAP, "0");
+				}
 			}
 		}
 	}
@@ -8502,9 +8540,11 @@ static void M_ReadSavegameInfo(UINT32 slot)
 	CHECKPOS
 	savegameinfo[slot].lives = READSINT8(save_p); // lives
 	CHECKPOS
-	(void)READINT32(save_p); // Score
+	savegameinfo[slot].continuescore = READINT32(save_p); // score
 	CHECKPOS
-	savegameinfo[slot].continues = READINT32(save_p); // continues
+	fake = READINT32(save_p); // continues
+	if (useContinues)
+		savegameinfo[slot].continuescore = fake;
 
 	// File end marker check
 	CHECKPOS
diff --git a/src/m_menu.h b/src/m_menu.h
index e7270380d..eeda9cc58 100644
--- a/src/m_menu.h
+++ b/src/m_menu.h
@@ -397,7 +397,7 @@ typedef struct
 	UINT8 numemeralds;
 	UINT8 numgameovers;
 	INT32 lives;
-	INT32 continues;
+	INT32 continuescore;
 	INT32 gamemap;
 } saveinfo_t;
 
diff --git a/src/p_inter.c b/src/p_inter.c
index 67d197375..b568fb359 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -633,7 +633,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 
 			if (ALL7EMERALDS(emeralds)) // Got all 7
 			{
-				if (!(netgame || multiplayer))
+				if (continuesInSession)
 				{
 					player->continues += 1;
 					player->gotcontinue = true;
@@ -643,7 +643,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 						S_StartSound(toucher, sfx_chchng);
 				}
 				else
+				{
+					P_GiveCoopLives(player, 1, true); // if continues are disabled, a life is a reasonable substitute
 					S_StartSound(toucher, sfx_chchng);
+				}
 			}
 			else
 			{
diff --git a/src/p_user.c b/src/p_user.c
index 612e31cbc..5ceaa45fb 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -1388,7 +1388,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
 
 					// Continues are worthless in netgames.
 					// If that stops being the case uncomment this.
-/*					if (!ultimatemode && players[i].marescore > 50000
+/*					if (!ultimatemode && continuesInSession && players[i].marescore > 50000
 					&& oldscore < 50000)
 					{
 						players[i].continues += 1;
@@ -1408,7 +1408,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
 			else
 				player->marescore = MAXSCORE;
 
-			if (!ultimatemode && !(netgame || multiplayer) && G_IsSpecialStage(gamemap)
+			if (!ultimatemode && continuesInSession && G_IsSpecialStage(gamemap)
 			&& player->marescore >= 50000 && oldscore < 50000)
 			{
 				player->continues += 1;
@@ -9539,7 +9539,7 @@ static void P_DeathThink(player_t *player)
 	// continue logic
 	if (!(netgame || multiplayer) && player->lives <= 0)
 	{
-		if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_USE || cmd->buttons & BT_JUMP) && player->continues > 0)
+		if (player->deadtimer > (3*TICRATE) && (cmd->buttons & BT_USE || cmd->buttons & BT_JUMP) && (!continuesInSession || player->continues > 0))
 			G_UseContinue();
 		else if (player->deadtimer >= gameovertics)
 			G_UseContinue(); // Even if we don't have one this handles ending the game
diff --git a/src/y_inter.c b/src/y_inter.c
index 94a289817..f1764a816 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -564,7 +564,7 @@ dontdrawbg:
 			V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125+yoffset, 0, data.spec.score);
 
 			// Draw continues!
-			if (!multiplayer /* && (data.spec.continues & 0x80) */) // Always draw outside of netplay
+			if (continuesInSession /* && (data.spec.continues & 0x80) */) // Always draw when continues are a thing
 			{
 				UINT8 continues = data.spec.continues & 0x7F;
 

From 8130599a4f01378e67308c98570e43df80e1118c Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Sat, 28 Mar 2020 15:23:15 +0100
Subject: [PATCH 151/251] Fix disconnected players being kicked for high ping

---
 src/d_clisrv.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 71e32977a..92602d68a 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -4855,7 +4855,8 @@ static inline void PingUpdate(void)
 	{
 		for (i = 1; i < MAXPLAYERS; i++)
 		{
-			if (playeringame[i] && (realpingtable[i] / pingmeasurecount > (unsigned)cv_maxping.value))
+			if (playeringame[i] && !players[i].quittime
+			&& (realpingtable[i] / pingmeasurecount > (unsigned)cv_maxping.value))
 			{
 				if (players[i].jointime > 30 * TICRATE)
 					laggers[i] = true;
@@ -4874,8 +4875,8 @@ static inline void PingUpdate(void)
 				if (playeringame[i] && laggers[i])
 				{
 					pingtimeout[i]++;
+					// ok your net has been bad for too long, you deserve to die.
 					if (pingtimeout[i] > cv_pingtimeout.value)
-// ok your net has been bad for too long, you deserve to die.
 					{
 						pingtimeout[i] = 0;
 						SendKick(i, KICK_MSG_PING_HIGH | KICK_MSG_KEEP_BODY);

From 2e27b3ea87cdc870774a1cbe068494d9a1df233d Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Mon, 30 Mar 2020 19:58:46 +0100
Subject: [PATCH 152/251] Turn the fixed-float convert macros into inline
 functions, like those in GZDoom. The old macros get to be just the same as
 calling these inline functions.

---
 src/m_fixed.h | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/m_fixed.h b/src/m_fixed.h
index 7fdb9ad0a..49e7cc096 100644
--- a/src/m_fixed.h
+++ b/src/m_fixed.h
@@ -38,8 +38,20 @@ typedef INT32 fixed_t;
 /*!
   \brief convert fixed_t into floating number
 */
-#define FIXED_TO_FLOAT(x) (((float)(x)) / ((float)FRACUNIT))
-#define FLOAT_TO_FIXED(f) (fixed_t)((f) * ((float)FRACUNIT))
+
+FUNCMATH FUNCINLINE static inline float FixedToFloat(fixed_t x)
+{
+	return x / (float)FRACUNIT;
+}
+
+FUNCMATH FUNCINLINE static inline fixed_t FloatToFixed(float f)
+{
+	return (fixed_t)(f * FRACUNIT);
+}
+
+// for backwards compat
+#define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT))
+#define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT))
 
 
 #if defined (__WATCOMC__) && FRACBITS == 16

From befae492fe996ddedd4e9c6e0feaaa74a3b889bd Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Mon, 30 Mar 2020 20:25:56 +0100
Subject: [PATCH 153/251] use ATTRINLINE rather than inline to match some of
 the other functions in this file, though I'm told modern compilers ignore
 inlining info as they actually decide themselves now

(though I could pretend we still support the older ones lol)
---
 src/m_fixed.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/m_fixed.h b/src/m_fixed.h
index 49e7cc096..cc54c1aea 100644
--- a/src/m_fixed.h
+++ b/src/m_fixed.h
@@ -39,12 +39,12 @@ typedef INT32 fixed_t;
   \brief convert fixed_t into floating number
 */
 
-FUNCMATH FUNCINLINE static inline float FixedToFloat(fixed_t x)
+FUNCMATH FUNCINLINE static ATTRINLINE float FixedToFloat(fixed_t x)
 {
 	return x / (float)FRACUNIT;
 }
 
-FUNCMATH FUNCINLINE static inline fixed_t FloatToFixed(float f)
+FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f)
 {
 	return (fixed_t)(f * FRACUNIT);
 }

From ad12e29fda52e5b75c01f36fdecfdd1d65a3f4d5 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Mon, 30 Mar 2020 22:11:48 +0200
Subject: [PATCH 154/251] Fix allowjoin off affecting single player

---
 src/d_clisrv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index aa5d4cb9a..56ce21c3d 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -1338,7 +1338,7 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
 	netbuffer->u.serverinfo.numberofplayer = (UINT8)D_NumPlayers();
 	netbuffer->u.serverinfo.maxplayer = (UINT8)cv_maxplayers.value;
 
-	if (FindRejoinerNum(node) != -1)
+	if (!node || FindRejoinerNum(node) != -1)
 		netbuffer->u.serverinfo.refusereason = 0;
 	else if (!cv_allownewplayer.value)
 		netbuffer->u.serverinfo.refusereason = 1;

From 3074880ac1c7e5259998fb3df4c1372d7d386d75 Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Thu, 2 Apr 2020 16:07:38 +0200
Subject: [PATCH 155/251] Actually check for available maps correctly. Whoops!

---
 src/m_menu.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index c6babc805..a40aea89e 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -7991,12 +7991,14 @@ static void M_SinglePlayerMenu(INT32 choice)
 {
 	(void)choice;
 
-	if (M_GametypeHasLevels(LLM_RECORDATTACK))
+	levellistmode = LLM_RECORDATTACK;
+	if (M_PrepareLevelPlatter(-1, true))
 		SP_MainMenu[sprecordattack].status = (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET;
 	else
 		SP_MainMenu[sprecordattack].status = IT_NOTHING|IT_DISABLED;
 
-	if (M_GametypeHasLevels(LLM_NIGHTSATTACK))
+	levellistmode = LLM_NIGHTSATTACK;
+	if (M_PrepareLevelPlatter(-1, true))
 		SP_MainMenu[spnightsmode].status = (M_SecretUnlocked(SECRET_NIGHTSMODE)) ? IT_CALL|IT_STRING : IT_SECRET;
 	else
 		SP_MainMenu[spnightsmode].status = IT_NOTHING|IT_DISABLED;

From 806884a3f4cce2744cdf626982279e8ef3494f3f Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Thu, 2 Apr 2020 17:59:56 +0200
Subject: [PATCH 156/251] Use M_GametypeHasLevels again (properly this time) to
 save memory.

---
 src/m_menu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index a40aea89e..4af94e77b 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -7992,13 +7992,13 @@ static void M_SinglePlayerMenu(INT32 choice)
 	(void)choice;
 
 	levellistmode = LLM_RECORDATTACK;
-	if (M_PrepareLevelPlatter(-1, true))
+	if (M_GametypeHasLevels(-1))
 		SP_MainMenu[sprecordattack].status = (M_SecretUnlocked(SECRET_RECORDATTACK)) ? IT_CALL|IT_STRING : IT_SECRET;
 	else
 		SP_MainMenu[sprecordattack].status = IT_NOTHING|IT_DISABLED;
 
 	levellistmode = LLM_NIGHTSATTACK;
-	if (M_PrepareLevelPlatter(-1, true))
+	if (M_GametypeHasLevels(-1))
 		SP_MainMenu[spnightsmode].status = (M_SecretUnlocked(SECRET_NIGHTSMODE)) ? IT_CALL|IT_STRING : IT_SECRET;
 	else
 		SP_MainMenu[spnightsmode].status = IT_NOTHING|IT_DISABLED;

From dc25177457176814670975bf08eb7b36d20cc780 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Thu, 9 Apr 2020 17:30:53 -0700
Subject: [PATCH 157/251] You don't need to push the value twice, it's only
 used once

---
 src/lua_infolib.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index b7902ef79..a82403097 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -1631,7 +1631,6 @@ int LUA_InfoLib(lua_State *L)
 			lua_pushcfunction(L, lib_spriteinfolen);
 			lua_setfield(L, -2, "__len");
 		lua_setmetatable(L, -2);
-	lua_pushvalue(L, -1);
 	lua_setglobal(L, "spriteinfo");
 
 	luaL_newmetatable(L, META_LUABANKS);

From 6845aca6e5cf2292b5586dbf01ea0be80c9225af Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Thu, 9 Apr 2020 20:52:23 -0500
Subject: [PATCH 158/251] Make chdir usage consistent with other source usage

---
 src/d_main.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/d_main.c b/src/d_main.c
index 8519e6281..80f075cb1 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -909,7 +909,13 @@ static void IdentifyVersion(void)
 		}
 
 		CONS_Printf("%s\n", srb2path);
-		chdir(srb2path);
+
+#if defined (_WIN32)
+		SetCurrentDirectoryA(srb2path);
+#else
+		if (chdir(srb2path) == -1)
+			I_OutputMsg("Couldn't change working directory\n");
+#endif
 	}
 
 #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)

From be07a23e5265aceea62f18acce09c1e7cdda31af Mon Sep 17 00:00:00 2001
From: fickleheart <fickle@tinted.red>
Date: Thu, 9 Apr 2020 20:56:27 -0500
Subject: [PATCH 159/251] Make a separate function instead of clogging up
 IdentifyVersion

---
 src/d_main.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/src/d_main.c b/src/d_main.c
index 80f075cb1..a0672bb4e 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -880,15 +880,10 @@ static inline void D_CleanFile(void)
 	}
 }
 
-// ==========================================================================
-// Identify the SRB2 version, and IWAD file to use.
-// ==========================================================================
-
-static void IdentifyVersion(void)
+///\brief Checks if a netgame URL is being handled, and changes working directory to the EXE's if so.
+///       Done because browsers (at least, Firefox on Windows) launch the game from the browser's directory, which causes problems.
+static void ChangeDirForUrlHandler(void)
 {
-	char *srb2wad;
-	const char *srb2waddir = NULL;
-
 	// URL handlers are opened by web browsers (at least Firefox) from the browser's working directory, not the game's stored directory,
 	// so chdir to that directory unless overridden.
 	if (M_GetUrlProtocolArg() != NULL && !M_CheckParm("-nochdir"))
@@ -917,6 +912,16 @@ static void IdentifyVersion(void)
 			I_OutputMsg("Couldn't change working directory\n");
 #endif
 	}
+}
+
+// ==========================================================================
+// Identify the SRB2 version, and IWAD file to use.
+// ==========================================================================
+
+static void IdentifyVersion(void)
+{
+	char *srb2wad;
+	const char *srb2waddir = NULL;
 
 #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
 	// change to the directory where 'srb2.pk3' is found
@@ -1097,6 +1102,9 @@ void D_SRB2Main(void)
 	// Test Dehacked lists
 	DEH_Check();
 
+	// Netgame URL special case: change working dir to EXE folder.
+	ChangeDirForUrlHandler();
+
 	// identify the main IWAD file to use
 	IdentifyVersion();
 

From 4214397679c70a7910c82126783b434f0d10343e Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Sun, 12 Apr 2020 17:05:18 -0700
Subject: [PATCH 160/251] Make the PACKETVERSION rule easier

---
 src/d_clisrv.h | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index 10a1d714d..2ddebadba 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -20,12 +20,9 @@
 #include "d_player.h"
 
 /*
-The 'packet version' may be used with packets whose
-format is expected to change between versions.
-
-This version is independent of the mod name, and standard
-version and subversion. It should only account for the
-basic fields of the packet, and change infrequently.
+The 'packet version' is used to distinguish packet formats.
+This version is independent of VERSION and SUBVERSION. Different
+applications may follow different packet versions.
 */
 #define PACKETVERSION 2
 

From 711c35970c0c467c3a78c87aa8a7c851c16e9614 Mon Sep 17 00:00:00 2001
From: Nev3r <apophycens@gmail.com>
Date: Mon, 13 Apr 2020 14:31:19 +0200
Subject: [PATCH 161/251] Refactor an unholy piece of code.

---
 src/p_floor.c | 132 ++++++++++++++++++++++++++++----------------------
 1 file changed, 74 insertions(+), 58 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index b8b40df3c..2923eeda0 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -48,13 +48,7 @@ result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crus
 	boolean flag;
 	fixed_t lastpos;
 	fixed_t destheight; // used to keep floors/ceilings from moving through each other
-	// Stuff used for mobj hacks.
-	INT32 secnum = -1;
 	mobj_t *mo = NULL;
-	sector_t *sec = NULL;
-	ffloor_t *rover = NULL;
-	boolean sectorisffloor = false;
-	boolean sectorisquicksand = false;
 
 	sector->moved = true;
 
@@ -193,41 +187,37 @@ result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crus
 			break;
 	}
 
-	// Hack for buggy mobjs to move by gravity with moving planes.
+	// If this is an FOF being checked, check all the affected sectors for moving mobjs.
 	if (sector->tagline)
-		sectorisffloor = true;
-
-	// Optimization condition. If the sector is not an FOF, declare sec as the main sector outside of the loop.
-	if (!sectorisffloor)
-		sec = sector;
-
-	// Optimization condition. Only run the logic if there is any Things in the sector.
-	if (sectorisffloor || sec->thinglist)
 	{
-		// If this is an FOF being checked, check all the affected sectors for moving mobjs.
-		while ((sectorisffloor ? (secnum = P_FindSectorFromLineTag(sector->tagline, secnum)) : (secnum = 1)) >= 0)
-		{
-			if (sectorisffloor)
-			{
-				// Get actual sector from the list of sectors.
-				sec = &sectors[secnum];
+		boolean sectorisquicksand = false;
+		sector_t *sec;
+		ffloor_t *rover;
+		INT32 secnum;
 
-				// Can't use P_InQuicksand because it will return the incorrect result
-				// because of checking for heights.
-				for (rover = sec->ffloors; rover; rover = rover->next)
+		while (secnum = P_FindSectorFromLineTag(sector->tagline, secnum) >= 0)
+		{
+			// Get actual sector from the list of sectors.
+			sec = &sectors[secnum];
+
+			if (!sec->thinglist)
+				continue;
+
+			// Can't use P_InQuicksand because it will return the incorrect result
+			// because of checking for heights.
+			for (rover = sec->ffloors; rover; rover = rover->next)
+			{
+				if (rover->target == sec && (rover->flags & FF_QUICKSAND))
 				{
-					if (rover->target == sec && (rover->flags & FF_QUICKSAND))
-					{
-						sectorisquicksand = true;
-						break;
-					}
+					sectorisquicksand = true;
+					break;
 				}
 			}
 
 			for (mo = sec->thinglist; mo; mo = mo->snext)
 			{
 				// The object should be ready to move as defined by this function.
-				if (!P_MobjReadyToMove(mo, sec, sectorisffloor, sectorisquicksand))
+				if (!P_MobjReadyToMove(mo, sec, true, sectorisquicksand))
 					continue;
 
 				// The object should not be moving at all.
@@ -237,39 +227,65 @@ result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crus
 				// These objects will be affected by this condition.
 				switch (mo->type)
 				{
-					case MT_GOOP: // Egg Slimer's goop objects
-					case MT_SPINFIRE: // Elemental Shield flame balls
-					case MT_SPIKE: // Floor Spike
-						// Is the object hang from the ceiling?
-						// In that case, swap the planes used.
-						// verticalflip inverts
-						if (!!(mo->flags & MF_SPAWNCEILING) ^ !!(mo->eflags & MFE_VERTICALFLIP))
-						{
-							if (sectorisffloor && !sectorisquicksand)
-								mo->z = mo->ceilingz - mo->height;
-							else
-								mo->z = mo->ceilingz = mo->subsector->sector->ceilingheight - mo->height;
-						}
+				case MT_GOOP: // Egg Slimer's goop objects
+				case MT_SPINFIRE: // Elemental Shield flame balls
+				case MT_SPIKE: // Floor Spike
+					// Is the object hang from the ceiling?
+					// In that case, swap the planes used.
+					// verticalflip inverts
+					if (!!(mo->flags & MF_SPAWNCEILING) ^ !!(mo->eflags & MFE_VERTICALFLIP))
+					{
+						if (!sectorisquicksand)
+							mo->z = mo->ceilingz - mo->height;
 						else
-						{
-							if (sectorisffloor && !sectorisquicksand)
-								mo->z = mo->floorz;
-							else
-								mo->z = mo->floorz = mo->subsector->sector->floorheight;
-						}
-						break;
-					// Kill warnings...
-					default:
-						break;
+							mo->z = mo->ceilingz = mo->subsector->sector->ceilingheight - mo->height;
+					}
+					else
+					{
+						if (!sectorisquicksand)
+							mo->z = mo->floorz;
+						else
+							mo->z = mo->floorz = mo->subsector->sector->floorheight;
+					}
+					break;
+				default:
+					break;
 				}
 			}
-
-			// Break from loop if there is no FOFs to check.
-			if (!sectorisffloor)
-				break;
 		}
 	}
 
+	// Only run the logic if there is any mobjs in the sector.
+	if (sector->thinglist)
+		for (mo = sector->thinglist; mo; mo = mo->snext)
+		{
+			// The object should be ready to move as defined by this function.
+			if (!P_MobjReadyToMove(mo, sector, false, false))
+				continue;
+
+			// The object should not be moving at all.
+			if (mo->momx || mo->momy || mo->momz)
+				continue;
+
+			// These objects will be affected by this condition.
+			switch (mo->type)
+			{
+			case MT_GOOP: // Egg Slimer's goop objects
+			case MT_SPINFIRE: // Elemental Shield flame balls
+			case MT_SPIKE: // Floor Spike
+				// Is the object hang from the ceiling?
+				// In that case, swap the planes used.
+				// verticalflip inverts
+				if (!!(mo->flags & MF_SPAWNCEILING) ^ !!(mo->eflags & MFE_VERTICALFLIP))
+					mo->z = mo->ceilingz = mo->subsector->sector->ceilingheight - mo->height;
+				else
+					mo->z = mo->floorz = mo->subsector->sector->floorheight;
+				break;
+			default:
+				break;
+			}
+		}
+
 	return ok;
 }
 

From 74bd23c275f5c57fc5a5f31659fb752e79acddcf Mon Sep 17 00:00:00 2001
From: Nev3r <apophycens@gmail.com>
Date: Mon, 13 Apr 2020 15:17:53 +0200
Subject: [PATCH 162/251] Actually remove the entire code block in
 T_MovePlane(), and remove line_t.tagline as it served no other purpose.

---
 src/p_floor.c | 101 --------------------------------------------------
 src/p_setup.c |   1 -
 src/p_spec.c  |   2 -
 src/r_defs.h  |   5 ---
 4 files changed, 109 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 2923eeda0..078ee187b 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -48,8 +48,6 @@ result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crus
 	boolean flag;
 	fixed_t lastpos;
 	fixed_t destheight; // used to keep floors/ceilings from moving through each other
-	mobj_t *mo = NULL;
-
 	sector->moved = true;
 
 	switch (floorOrCeiling)
@@ -187,105 +185,6 @@ result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crus
 			break;
 	}
 
-	// If this is an FOF being checked, check all the affected sectors for moving mobjs.
-	if (sector->tagline)
-	{
-		boolean sectorisquicksand = false;
-		sector_t *sec;
-		ffloor_t *rover;
-		INT32 secnum;
-
-		while (secnum = P_FindSectorFromLineTag(sector->tagline, secnum) >= 0)
-		{
-			// Get actual sector from the list of sectors.
-			sec = &sectors[secnum];
-
-			if (!sec->thinglist)
-				continue;
-
-			// Can't use P_InQuicksand because it will return the incorrect result
-			// because of checking for heights.
-			for (rover = sec->ffloors; rover; rover = rover->next)
-			{
-				if (rover->target == sec && (rover->flags & FF_QUICKSAND))
-				{
-					sectorisquicksand = true;
-					break;
-				}
-			}
-
-			for (mo = sec->thinglist; mo; mo = mo->snext)
-			{
-				// The object should be ready to move as defined by this function.
-				if (!P_MobjReadyToMove(mo, sec, true, sectorisquicksand))
-					continue;
-
-				// The object should not be moving at all.
-				if (mo->momx || mo->momy || mo->momz)
-					continue;
-
-				// These objects will be affected by this condition.
-				switch (mo->type)
-				{
-				case MT_GOOP: // Egg Slimer's goop objects
-				case MT_SPINFIRE: // Elemental Shield flame balls
-				case MT_SPIKE: // Floor Spike
-					// Is the object hang from the ceiling?
-					// In that case, swap the planes used.
-					// verticalflip inverts
-					if (!!(mo->flags & MF_SPAWNCEILING) ^ !!(mo->eflags & MFE_VERTICALFLIP))
-					{
-						if (!sectorisquicksand)
-							mo->z = mo->ceilingz - mo->height;
-						else
-							mo->z = mo->ceilingz = mo->subsector->sector->ceilingheight - mo->height;
-					}
-					else
-					{
-						if (!sectorisquicksand)
-							mo->z = mo->floorz;
-						else
-							mo->z = mo->floorz = mo->subsector->sector->floorheight;
-					}
-					break;
-				default:
-					break;
-				}
-			}
-		}
-	}
-
-	// Only run the logic if there is any mobjs in the sector.
-	if (sector->thinglist)
-		for (mo = sector->thinglist; mo; mo = mo->snext)
-		{
-			// The object should be ready to move as defined by this function.
-			if (!P_MobjReadyToMove(mo, sector, false, false))
-				continue;
-
-			// The object should not be moving at all.
-			if (mo->momx || mo->momy || mo->momz)
-				continue;
-
-			// These objects will be affected by this condition.
-			switch (mo->type)
-			{
-			case MT_GOOP: // Egg Slimer's goop objects
-			case MT_SPINFIRE: // Elemental Shield flame balls
-			case MT_SPIKE: // Floor Spike
-				// Is the object hang from the ceiling?
-				// In that case, swap the planes used.
-				// verticalflip inverts
-				if (!!(mo->flags & MF_SPAWNCEILING) ^ !!(mo->eflags & MFE_VERTICALFLIP))
-					mo->z = mo->ceilingz = mo->subsector->sector->ceilingheight - mo->height;
-				else
-					mo->z = mo->floorz = mo->subsector->sector->floorheight;
-				break;
-			default:
-				break;
-			}
-		}
-
 	return ok;
 }
 
diff --git a/src/p_setup.c b/src/p_setup.c
index 6c6ecbc5d..700113d85 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -872,7 +872,6 @@ static void P_InitializeSector(sector_t *ss)
 
 	ss->linecount = 0;
 	ss->lines = NULL;
-	ss->tagline = NULL;
 
 	ss->ffloors = NULL;
 	ss->attached = NULL;
diff --git a/src/p_spec.c b/src/p_spec.c
index 50b767535..ad22d1a54 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -5772,8 +5772,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
 		sec2->floorheight = tempceiling;
 	}
 
-	sec2->tagline = master;
-
 	if (sec2->numattached == 0)
 	{
 		sec2->attached = Z_Malloc(sizeof (*sec2->attached) * sec2->maxattached, PU_STATIC, NULL);
diff --git a/src/r_defs.h b/src/r_defs.h
index 5f62ec058..10c0721ac 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -328,11 +328,6 @@ typedef struct sector_s
 
 	size_t linecount;
 	struct line_s **lines; // [linecount] size
-	// Hack: store special line tagging to some sectors
-	// to efficiently help work around bugs by directly
-	// referencing the specific line that the problem happens in.
-	// (used in T_MovePlane mobj physics)
-	struct line_s *tagline;
 
 	// Improved fake floor hack
 	ffloor_t *ffloors;

From 01c0797ba6965c110b37c385c02c3718d962bb90 Mon Sep 17 00:00:00 2001
From: Nev3r <apophycens@gmail.com>
Date: Mon, 13 Apr 2020 16:00:58 +0200
Subject: [PATCH 163/251] Remove now unused P_MobjReadyToMove().

---
 src/p_floor.c | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 078ee187b..aa05c6af2 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -26,19 +26,6 @@
 //                              FLOORS
 // ==========================================================================
 
-//
-// Mini-P_IsObjectOnGroundIn for T_MovePlane hack
-//
-static inline boolean P_MobjReadyToMove(mobj_t *mo, sector_t *sec, boolean sectorisffloor, boolean sectorisquicksand)
-{
-	if (sectorisquicksand)
-		return (mo->z > sec->floorheight && mo->z < sec->ceilingheight);
-	else if (!!(mo->flags & MF_SPAWNCEILING) ^ !!(mo->eflags & MFE_VERTICALFLIP))
-		return ((sectorisffloor) ? (mo->z+mo->height != sec->floorheight) : (mo->z+mo->height != sec->ceilingheight));
-	else
-		return ((sectorisffloor) ? (mo->z != sec->ceilingheight) : (mo->z != sec->floorheight));
-}
-
 //
 // Move a plane (floor or ceiling) and check for crushing
 //

From 01b28b66a6d47c604457561e01dd33ac7693ec84 Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Mon, 13 Apr 2020 17:10:25 +0200
Subject: [PATCH 164/251] Make linedef type 461 able to set object angle, using
 the line's angle.

---
 extras/conf/SRB2-22.cfg | 3 ++-
 src/p_spec.c            | 4 ++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg
index ec030b32f..a59771b2d 100644
--- a/extras/conf/SRB2-22.cfg
+++ b/extras/conf/SRB2-22.cfg
@@ -15,7 +15,7 @@
 	* Oogaland
 	* Rob
 	* Shadow Hog
-	* Spherallic
+	* sphere
 	* SRB2-Playah
 	* SSNTails
 	* SteelT
@@ -2214,6 +2214,7 @@ linedeftypes
 			title = "Spawn Object";
 			prefix = "(461)";
 			flags8text = "[3] Set delay by backside sector";
+			flags32text = "[5] Use line angle for object";
 			flags64text = "[6] Spawn inside a range";
 		}
 
diff --git a/src/p_spec.c b/src/p_spec.c
index 50b767535..13280f3fe 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -4027,7 +4027,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 
 				mobj = P_SpawnMobj(x, y, z, type);
 				if (mobj)
+				{
+					if (line->flags & ML_EFFECT1)
+						mobj->angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y);
 					CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow.
+				}
 				else
 					CONS_Alert(CONS_ERROR,"Linedef Type %d - Spawn Object: Object did not spawn!\n", line->special);
 			}

From 778ef86fee107d820701ba16eabaaa9b0687321f Mon Sep 17 00:00:00 2001
From: Nev3r <apophycens@gmail.com>
Date: Tue, 14 Apr 2020 10:31:07 +0200
Subject: [PATCH 165/251] Remove the bridge thinker code.

---
 src/p_floor.c | 472 --------------------------------------------------
 src/p_saveg.c |  10 --
 src/p_spec.c  |  52 +-----
 src/p_spec.h  |   1 -
 4 files changed, 6 insertions(+), 529 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index b8b40df3c..b916014b2 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1275,478 +1275,6 @@ void T_FloatSector(levelspecthink_t *floater)
 	}
 }
 
-//
-// T_BridgeThinker
-//
-// Kind of like T_RaiseSector,
-// but spreads out across
-// multiple FOFs at varying
-// intensity.
-//
-void T_BridgeThinker(levelspecthink_t *bridge)
-{
-	msecnode_t *node;
-	mobj_t *thing;
-	sector_t *sector;
-	sector_t *controlsec = NULL;
-	INT32 i, k;
-
-	INT16 j;
-	boolean playeronme = false;
-	fixed_t ceilingdestination = 0, floordestination = 0;
-	result_e res = 0;
-
-#define ORIGFLOORHEIGHT (bridge->vars[0])
-#define ORIGCEILINGHEIGHT (bridge->vars[1])
-#define BASESPEED (bridge->vars[2])
-#define CURSPEED (bridge->vars[3])
-#define STARTTAG ((INT16)bridge->vars[4])
-#define ENDTAG ((INT16)bridge->vars[5])
-#define DIRECTION (bridge->vars[8])
-#define SAGAMT (8*FRACUNIT)
-	fixed_t lowceilheight = ORIGCEILINGHEIGHT - SAGAMT;
-	fixed_t lowfloorheight = ORIGFLOORHEIGHT - SAGAMT;
-#define LOWCEILINGHEIGHT (lowceilheight)
-#define LOWFLOORHEIGHT (lowfloorheight)
-#define STARTCONTROLTAG (ENDTAG + 1)
-#define ENDCONTROLTAG (ENDTAG + (ENDTAG - STARTTAG) + 1)
-
-	// Is someone standing on it?
-	for (j = STARTTAG; j <= ENDTAG; j++)
-	{
-		for (i = -1; (i = P_FindSectorFromTag(j, i)) >= 0 ;)
-		{
-			sector = &sectors[i];
-
-			// Nab the control sector that this sector belongs to.
-			k = P_FindSectorFromTag((INT16)(j + (ENDTAG-STARTTAG) + 1), -1);
-
-			if (k == -1)
-				break;
-
-			controlsec = &sectors[k];
-
-			// Is a player standing on me?
-			for (node = sector->touching_thinglist; node; node = node->m_thinglist_next)
-			{
-				thing = node->m_thing;
-
-				if (!thing->player)
-					continue;
-
-				if (!(thing->z == controlsec->ceilingheight))
-					continue;
-
-				playeronme = true;
-				goto wegotit; // Just take the first one?
-			}
-		}
-	}
-wegotit:
-	if (playeronme)
-	{
-		// Lower controlsec like a regular T_RaiseSector
-		// Set the heights of all the other control sectors to
-		// be a gradient of this height toward the edges
-	}
-	else
-	{
-		// Raise controlsec like a regular T_RaiseSector
-		// Set the heights of all the other control sectors to
-		// be a gradient of this height toward the edges.
-	}
-
-	if (playeronme && controlsec)
-	{
-		INT32 dist;
-
-		bridge->sector = controlsec;
-		CURSPEED = BASESPEED;
-
-		{
-			// Translate tags to - 0 + range
-			/*so you have a number in [min, max].
-			let range = max - min, subtract min
-			from your number to get [0, range].
-			subtract range/2 to get [-range/2, range/2].
-			take absolute value and get [0, range/2] where
-			lower number = closer to midpoint. divide by
-			range/2 to get [0, 1]. subtract that number
-			from 1 to get [0, 1] with higher number = closer
-			to midpoint. multiply this by max sag amount*/
-
-			INT32 midpoint = STARTCONTROLTAG + ((ENDCONTROLTAG-STARTCONTROLTAG) + 1)/2;
-//			INT32 tagstart = STARTTAG - midpoint;
-//			INT32 tagend = ENDTAG - midpoint;
-
-//			CONS_Debug(DBG_GAMELOGIC, "tagstart is %d, tagend is %d\n", tagstart, tagend);
-
-			// Sag is adjusted by how close you are to the center
-			dist = ((ENDCONTROLTAG - STARTCONTROLTAG))/2 - abs(bridge->sector->tag - midpoint);
-
-//			CONS_Debug(DBG_GAMELOGIC, "Dist is %d\n", dist);
-			LOWCEILINGHEIGHT -= (SAGAMT) * dist;
-			LOWFLOORHEIGHT -= (SAGAMT) * dist;
-		}
-
-		// go down
-		if (bridge->sector->ceilingheight <= LOWCEILINGHEIGHT)
-		{
-			bridge->sector->floorheight = LOWCEILINGHEIGHT - (bridge->sector->ceilingheight - bridge->sector->floorheight);
-			bridge->sector->ceilingheight = LOWCEILINGHEIGHT;
-			bridge->sector->ceilspeed = 0;
-			bridge->sector->floorspeed = 0;
-			goto dorest;
-		}
-
-		DIRECTION = -1;
-		ceilingdestination = LOWCEILINGHEIGHT;
-		floordestination = LOWFLOORHEIGHT;
-
-		if ((bridge->sector->ceilingheight - LOWCEILINGHEIGHT)
-			< (ORIGCEILINGHEIGHT - bridge->sector->ceilingheight))
-		{
-			fixed_t origspeed = CURSPEED;
-
-			// Slow down as you get closer to the bottom
-			CURSPEED = FixedMul(CURSPEED,FixedDiv(bridge->sector->ceilingheight - LOWCEILINGHEIGHT, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5));
-
-			if (CURSPEED <= origspeed/16)
-				CURSPEED = origspeed/16;
-			else if (CURSPEED > origspeed)
-				CURSPEED = origspeed;
-		}
-		else
-		{
-			fixed_t origspeed = CURSPEED;
-			// Slow down as you get closer to the top
-			CURSPEED = FixedMul(CURSPEED,FixedDiv(ORIGCEILINGHEIGHT - bridge->sector->ceilingheight, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5));
-
-			if (CURSPEED <= origspeed/16)
-				CURSPEED = origspeed/16;
-			else if (CURSPEED > origspeed)
-				CURSPEED = origspeed;
-		}
-
-//		CONS_Debug(DBG_GAMELOGIC, "Curspeed is %d\n", CURSPEED>>FRACBITS);
-
-		res = T_MovePlane
-		(
-			bridge->sector,         // sector
-			CURSPEED,          // speed
-			ceilingdestination, // dest
-			0,                        // crush
-			1,                        // floor or ceiling (1 for ceiling)
-			DIRECTION       // direction
-		);
-
-		if (res == ok || res == pastdest)
-			T_MovePlane
-			(
-				bridge->sector,           // sector
-				CURSPEED,            // speed
-				floordestination, // dest
-				0,                          // crush
-				0,                          // floor or ceiling (0 for floor)
-				DIRECTION         // direction
-			);
-
-		bridge->sector->ceilspeed = 42;
-		bridge->sector->floorspeed = CURSPEED*DIRECTION;
-
-	dorest:
-		// Adjust joined sector heights
-		{
-			sector_t *sourcesec = bridge->sector;
-
-			INT32 divisor = sourcesec->tag - ENDTAG + 1;
-			fixed_t heightdiff = ORIGCEILINGHEIGHT - sourcesec->ceilingheight;
-			fixed_t interval;
-			INT32 plusplusme = 0;
-
-			if (divisor > 0)
-			{
-				interval = heightdiff/divisor;
-
-//				CONS_Debug(DBG_GAMELOGIC, "interval is %d\n", interval>>FRACBITS);
-
-				// TODO: Use T_MovePlane
-
-				for (j = (INT16)(ENDTAG+1); j <= sourcesec->tag; j++, plusplusme++)
-				{
-					for (i = -1; (i = P_FindSectorFromTag(j, i)) >= 0 ;)
-					{
-						if (sectors[i].ceilingheight >= sourcesec->ceilingheight)
-						{
-							sectors[i].ceilingheight = ORIGCEILINGHEIGHT - (interval*plusplusme);
-							sectors[i].floorheight = ORIGFLOORHEIGHT - (interval*plusplusme);
-						}
-						else // Do the regular rise
-						{
-							bridge->sector = &sectors[i];
-
-							CURSPEED = BASESPEED/2;
-
-							// rise back up
-							if (bridge->sector->ceilingheight >= ORIGCEILINGHEIGHT)
-							{
-								bridge->sector->floorheight = ORIGCEILINGHEIGHT - (bridge->sector->ceilingheight - bridge->sector->floorheight);
-								bridge->sector->ceilingheight = ORIGCEILINGHEIGHT;
-								bridge->sector->ceilspeed = 0;
-								bridge->sector->floorspeed = 0;
-								continue;
-							}
-
-							DIRECTION = 1;
-							ceilingdestination = ORIGCEILINGHEIGHT;
-							floordestination = ORIGFLOORHEIGHT;
-
-//							CONS_Debug(DBG_GAMELOGIC, "ceildest: %d, floordest: %d\n", ceilingdestination>>FRACBITS, floordestination>>FRACBITS);
-
-							if ((bridge->sector->ceilingheight - LOWCEILINGHEIGHT)
-								< (ORIGCEILINGHEIGHT - bridge->sector->ceilingheight))
-							{
-								fixed_t origspeed = CURSPEED;
-
-								// Slow down as you get closer to the bottom
-								CURSPEED = FixedMul(CURSPEED,FixedDiv(bridge->sector->ceilingheight - LOWCEILINGHEIGHT, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5));
-
-								if (CURSPEED <= origspeed/16)
-									CURSPEED = origspeed/16;
-								else if (CURSPEED > origspeed)
-									CURSPEED = origspeed;
-							}
-							else
-							{
-								fixed_t origspeed = CURSPEED;
-								// Slow down as you get closer to the top
-								CURSPEED = FixedMul(CURSPEED,FixedDiv(ORIGCEILINGHEIGHT - bridge->sector->ceilingheight, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5));
-
-								if (CURSPEED <= origspeed/16)
-									CURSPEED = origspeed/16;
-								else if (CURSPEED > origspeed)
-									CURSPEED = origspeed;
-							}
-
-							res = T_MovePlane
-							(
-								bridge->sector,         // sector
-								CURSPEED,          // speed
-								ceilingdestination, // dest
-								0,                        // crush
-								1,                        // floor or ceiling (1 for ceiling)
-								DIRECTION       // direction
-							);
-
-							if (res == ok || res == pastdest)
-								T_MovePlane
-								(
-									bridge->sector,           // sector
-									CURSPEED,            // speed
-									floordestination, // dest
-									0,                          // crush
-									0,                          // floor or ceiling (0 for floor)
-									DIRECTION         // direction
-								);
-
-							bridge->sector->ceilspeed = 42;
-							bridge->sector->floorspeed = CURSPEED*DIRECTION;
-						}
-					}
-				}
-			}
-
-			// Now the other side
-			divisor = ENDTAG + (ENDTAG-STARTTAG) + 1;
-			divisor -= sourcesec->tag;
-
-			if (divisor > 0)
-			{
-				interval = heightdiff/divisor;
-				plusplusme = 0;
-
-//				CONS_Debug(DBG_GAMELOGIC, "interval2 is %d\n", interval>>FRACBITS);
-
-				for (j = (INT16)(sourcesec->tag+1); j <= ENDTAG + (ENDTAG-STARTTAG) + 1; j++, plusplusme++)
-				{
-					for (i = -1; (i = P_FindSectorFromTag(j, i)) >= 0 ;)
-					{
-						if (sectors[i].ceilingheight >= sourcesec->ceilingheight)
-						{
-							sectors[i].ceilingheight = sourcesec->ceilingheight + (interval*plusplusme);
-							sectors[i].floorheight = sourcesec->floorheight + (interval*plusplusme);
-						}
-						else // Do the regular rise
-						{
-							bridge->sector = &sectors[i];
-
-							CURSPEED = BASESPEED/2;
-
-							// rise back up
-							if (bridge->sector->ceilingheight >= ORIGCEILINGHEIGHT)
-							{
-								bridge->sector->floorheight = ORIGCEILINGHEIGHT - (bridge->sector->ceilingheight - bridge->sector->floorheight);
-								bridge->sector->ceilingheight = ORIGCEILINGHEIGHT;
-								bridge->sector->ceilspeed = 0;
-								bridge->sector->floorspeed = 0;
-								continue;
-							}
-
-							DIRECTION = 1;
-							ceilingdestination = ORIGCEILINGHEIGHT;
-							floordestination = ORIGFLOORHEIGHT;
-
-//							CONS_Debug(DBG_GAMELOGIC, "ceildest: %d, floordest: %d\n", ceilingdestination>>FRACBITS, floordestination>>FRACBITS);
-
-							if ((bridge->sector->ceilingheight - LOWCEILINGHEIGHT)
-								< (ORIGCEILINGHEIGHT - bridge->sector->ceilingheight))
-							{
-								fixed_t origspeed = CURSPEED;
-
-								// Slow down as you get closer to the bottom
-								CURSPEED = FixedMul(CURSPEED,FixedDiv(bridge->sector->ceilingheight - LOWCEILINGHEIGHT, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5));
-
-								if (CURSPEED <= origspeed/16)
-									CURSPEED = origspeed/16;
-								else if (CURSPEED > origspeed)
-									CURSPEED = origspeed;
-							}
-							else
-							{
-								fixed_t origspeed = CURSPEED;
-								// Slow down as you get closer to the top
-								CURSPEED = FixedMul(CURSPEED,FixedDiv(ORIGCEILINGHEIGHT - bridge->sector->ceilingheight, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5));
-
-								if (CURSPEED <= origspeed/16)
-									CURSPEED = origspeed/16;
-								else if (CURSPEED > origspeed)
-									CURSPEED = origspeed;
-							}
-
-							res = T_MovePlane
-							(
-								bridge->sector,         // sector
-								CURSPEED,          // speed
-								ceilingdestination, // dest
-								0,                        // crush
-								1,                        // floor or ceiling (1 for ceiling)
-								DIRECTION       // direction
-							);
-
-							if (res == ok || res == pastdest)
-								T_MovePlane
-								(
-									bridge->sector,           // sector
-									CURSPEED,            // speed
-									floordestination, // dest
-									0,                          // crush
-									0,                          // floor or ceiling (0 for floor)
-									DIRECTION         // direction
-								);
-
-							bridge->sector->ceilspeed = 42;
-							bridge->sector->floorspeed = CURSPEED*DIRECTION;
-						}
-					}
-				}
-			}
-		}
-
-	//	for (i = -1; (i = P_FindSectorFromTag(bridge->sourceline->tag, i)) >= 0 ;)
-	//		P_RecalcPrecipInSector(&sectors[i]);
-	}
-	else
-	{
-		// Iterate control sectors
-		for (j = (INT16)(ENDTAG+1); j <= (ENDTAG+(ENDTAG-STARTTAG)+1); j++)
-		{
-			for (i = -1; (i = P_FindSectorFromTag(j, i)) >= 0 ;)
-			{
-				bridge->sector = &sectors[i];
-
-				CURSPEED = BASESPEED/2;
-
-				// rise back up
-				if (bridge->sector->ceilingheight >= ORIGCEILINGHEIGHT)
-				{
-					bridge->sector->floorheight = ORIGCEILINGHEIGHT - (bridge->sector->ceilingheight - bridge->sector->floorheight);
-					bridge->sector->ceilingheight = ORIGCEILINGHEIGHT;
-					bridge->sector->ceilspeed = 0;
-					bridge->sector->floorspeed = 0;
-					continue;
-				}
-
-				DIRECTION = 1;
-				ceilingdestination = ORIGCEILINGHEIGHT;
-				floordestination = ORIGFLOORHEIGHT;
-
-//				CONS_Debug(DBG_GAMELOGIC, "ceildest: %d, floordest: %d\n", ceilingdestination>>FRACBITS, floordestination>>FRACBITS);
-
-				if ((bridge->sector->ceilingheight - LOWCEILINGHEIGHT)
-					< (ORIGCEILINGHEIGHT - bridge->sector->ceilingheight))
-				{
-					fixed_t origspeed = CURSPEED;
-
-					// Slow down as you get closer to the bottom
-					CURSPEED = FixedMul(CURSPEED,FixedDiv(bridge->sector->ceilingheight - LOWCEILINGHEIGHT, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5));
-
-					if (CURSPEED <= origspeed/16)
-						CURSPEED = origspeed/16;
-					else if (CURSPEED > origspeed)
-						CURSPEED = origspeed;
-				}
-				else
-				{
-					fixed_t origspeed = CURSPEED;
-					// Slow down as you get closer to the top
-					CURSPEED = FixedMul(CURSPEED,FixedDiv(ORIGCEILINGHEIGHT - bridge->sector->ceilingheight, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5));
-
-					if (CURSPEED <= origspeed/16)
-						CURSPEED = origspeed/16;
-					else if (CURSPEED > origspeed)
-						CURSPEED = origspeed;
-				}
-
-				res = T_MovePlane
-				(
-					bridge->sector,         // sector
-					CURSPEED,          // speed
-					ceilingdestination, // dest
-					0,                        // crush
-					1,                        // floor or ceiling (1 for ceiling)
-					DIRECTION       // direction
-				);
-
-				if (res == ok || res == pastdest)
-					T_MovePlane
-					(
-						bridge->sector,           // sector
-						CURSPEED,            // speed
-						floordestination, // dest
-						0,                          // crush
-						0,                          // floor or ceiling (0 for floor)
-						DIRECTION         // direction
-					);
-
-				bridge->sector->ceilspeed = 42;
-				bridge->sector->floorspeed = CURSPEED*DIRECTION;
-			}
-		}
-		// Update precip
-	}
-
-#undef SAGAMT
-#undef LOWFLOORHEIGHT
-#undef LOWCEILINGHEIGHT
-#undef ORIGFLOORHEIGHT
-#undef ORIGCEILINGHEIGHT
-#undef BASESPEED
-#undef CURSPEED
-#undef STARTTAG
-#undef ENDTAG
-#undef DIRECTION
-}
-
 static mobj_t *SearchMarioNode(msecnode_t *node)
 {
 	mobj_t *thing = NULL;
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 716904432..259e58168 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1275,7 +1275,6 @@ typedef enum
 	tc_marioblockchecker,
 	tc_spikesector,
 	tc_floatsector,
-	tc_bridgethinker,
 	tc_crushceiling,
 	tc_scroll,
 	tc_friction,
@@ -2291,11 +2290,6 @@ static void P_NetArchiveThinkers(void)
 				SaveSpecialLevelThinker(th, tc_floatsector);
 				continue;
 			}
-			else if (th->function.acp1 == (actionf_p1)T_BridgeThinker)
-			{
-				SaveSpecialLevelThinker(th, tc_bridgethinker);
-				continue;
-			}
 			else if (th->function.acp1 == (actionf_p1)T_LaserFlash)
 			{
 				SaveLaserThinker(th, tc_laserflash);
@@ -3487,10 +3481,6 @@ static void P_NetUnArchiveThinkers(void)
 					th = LoadSpecialLevelThinker((actionf_p1)T_FloatSector, 0);
 					break;
 
-				case tc_bridgethinker:
-					th = LoadSpecialLevelThinker((actionf_p1)T_BridgeThinker, 3);
-					break;
-
 				case tc_laserflash:
 					th = LoadLaserThinker((actionf_p1)T_LaserFlash);
 					break;
diff --git a/src/p_spec.c b/src/p_spec.c
index 50b767535..8e56f2efe 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -2041,7 +2041,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 				INT32 triggercolor = (INT32)sides[triggerline->sidenum[0]].toptexture;
 				UINT8 color = (actor->player ? actor->player->powers[pw_dye] : actor->color);
 				boolean invert = (triggerline->flags & ML_NOCLIMB ? true : false);
-				
+
 				if (invert ^ (triggercolor != color))
 					return false;
 			}
@@ -4050,23 +4050,23 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				}
 			}
 			break;
-		
+
 		case 463: // Dye object
 			{
 				INT32 color = sides[line->sidenum[0]].toptexture;
-				
+
 				if (mo)
 				{
 					if (color < 0 || color >= MAXTRANSLATIONS)
 						return;
-					
+
 					var1 = 0;
 					var2 = color;
 					A_Dye(mo);
 				}
 			}
 			break;
-		
+
 #ifdef POLYOBJECTS
 		case 480: // Polyobj_DoorSlide
 		case 481: // Polyobj_DoorSwing
@@ -5975,39 +5975,6 @@ static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline)
 	floater->sourceline = sourceline;
 }
 
-/** Adds a bridge thinker.
-  * Bridge thinkers cause a group of FOFs to behave like
-  * a bridge made up of pieces, that bows under weight.
-  *
-  * \param sec          Control sector.
-  * \sa P_SpawnSpecials, T_BridgeThinker
-  * \author SSNTails <http://www.ssntails.org>
-  */
-/*
-static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec)
-{
-	levelspecthink_t *bridge;
-
-	// create an initialize new thinker
-	bridge = Z_Calloc(sizeof (*bridge), PU_LEVSPEC, NULL);
-	P_AddThinker(THINK_MAIN, &bridge->thinker);
-
-	bridge->thinker.function.acp1 = (actionf_p1)T_BridgeThinker;
-
-	bridge->sector = sec;
-	bridge->vars[0] = sourceline->frontsector->floorheight;
-	bridge->vars[1] = sourceline->frontsector->ceilingheight;
-	bridge->vars[2] = P_AproxDistance(sourceline->dx, sourceline->dy); // Speed
-	bridge->vars[2] = FixedDiv(bridge->vars[2], 16*FRACUNIT);
-	bridge->vars[3] = bridge->vars[2];
-
-	// Start tag and end tag are TARGET SECTORS, not CONTROL SECTORS
-	// Control sector tags should be End_Tag + (End_Tag - Start_Tag)
-	bridge->vars[4] = sourceline->tag; // Start tag
-	bridge->vars[5] = (sides[sourceline->sidenum[0]].textureoffset>>FRACBITS); // End tag
-}
-*/
-
 /**
   * Adds a plane displacement thinker.
   * Whenever the "control" sector moves,
@@ -6753,13 +6720,6 @@ void P_SpawnSpecials(boolean fromnetsave)
 					}
 				break;
 
-			case 65: // Bridge Thinker
-				/*
-				// Disable this until it's working right!
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-					P_AddBridgeThinker(&lines[i], &sectors[s]);*/
-				break;
-
 			case 66: // Displace floor by front sector
 				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
 					P_AddPlaneDisplaceThinker(pd_floor, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB));
@@ -7287,7 +7247,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 			case 331:
 			case 333:
 				break;
-			
+
 			// Object dye executors
 			case 334:
 			case 336:
diff --git a/src/p_spec.h b/src/p_spec.h
index 6377059b6..d756f1942 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -354,7 +354,6 @@ void T_StartCrumble(elevator_t *elevator);
 void T_MarioBlock(levelspecthink_t *block);
 void T_SpikeSector(levelspecthink_t *spikes);
 void T_FloatSector(levelspecthink_t *floater);
-void T_BridgeThinker(levelspecthink_t *bridge);
 void T_MarioBlockChecker(levelspecthink_t *block);
 void T_ThwompSector(levelspecthink_t *thwomp);
 void T_NoEnemiesSector(levelspecthink_t *nobaddies);

From 98481dc10b24f43d77b146dfcd42b87496c60827 Mon Sep 17 00:00:00 2001
From: Nev3r <apophycens@gmail.com>
Date: Tue, 14 Apr 2020 10:31:26 +0200
Subject: [PATCH 166/251] Remove the bridge thinker entry from the ZB
 configuration.

---
 extras/conf/SRB2-22.cfg | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg
index ec030b32f..b918cdb26 100644
--- a/extras/conf/SRB2-22.cfg
+++ b/extras/conf/SRB2-22.cfg
@@ -738,12 +738,6 @@ linedeftypes
 			flags2text = "[1] Use control sector tag";
 			flags64text = "[6] No sound effect";
 		}
-
-		65
-		{
-			title = "Bridge Thinker <disabled>";
-			prefix = "(65)";
-		}
 	}
 
 	polyobject

From d0c473c9ae817314f8860e084807e8d9f5db74ed Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 17 Apr 2020 09:58:53 +0200
Subject: [PATCH 167/251] Make T_RaiseSector use its own thinker struct instead
 of levelspecthink_t

---
 src/p_floor.c | 130 +++++++++++++++++++++++++-------------------------
 src/p_saveg.c |  49 ++++++++++++++++++-
 src/p_spec.c  |  79 ++++++++++--------------------
 src/p_spec.h  |  26 +++++++++-
 4 files changed, 163 insertions(+), 121 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 7ab1dc1f6..d43900be7 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1847,7 +1847,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
 // Rises up to its topmost position when a
 // player steps on it. Lowers otherwise.
 //
-void T_RaiseSector(levelspecthink_t *raise)
+void T_RaiseSector(raise_t *raise)
 {
 	msecnode_t *node;
 	mobj_t *thing;
@@ -1877,7 +1877,7 @@ void T_RaiseSector(levelspecthink_t *raise)
 				continue;
 
 			// Option to require spindashing.
-			if (raise->vars[1] && !(thing->player->pflags & PF_STARTDASH))
+			if (raise->flags & RF_SPINDASH && !(thing->player->pflags & PF_STARTDASH))
 				continue;
 
 			if (!(thing->z == P_GetSpecialTopZ(thing, raise->sector, sector)))
@@ -1888,43 +1888,43 @@ void T_RaiseSector(levelspecthink_t *raise)
 		}
 	}
 
-	if (raise->vars[9]) // Dynamically Sinking Platform^tm
+	if (raise->flags & RF_DYNAMIC) // Dynamically Sinking Platform^tm
 	{
 #define shaketime 10
-		if (raise->vars[11] > shaketime) // State: moving
+		if (raise->shaketimer > shaketime) // State: moving
 		{
 			if (playeronme) // If player is standing on the platform, accelerate
 			{
-				raise->vars[10] += (FRACUNIT >> 5);
+				raise->extraspeed += (FRACUNIT >> 5);
 			}
 			else // otherwise, decelerate until inflection
 			{
-				raise->vars[10] -= FRACUNIT >> 3;
-				if (raise->vars[10] <= 0) // inflection!
+				raise->extraspeed -= FRACUNIT >> 3;
+				if (raise->extraspeed <= 0) // inflection!
 				{
-					raise->vars[10] = 0;
-					raise->vars[11] = 0; // allow the shake to occur again (fucks over players attempting to jump-cheese)
+					raise->extraspeed = 0;
+					raise->shaketimer = 0; // allow the shake to occur again (fucks over players attempting to jump-cheese)
 				}
 			}
-			active = raise->vars[10] > 0;
+			active = raise->extraspeed > 0;
 		}
 		else // State: shaking
 		{
-			if (playeronme || raise->vars[11])
+			if (playeronme || raise->shaketimer)
 			{
 				active = true;
-				if (++raise->vars[11] > shaketime)
+				if (++raise->shaketimer > shaketime)
 				{
 					if (playeronme)
-						raise->vars[10] = FRACUNIT >> 5;
+						raise->extraspeed = FRACUNIT >> 5;
 					else
-						raise->vars[10] = FRACUNIT << 1;
+						raise->extraspeed = FRACUNIT << 1;
 				}
 				else
 				{
-					raise->vars[10] = ((shaketime/2) - raise->vars[11]) << FRACBITS;
-					if (raise->vars[10] < -raise->vars[2]/2)
-						raise->vars[10] = -raise->vars[2]/2;
+					raise->extraspeed = ((shaketime/2) - raise->shaketimer) << FRACBITS;
+					if (raise->extraspeed < -raise->basespeed/2)
+						raise->extraspeed = -raise->basespeed/2;
 				}
 			}
 		}
@@ -1935,123 +1935,123 @@ void T_RaiseSector(levelspecthink_t *raise)
 
 	if (active)
 	{
-		raise->vars[3] = raise->vars[2];
+		raise->speed = raise->basespeed;
 
-		if (raise->vars[0] == 1)
+		if (raise->flags & RF_REVERSE)
 		{
-			if (raise->sector->ceilingheight <= raise->vars[7])
+			if (raise->sector->ceilingheight <= raise->ceilingbottom)
 			{
-				raise->sector->floorheight = raise->vars[7] - (raise->sector->ceilingheight - raise->sector->floorheight);
-				raise->sector->ceilingheight = raise->vars[7];
+				raise->sector->floorheight = raise->ceilingbottom - (raise->sector->ceilingheight - raise->sector->floorheight);
+				raise->sector->ceilingheight = raise->ceilingbottom;
 				raise->sector->ceilspeed = 0;
 				raise->sector->floorspeed = 0;
 				return;
 			}
 
-			raise->vars[8] = -1;
-			ceilingdestination = raise->vars[7];
-			floordestination = raise->vars[6];
+			raise->direction = -1;
+			ceilingdestination = raise->ceilingbottom;
+			floordestination = raise->floorbottom;
 		}
 		else // elevateUp
 		{
-			if (raise->sector->ceilingheight >= raise->vars[5])
+			if (raise->sector->ceilingheight >= raise->ceilingtop)
 			{
-				raise->sector->floorheight = raise->vars[5] - (raise->sector->ceilingheight - raise->sector->floorheight);
-				raise->sector->ceilingheight = raise->vars[5];
+				raise->sector->floorheight = raise->ceilingtop - (raise->sector->ceilingheight - raise->sector->floorheight);
+				raise->sector->ceilingheight = raise->ceilingtop;
 				raise->sector->ceilspeed = 0;
 				raise->sector->floorspeed = 0;
 				return;
 			}
 
-			raise->vars[8] = 1;
-			ceilingdestination = raise->vars[5];
-			floordestination = raise->vars[4];
+			raise->direction = 1;
+			ceilingdestination = raise->ceilingtop;
+			floordestination = raise->floortop;
 		}
 	}
 	else
 	{
-		raise->vars[3] = raise->vars[2]/2;
+		raise->speed = raise->basespeed/2;
 
-		if (raise->vars[0] == 1)
+		if (raise->flags & RF_REVERSE)
 		{
-			if (raise->sector->ceilingheight >= raise->vars[5])
+			if (raise->sector->ceilingheight >= raise->ceilingtop)
 			{
-				raise->sector->floorheight = raise->vars[5] - (raise->sector->ceilingheight - raise->sector->floorheight);
-				raise->sector->ceilingheight = raise->vars[5];
+				raise->sector->floorheight = raise->ceilingtop - (raise->sector->ceilingheight - raise->sector->floorheight);
+				raise->sector->ceilingheight = raise->ceilingtop;
 				raise->sector->ceilspeed = 0;
 				raise->sector->floorspeed = 0;
 				return;
 			}
-			raise->vars[8] = 1;
-			ceilingdestination = raise->vars[5];
-			floordestination = raise->vars[4];
+			raise->direction = 1;
+			ceilingdestination = raise->ceilingtop;
+			floordestination = raise->floortop;
 		}
 		else // elevateUp
 		{
-			if (raise->sector->ceilingheight <= raise->vars[7])
+			if (raise->sector->ceilingheight <= raise->ceilingbottom)
 			{
-				raise->sector->floorheight = raise->vars[7] - (raise->sector->ceilingheight - raise->sector->floorheight);
-				raise->sector->ceilingheight = raise->vars[7];
+				raise->sector->floorheight = raise->ceilingbottom - (raise->sector->ceilingheight - raise->sector->floorheight);
+				raise->sector->ceilingheight = raise->ceilingbottom;
 				raise->sector->ceilspeed = 0;
 				raise->sector->floorspeed = 0;
 				return;
 			}
-			raise->vars[8] = -1;
-			ceilingdestination = raise->vars[7];
-			floordestination = raise->vars[6];
+			raise->direction = -1;
+			ceilingdestination = raise->ceilingbottom;
+			floordestination = raise->floorbottom;
 		}
 	}
 
-	if ((raise->sector->ceilingheight - raise->vars[7])
-		< (raise->vars[5] - raise->sector->ceilingheight))
+	if ((raise->sector->ceilingheight - raise->ceilingbottom)
+		< (raise->ceilingtop - raise->sector->ceilingheight))
 	{
-		fixed_t origspeed = raise->vars[3];
+		fixed_t origspeed = raise->speed;
 
 		// Slow down as you get closer to the bottom
-		raise->vars[3] = FixedMul(raise->vars[3],FixedDiv(raise->sector->ceilingheight - raise->vars[7], (raise->vars[5] - raise->vars[7])>>5));
+		raise->speed = FixedMul(raise->speed,FixedDiv(raise->sector->ceilingheight - raise->ceilingbottom, (raise->ceilingtop - raise->ceilingbottom)>>5));
 
-		if (raise->vars[3] <= origspeed/16)
-			raise->vars[3] = origspeed/16;
-		else if (raise->vars[3] > origspeed)
-			raise->vars[3] = origspeed;
+		if (raise->speed <= origspeed/16)
+			raise->speed = origspeed/16;
+		else if (raise->speed > origspeed)
+			raise->speed = origspeed;
 	}
 	else
 	{
-		fixed_t origspeed = raise->vars[3];
+		fixed_t origspeed = raise->speed;
 		// Slow down as you get closer to the top
-		raise->vars[3] = FixedMul(raise->vars[3],FixedDiv(raise->vars[5] - raise->sector->ceilingheight, (raise->vars[5] - raise->vars[7])>>5));
+		raise->speed = FixedMul(raise->speed,FixedDiv(raise->ceilingtop - raise->sector->ceilingheight, (raise->ceilingtop - raise->ceilingbottom)>>5));
 
-		if (raise->vars[3] <= origspeed/16)
-			raise->vars[3] = origspeed/16;
-		else if (raise->vars[3] > origspeed)
-			raise->vars[3] = origspeed;
+		if (raise->speed <= origspeed/16)
+			raise->speed = origspeed/16;
+		else if (raise->speed > origspeed)
+			raise->speed = origspeed;
 	}
 
-	raise->vars[3] += raise->vars[10];
+	raise->speed += raise->extraspeed;
 
 	res = T_MovePlane
 	(
 		raise->sector,         // sector
-		raise->vars[3],          // speed
+		raise->speed,          // speed
 		ceilingdestination, // dest
 		0,                        // crush
 		1,                        // floor or ceiling (1 for ceiling)
-		raise->vars[8]       // direction
+		raise->direction       // direction
 	);
 
 	if (res == ok || res == pastdest)
 		T_MovePlane
 		(
 			raise->sector,           // sector
-			raise->vars[3],            // speed
+			raise->speed,            // speed
 			floordestination, // dest
 			0,                          // crush
 			0,                          // floor or ceiling (0 for floor)
-			raise->vars[8]         // direction
+			raise->direction         // direction
 		);
 
 	raise->sector->ceilspeed = 42;
-	raise->sector->floorspeed = raise->vars[3]*raise->vars[8];
+	raise->sector->floorspeed = raise->speed*raise->direction;
 
 	for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->tag, i)) >= 0 ;)
 		P_RecalcPrecipInSector(&sectors[i]);
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 259e58168..114f30172 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1659,6 +1659,28 @@ static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveSector(ht->sector));
 }
 
+// SaveRaiseThinker
+//
+// Saves a raise_t thinker
+//
+static void SaveRaiseThinker(const thinker_t *th, const UINT8 type)
+{
+	const raise_t *ht  = (const void *)th;
+	WRITEUINT8(save_p, type);
+	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+	WRITEUINT32(save_p, SaveSector(ht->sector));
+	WRITEFIXED(save_p, ht->floorbottom);
+	WRITEFIXED(save_p, ht->ceilingbottom);
+	WRITEFIXED(save_p, ht->floortop);
+	WRITEFIXED(save_p, ht->ceilingtop);
+	WRITEFIXED(save_p, ht->basespeed);
+	WRITEFIXED(save_p, ht->speed);
+	WRITEINT32(save_p, ht->direction);
+	WRITEFIXED(save_p, ht->extraspeed);
+	WRITEUINT8(save_p, ht->shaketimer);
+	WRITEUINT8(save_p, ht->flags);
+}
+
 //
 // SaveCeilingThinker
 //
@@ -2237,7 +2259,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_RaiseSector)
 			{
-				SaveSpecialLevelThinker(th, tc_raisesector);
+				SaveRaiseThinker(th, tc_raisesector);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_CameraScanner)
@@ -2770,6 +2792,29 @@ static thinker_t* LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeili
 	return &ht->thinker;
 }
 
+// LoadRaiseThinker
+//
+// Loads a raise_t from a save game
+//
+static thinker_t* LoadRaiseThinker(actionf_p1 thinker)
+{
+	raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ht->thinker.function.acp1 = thinker;
+	ht->sourceline = LoadLine(READUINT32(save_p));
+	ht->sector = LoadSector(READUINT32(save_p));
+	ht->floorbottom = READFIXED(save_p);
+	ht->ceilingbottom = READFIXED(save_p);
+	ht->floortop = READFIXED(save_p);
+	ht->ceilingtop = READFIXED(save_p);
+	ht->basespeed = READFIXED(save_p);
+	ht->speed = READFIXED(save_p);
+	ht->direction = READINT32(save_p);
+	ht->extraspeed = READFIXED(save_p);
+	ht->shaketimer = READUINT8(save_p);
+	ht->flags = READUINT8(save_p);
+	return &ht->thinker;
+}
+
 //
 // LoadCeilingThinker
 //
@@ -3448,7 +3493,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_raisesector:
-					th = LoadSpecialLevelThinker((actionf_p1)T_RaiseSector, 0);
+					th = LoadRaiseThinker((actionf_p1)T_RaiseSector);
 					break;
 
 				/// \todo rewrite all the code that uses an elevator_t but isn't an elevator
diff --git a/src/p_spec.c b/src/p_spec.c
index e73c6ee9a..b0be41ae3 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6042,83 +6042,56 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline)
   */
 static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline)
 {
-	levelspecthink_t *raise;
+	raise_t *raise;
 
 	raise = Z_Calloc(sizeof (*raise), PU_LEVSPEC, NULL);
 	P_AddThinker(THINK_MAIN, &raise->thinker);
 
 	raise->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
 
-	if (sourceline->flags & ML_BLOCKMONSTERS)
-		raise->vars[0] = 1;
-	else
-		raise->vars[0] = 0;
-
-	// set up the fields
+	raise->sourceline = sourceline;
 	raise->sector = sec;
 
-	// Require a spindash to activate
+	raise->ceilingtop = P_FindHighestCeilingSurrounding(sec);
+	raise->floortop = raise->ceilingtop - (sec->ceilingheight - sec->floorheight);
+	raise->ceilingbottom = P_FindLowestCeilingSurrounding(sec);
+	raise->floorbottom = raise->ceilingbottom - (sec->ceilingheight - sec->floorheight);
+
+	raise->basespeed =  FixedDiv(P_AproxDistance(sourceline->dx, sourceline->dy), 4*FRACUNIT);
+	raise->speed = raise->basespeed;
+
+	if (sourceline->flags & ML_BLOCKMONSTERS)
+		raise->flags |= RF_REVERSE;
 	if (sourceline->flags & ML_NOCLIMB)
-		raise->vars[1] = 1;
-	else
-		raise->vars[1] = 0;
-
-	raise->vars[2] = P_AproxDistance(sourceline->dx, sourceline->dy);
-	raise->vars[2] = FixedDiv(raise->vars[2], 4*FRACUNIT);
-	raise->vars[3] = raise->vars[2];
-
-	raise->vars[5] = P_FindHighestCeilingSurrounding(sec);
-	raise->vars[4] = raise->vars[5]
-		- (sec->ceilingheight - sec->floorheight);
-
-	raise->vars[7] = P_FindLowestCeilingSurrounding(sec);
-	raise->vars[6] = raise->vars[7]
-		- (sec->ceilingheight - sec->floorheight);
-
-	raise->sourceline = sourceline;
+		raise->flags |= RF_SPINDASH;
 }
 
 static void P_AddAirbob(sector_t *sec, line_t *sourceline, boolean noadjust, boolean dynamic)
 {
-	levelspecthink_t *airbob;
+	raise_t *airbob;
 
 	airbob = Z_Calloc(sizeof (*airbob), PU_LEVSPEC, NULL);
 	P_AddThinker(THINK_MAIN, &airbob->thinker);
 
 	airbob->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
 
-	// set up the fields
+	airbob->sourceline = sourceline;
 	airbob->sector = sec;
 
-	// Require a spindash to activate
-	if (sourceline->flags & ML_NOCLIMB)
-		airbob->vars[1] = 1;
-	else
-		airbob->vars[1] = 0;
+	airbob->ceilingtop = sec->ceilingheight;
+	airbob->floortop = airbob->ceilingtop - (sec->ceilingheight - sec->floorheight);
+	airbob->ceilingbottom = sec->ceilingheight - (noadjust ? 16*FRACUNIT : P_AproxDistance(sourceline->dx, sourceline->dy));
+	airbob->floorbottom = airbob->ceilingbottom - (sec->ceilingheight - sec->floorheight);
 
-	airbob->vars[2] = FRACUNIT;
-
-	if (noadjust)
-		airbob->vars[7] = airbob->sector->ceilingheight-16*FRACUNIT;
-	else
-		airbob->vars[7] = airbob->sector->ceilingheight - P_AproxDistance(sourceline->dx, sourceline->dy);
-	airbob->vars[6] = airbob->vars[7]
-		- (sec->ceilingheight - sec->floorheight);
-
-	airbob->vars[3] = airbob->vars[2];
+	airbob->basespeed = FRACUNIT;
+	airbob->speed = airbob->basespeed;
 
 	if (sourceline->flags & ML_BLOCKMONSTERS)
-		airbob->vars[0] = 1;
-	else
-		airbob->vars[0] = 0;
-
-	airbob->vars[5] = sec->ceilingheight;
-	airbob->vars[4] = airbob->vars[5]
-			- (sec->ceilingheight - sec->floorheight);
-
-	airbob->vars[9] = dynamic ? 1 : 0;
-
-	airbob->sourceline = sourceline;
+		airbob->flags |= RF_REVERSE;
+	if (sourceline->flags & ML_NOCLIMB)
+		airbob->flags |= RF_SPINDASH;
+	if (dynamic)
+		airbob->flags |= RF_DYNAMIC;
 }
 
 /** Adds a thwomp thinker.
diff --git a/src/p_spec.h b/src/p_spec.h
index d756f1942..1608728d9 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -320,6 +320,30 @@ typedef struct
 	sector_t *sector;   // Sector the thinker is from
 } levelspecthink_t;
 
+typedef enum
+{
+	RF_REVERSE  = 1,    //Lower when stood on
+	RF_SPINDASH = 1<<1, //Require spindash to move
+	RF_DYNAMIC  = 1<<2, //Dynamically sinking platform
+} raiseflag_t;
+
+typedef struct
+{
+	thinker_t thinker;
+	line_t *sourceline;
+	sector_t *sector;
+	fixed_t floorbottom;
+	fixed_t ceilingbottom;
+	fixed_t floortop;
+	fixed_t ceilingtop;
+	fixed_t basespeed;
+	fixed_t speed;
+	INT32 direction; //1 = up, -1 = down
+	fixed_t extraspeed; //For dynamically sinking platform
+	UINT8 shaketimer; //For dynamically sinking platform
+	UINT8 flags;
+} raise_t;
+
 #define ELEVATORSPEED (FRACUNIT*4)
 #define FLOORSPEED (FRACUNIT)
 
@@ -359,7 +383,7 @@ void T_ThwompSector(levelspecthink_t *thwomp);
 void T_NoEnemiesSector(levelspecthink_t *nobaddies);
 void T_EachTimeThinker(levelspecthink_t *eachtime);
 void T_CameraScanner(elevator_t *elevator);
-void T_RaiseSector(levelspecthink_t *sraise);
+void T_RaiseSector(raise_t *raise);
 
 typedef struct
 {

From a41dbe2bae93cc4e62f3547c0f4b7ecd32ab82cb Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 17 Apr 2020 10:19:02 +0200
Subject: [PATCH 168/251] Get rid of code duplication in T_RaiseSector

---
 src/p_floor.c | 116 ++++++++++++--------------------------------------
 1 file changed, 27 insertions(+), 89 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index d43900be7..03fa8629f 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1854,7 +1854,10 @@ void T_RaiseSector(raise_t *raise)
 	sector_t *sector;
 	INT32 i;
 	boolean playeronme = false, active = false;
+	boolean moveUp;
 	fixed_t ceilingdestination, floordestination;
+	fixed_t origspeed;
+	fixed_t distToNearestEndpoint;
 	result_e res = 0;
 
 	if (raise->sector->crumblestate >= 3 || raise->sector->ceilingdata)
@@ -1933,99 +1936,34 @@ void T_RaiseSector(raise_t *raise)
 	else // Air bobbing platform (not a Dynamically Sinking Platform^tm)
 		active = playeronme;
 
-	if (active)
+	raise->speed = raise->basespeed;
+	if (!active)
+		raise->speed /= 2;
+
+	moveUp = active ^ (raise->flags & RF_REVERSE);
+	ceilingdestination = moveUp ? raise->ceilingtop : raise->ceilingbottom;
+	floordestination = moveUp ? raise->floortop : raise->floorbottom;
+
+	if ((moveUp && raise->sector->ceilingheight >= ceilingdestination)
+		|| (!moveUp && raise->sector->ceilingheight <= ceilingdestination))
 	{
-		raise->speed = raise->basespeed;
-
-		if (raise->flags & RF_REVERSE)
-		{
-			if (raise->sector->ceilingheight <= raise->ceilingbottom)
-			{
-				raise->sector->floorheight = raise->ceilingbottom - (raise->sector->ceilingheight - raise->sector->floorheight);
-				raise->sector->ceilingheight = raise->ceilingbottom;
-				raise->sector->ceilspeed = 0;
-				raise->sector->floorspeed = 0;
-				return;
-			}
-
-			raise->direction = -1;
-			ceilingdestination = raise->ceilingbottom;
-			floordestination = raise->floorbottom;
-		}
-		else // elevateUp
-		{
-			if (raise->sector->ceilingheight >= raise->ceilingtop)
-			{
-				raise->sector->floorheight = raise->ceilingtop - (raise->sector->ceilingheight - raise->sector->floorheight);
-				raise->sector->ceilingheight = raise->ceilingtop;
-				raise->sector->ceilspeed = 0;
-				raise->sector->floorspeed = 0;
-				return;
-			}
-
-			raise->direction = 1;
-			ceilingdestination = raise->ceilingtop;
-			floordestination = raise->floortop;
-		}
+		raise->sector->floorheight = ceilingdestination - (raise->sector->ceilingheight - raise->sector->floorheight);
+		raise->sector->ceilingheight = ceilingdestination;
+		raise->sector->ceilspeed = 0;
+		raise->sector->floorspeed = 0;
+		return;
 	}
-	else
-	{
-		raise->speed = raise->basespeed/2;
+	raise->direction = moveUp ? 1 : -1;
 
-		if (raise->flags & RF_REVERSE)
-		{
-			if (raise->sector->ceilingheight >= raise->ceilingtop)
-			{
-				raise->sector->floorheight = raise->ceilingtop - (raise->sector->ceilingheight - raise->sector->floorheight);
-				raise->sector->ceilingheight = raise->ceilingtop;
-				raise->sector->ceilspeed = 0;
-				raise->sector->floorspeed = 0;
-				return;
-			}
-			raise->direction = 1;
-			ceilingdestination = raise->ceilingtop;
-			floordestination = raise->floortop;
-		}
-		else // elevateUp
-		{
-			if (raise->sector->ceilingheight <= raise->ceilingbottom)
-			{
-				raise->sector->floorheight = raise->ceilingbottom - (raise->sector->ceilingheight - raise->sector->floorheight);
-				raise->sector->ceilingheight = raise->ceilingbottom;
-				raise->sector->ceilspeed = 0;
-				raise->sector->floorspeed = 0;
-				return;
-			}
-			raise->direction = -1;
-			ceilingdestination = raise->ceilingbottom;
-			floordestination = raise->floorbottom;
-		}
-	}
+	origspeed = raise->speed;
+	// Speed up as you get closer to the middle, then slow down again
+	distToNearestEndpoint = min(raise->sector->ceilingheight - raise->ceilingbottom, raise->ceilingtop - raise->sector->ceilingheight);
+	raise->speed = FixedMul(raise->speed, FixedDiv(distToNearestEndpoint, (raise->ceilingtop - raise->ceilingbottom) >> 5));
 
-	if ((raise->sector->ceilingheight - raise->ceilingbottom)
-		< (raise->ceilingtop - raise->sector->ceilingheight))
-	{
-		fixed_t origspeed = raise->speed;
-
-		// Slow down as you get closer to the bottom
-		raise->speed = FixedMul(raise->speed,FixedDiv(raise->sector->ceilingheight - raise->ceilingbottom, (raise->ceilingtop - raise->ceilingbottom)>>5));
-
-		if (raise->speed <= origspeed/16)
-			raise->speed = origspeed/16;
-		else if (raise->speed > origspeed)
-			raise->speed = origspeed;
-	}
-	else
-	{
-		fixed_t origspeed = raise->speed;
-		// Slow down as you get closer to the top
-		raise->speed = FixedMul(raise->speed,FixedDiv(raise->ceilingtop - raise->sector->ceilingheight, (raise->ceilingtop - raise->ceilingbottom)>>5));
-
-		if (raise->speed <= origspeed/16)
-			raise->speed = origspeed/16;
-		else if (raise->speed > origspeed)
-			raise->speed = origspeed;
-	}
+	if (raise->speed <= origspeed/16)
+		raise->speed = origspeed/16;
+	else if (raise->speed > origspeed)
+		raise->speed = origspeed;
 
 	raise->speed += raise->extraspeed;
 

From 63a901b714182cf5963ecfbad371e9d383517e36 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 17 Apr 2020 11:11:36 +0200
Subject: [PATCH 169/251] -Remove superfluous variables from raise_t -Cleanup
 signatures of P_AddRaiseThinker and P_AddAirbob

---
 src/p_floor.c | 52 ++++++++++++++++++++++++------------------------
 src/p_saveg.c |  8 --------
 src/p_spec.c  | 55 ++++++++++++++++++++++++---------------------------
 src/p_spec.h  |  4 ----
 4 files changed, 52 insertions(+), 67 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 03fa8629f..8b4b515fe 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1856,8 +1856,9 @@ void T_RaiseSector(raise_t *raise)
 	boolean playeronme = false, active = false;
 	boolean moveUp;
 	fixed_t ceilingdestination, floordestination;
-	fixed_t origspeed;
+	fixed_t speed, origspeed;
 	fixed_t distToNearestEndpoint;
+	INT32 direction;
 	result_e res = 0;
 
 	if (raise->sector->crumblestate >= 3 || raise->sector->ceilingdata)
@@ -1936,60 +1937,59 @@ void T_RaiseSector(raise_t *raise)
 	else // Air bobbing platform (not a Dynamically Sinking Platform^tm)
 		active = playeronme;
 
-	raise->speed = raise->basespeed;
-	if (!active)
-		raise->speed /= 2;
-
 	moveUp = active ^ (raise->flags & RF_REVERSE);
 	ceilingdestination = moveUp ? raise->ceilingtop : raise->ceilingbottom;
-	floordestination = moveUp ? raise->floortop : raise->floorbottom;
+	floordestination = ceilingdestination - (raise->sector->ceilingheight - raise->sector->floorheight);
 
 	if ((moveUp && raise->sector->ceilingheight >= ceilingdestination)
 		|| (!moveUp && raise->sector->ceilingheight <= ceilingdestination))
 	{
-		raise->sector->floorheight = ceilingdestination - (raise->sector->ceilingheight - raise->sector->floorheight);
+		raise->sector->floorheight = floordestination;
 		raise->sector->ceilingheight = ceilingdestination;
 		raise->sector->ceilspeed = 0;
 		raise->sector->floorspeed = 0;
 		return;
 	}
-	raise->direction = moveUp ? 1 : -1;
+	direction = moveUp ? 1 : -1;
+
+	origspeed = raise->basespeed;
+	if (!active)
+		origspeed /= 2;
 
-	origspeed = raise->speed;
 	// Speed up as you get closer to the middle, then slow down again
 	distToNearestEndpoint = min(raise->sector->ceilingheight - raise->ceilingbottom, raise->ceilingtop - raise->sector->ceilingheight);
-	raise->speed = FixedMul(raise->speed, FixedDiv(distToNearestEndpoint, (raise->ceilingtop - raise->ceilingbottom) >> 5));
+	speed = FixedMul(origspeed, FixedDiv(distToNearestEndpoint, (raise->ceilingtop - raise->ceilingbottom) >> 5));
 
-	if (raise->speed <= origspeed/16)
-		raise->speed = origspeed/16;
-	else if (raise->speed > origspeed)
-		raise->speed = origspeed;
+	if (speed <= origspeed/16)
+		speed = origspeed/16;
+	else if (speed > origspeed)
+		speed = origspeed;
 
-	raise->speed += raise->extraspeed;
+	speed += raise->extraspeed;
 
 	res = T_MovePlane
 	(
-		raise->sector,         // sector
-		raise->speed,          // speed
+		raise->sector,      // sector
+		speed,              // speed
 		ceilingdestination, // dest
-		0,                        // crush
-		1,                        // floor or ceiling (1 for ceiling)
-		raise->direction       // direction
+		0,                  // crush
+		1,                  // floor or ceiling (1 for ceiling)
+		direction           // direction
 	);
 
 	if (res == ok || res == pastdest)
 		T_MovePlane
 		(
-			raise->sector,           // sector
-			raise->speed,            // speed
+			raise->sector,    // sector
+			speed,            // speed
 			floordestination, // dest
-			0,                          // crush
-			0,                          // floor or ceiling (0 for floor)
-			raise->direction         // direction
+			0,                // crush
+			0,                // floor or ceiling (0 for floor)
+			direction         // direction
 		);
 
 	raise->sector->ceilspeed = 42;
-	raise->sector->floorspeed = raise->speed*raise->direction;
+	raise->sector->floorspeed = speed*direction;
 
 	for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->tag, i)) >= 0 ;)
 		P_RecalcPrecipInSector(&sectors[i]);
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 114f30172..c93756983 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1669,13 +1669,9 @@ static void SaveRaiseThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT8(save_p, type);
 	WRITEUINT32(save_p, SaveLine(ht->sourceline));
 	WRITEUINT32(save_p, SaveSector(ht->sector));
-	WRITEFIXED(save_p, ht->floorbottom);
 	WRITEFIXED(save_p, ht->ceilingbottom);
-	WRITEFIXED(save_p, ht->floortop);
 	WRITEFIXED(save_p, ht->ceilingtop);
 	WRITEFIXED(save_p, ht->basespeed);
-	WRITEFIXED(save_p, ht->speed);
-	WRITEINT32(save_p, ht->direction);
 	WRITEFIXED(save_p, ht->extraspeed);
 	WRITEUINT8(save_p, ht->shaketimer);
 	WRITEUINT8(save_p, ht->flags);
@@ -2802,13 +2798,9 @@ static thinker_t* LoadRaiseThinker(actionf_p1 thinker)
 	ht->thinker.function.acp1 = thinker;
 	ht->sourceline = LoadLine(READUINT32(save_p));
 	ht->sector = LoadSector(READUINT32(save_p));
-	ht->floorbottom = READFIXED(save_p);
 	ht->ceilingbottom = READFIXED(save_p);
-	ht->floortop = READFIXED(save_p);
 	ht->ceilingtop = READFIXED(save_p);
 	ht->basespeed = READFIXED(save_p);
-	ht->speed = READFIXED(save_p);
-	ht->direction = READINT32(save_p);
 	ht->extraspeed = READFIXED(save_p);
 	ht->shaketimer = READUINT8(save_p);
 	ht->flags = READUINT8(save_p);
diff --git a/src/p_spec.c b/src/p_spec.c
index b0be41ae3..ea86c88a4 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6040,7 +6040,7 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline)
   * \sa P_SpawnSpecials, T_RaiseSector
   * \author SSNTails <http://www.ssntails.org>
   */
-static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline)
+static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, boolean lower, boolean spindash)
 {
 	raise_t *raise;
 
@@ -6053,20 +6053,17 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline)
 	raise->sector = sec;
 
 	raise->ceilingtop = P_FindHighestCeilingSurrounding(sec);
-	raise->floortop = raise->ceilingtop - (sec->ceilingheight - sec->floorheight);
 	raise->ceilingbottom = P_FindLowestCeilingSurrounding(sec);
-	raise->floorbottom = raise->ceilingbottom - (sec->ceilingheight - sec->floorheight);
 
 	raise->basespeed =  FixedDiv(P_AproxDistance(sourceline->dx, sourceline->dy), 4*FRACUNIT);
-	raise->speed = raise->basespeed;
 
-	if (sourceline->flags & ML_BLOCKMONSTERS)
+	if (lower)
 		raise->flags |= RF_REVERSE;
-	if (sourceline->flags & ML_NOCLIMB)
+	if (spindash)
 		raise->flags |= RF_SPINDASH;
 }
 
-static void P_AddAirbob(sector_t *sec, line_t *sourceline, boolean noadjust, boolean dynamic)
+static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean raise, boolean spindash, boolean dynamic)
 {
 	raise_t *airbob;
 
@@ -6079,16 +6076,15 @@ static void P_AddAirbob(sector_t *sec, line_t *sourceline, boolean noadjust, boo
 	airbob->sector = sec;
 
 	airbob->ceilingtop = sec->ceilingheight;
-	airbob->floortop = airbob->ceilingtop - (sec->ceilingheight - sec->floorheight);
-	airbob->ceilingbottom = sec->ceilingheight - (noadjust ? 16*FRACUNIT : P_AproxDistance(sourceline->dx, sourceline->dy));
-	airbob->floorbottom = airbob->ceilingbottom - (sec->ceilingheight - sec->floorheight);
+	airbob->ceilingbottom = sec->ceilingheight - speed;
 
 	airbob->basespeed = FRACUNIT;
-	airbob->speed = airbob->basespeed;
 
-	if (sourceline->flags & ML_BLOCKMONSTERS)
+	airbob->flags = flags;
+
+	if (!raise)
 		airbob->flags |= RF_REVERSE;
-	if (sourceline->flags & ML_NOCLIMB)
+	if (spindash)
 		airbob->flags |= RF_SPINDASH;
 	if (dynamic)
 		airbob->flags |= RF_DYNAMIC;
@@ -6894,18 +6890,22 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 150: // Air bobbing platform
 			case 151: // Adjustable air bobbing platform
+			{
+				fixed_t dist = (lines[i].special == 150) ? 16*FRACUNIT : P_AproxDistance(lines[i].dx, lines[i].dy);
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
-				lines[i].flags |= ML_BLOCKMONSTERS;
-				P_AddAirbob(lines[i].frontsector, lines + i, (lines[i].special != 151), false);
+				P_AddAirbob(lines[i].frontsector, lines + i, dist, false, !!(lines[i].flags & ML_NOCLIMB), false);
 				break;
+			}
 			case 152: // Adjustable air bobbing platform in reverse
+				if (lines[i].flags & NOCLIMB)
+					raiseflags |= RF_SPINDASH;
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
-				P_AddAirbob(lines[i].frontsector, lines + i, true, false);
+				P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), true, !!(lines[i].flags & ML_NOCLIMB), false);
 				break;
 			case 153: // Dynamic Sinking Platform
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
 				lines[i].flags |= ML_BLOCKMONSTERS;
-				P_AddAirbob(lines[i].frontsector, lines + i, false, true);
+				P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), false, !!(lines[i].flags & ML_NOCLIMB), true);
 				break;
 
 			case 160: // Float/bob platform
@@ -6955,15 +6955,13 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 176: // Air bobbing platform that will crumble and bob on the water when it falls and hits
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB|FF_CRUMBLE, secthinkers);
-				lines[i].flags |= ML_BLOCKMONSTERS;
-				P_AddAirbob(lines[i].frontsector, lines + i, true, false);
+				P_AddAirbob(lines[i].frontsector, lines + i, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false);
 				break;
 
 			case 177: // Air bobbing platform that will crumble and bob on
 				// the water when it falls and hits, then never return
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB|FF_CRUMBLE|FF_NORETURN, secthinkers);
-				lines[i].flags |= ML_BLOCKMONSTERS;
-				P_AddAirbob(lines[i].frontsector, lines + i, true, false);
+				P_AddAirbob(lines[i].frontsector, lines + i, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false);
 				break;
 
 			case 178: // Crumbling platform that will float when it hits water
@@ -6976,28 +6974,27 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 180: // Air bobbing platform that will crumble
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE, secthinkers);
-				lines[i].flags |= ML_BLOCKMONSTERS;
-				P_AddAirbob(lines[i].frontsector, lines + i, true, false);
+				P_AddAirbob(lines[i].frontsector, lines + i, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false);
 				break;
 
 			case 190: // Rising Platform FOF (solid, opaque, shadows)
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i]);
+				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
 				break;
 
 			case 191: // Rising Platform FOF (solid, opaque, no shadows)
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_CUTLEVEL, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i]);
+				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
 				break;
 
 			case 192: // Rising Platform TL block: FOF (solid, translucent)
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i]);
+				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
 				break;
 
 			case 193: // Rising Platform FOF (solid, invisible)
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_NOSHADE, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i]);
+				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
 				break;
 
 			case 194: // Rising Platform 'Platform' - You can jump up through it
@@ -7007,7 +7004,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 					ffloorflags |= FF_NOSHADE;
 
 				P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i]);
+				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
 				break;
 
 			case 195: // Rising Platform Translucent "platform"
@@ -7017,7 +7014,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 					ffloorflags |= FF_NOSHADE;
 
 				P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i]);
+				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
 				break;
 
 			case 200: // Double light effect
diff --git a/src/p_spec.h b/src/p_spec.h
index 1608728d9..eb61ad7bf 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -332,13 +332,9 @@ typedef struct
 	thinker_t thinker;
 	line_t *sourceline;
 	sector_t *sector;
-	fixed_t floorbottom;
 	fixed_t ceilingbottom;
-	fixed_t floortop;
 	fixed_t ceilingtop;
 	fixed_t basespeed;
-	fixed_t speed;
-	INT32 direction; //1 = up, -1 = down
 	fixed_t extraspeed; //For dynamically sinking platform
 	UINT8 shaketimer; //For dynamically sinking platform
 	UINT8 flags;

From 3e0a9c8718595daf124987a88b1220bc136f8937 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 17 Apr 2020 11:13:13 +0200
Subject: [PATCH 170/251] Forgot to clean up some stuff

---
 src/p_spec.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index ea86c88a4..a72f56cc0 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6076,12 +6076,10 @@ static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean
 	airbob->sector = sec;
 
 	airbob->ceilingtop = sec->ceilingheight;
-	airbob->ceilingbottom = sec->ceilingheight - speed;
+	airbob->ceilingbottom = sec->ceilingheight - dist;
 
 	airbob->basespeed = FRACUNIT;
 
-	airbob->flags = flags;
-
 	if (!raise)
 		airbob->flags |= RF_REVERSE;
 	if (spindash)
@@ -6897,8 +6895,6 @@ void P_SpawnSpecials(boolean fromnetsave)
 				break;
 			}
 			case 152: // Adjustable air bobbing platform in reverse
-				if (lines[i].flags & NOCLIMB)
-					raiseflags |= RF_SPINDASH;
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
 				P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), true, !!(lines[i].flags & ML_NOCLIMB), false);
 				break;

From 89539512f69f795f7a11c4d57dc5633aee9657f0 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 17 Apr 2020 14:00:48 +0200
Subject: [PATCH 171/251] Make T_EachTimeThinker use its own struct

---
 src/p_floor.c | 45 ++++++++++-----------------------------------
 src/p_saveg.c | 41 +++++++++++++++++++++++++++++++++++++++--
 src/p_spec.c  | 11 +++++------
 src/p_spec.h  | 11 ++++++++++-
 4 files changed, 64 insertions(+), 44 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 8b4b515fe..a5c358621 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1581,7 +1581,7 @@ static INT32 P_HavePlayersEnteredArea(boolean *curPlayers, boolean *oldPlayers,
 //
 // \sa P_AddEachTimeThinker
 //
-void T_EachTimeThinker(levelspecthink_t *eachtime)
+void T_EachTimeThinker(eachtime_t *eachtime)
 {
 	size_t i, j;
 	sector_t *sec = NULL;
@@ -1604,19 +1604,10 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
 
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
-		if (i & 1)
-		{
-			oldPlayersInArea[i] = eachtime->vars[i/2] & 65535;
-			oldPlayersOnArea[i] = eachtime->var2s[i/2] & 65535;
-			eachtime->vars[i/2] = 0;
-			eachtime->var2s[i/2] = 0;
-		}
-		else
-		{
-			oldPlayersInArea[i] = eachtime->vars[i/2] >> 16;
-			oldPlayersOnArea[i] = eachtime->var2s[i/2] >> 16;
-		}
-
+		oldPlayersInArea[i] = eachtime->playersInArea[i];
+		oldPlayersOnArea[i] = eachtime->playersOnArea[i];
+		eachtime->playersInArea[i] = false;
+		eachtime->playersOnArea[i] = false;
 		playersInArea[i] = false;
 		playersOnArea[i] = false;
 	}
@@ -1705,20 +1696,12 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
 
 					if (floortouch == true && P_IsObjectOnGroundIn(players[j].mo, targetsec))
 					{
-						if (j & 1)
-							eachtime->var2s[j/2] |= 1;
-						else
-							eachtime->var2s[j/2] |= 1 << 16;
-
+						eachtime->playersOnArea[j] = true;
 						playersOnArea[j] = true;
 					}
 					else
 					{
-						if (j & 1)
-							eachtime->vars[j/2] |= 1;
-						else
-							eachtime->vars[j/2] |= 1 << 16;
-
+						eachtime->playersInArea[j] = true;
 						playersInArea[j] = true;
 					}
 				}
@@ -1766,27 +1749,19 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
 
 				if (floortouch == true && P_IsObjectOnRealGround(players[i].mo, sec))
 				{
-					if (i & 1)
-						eachtime->var2s[i/2] |= 1;
-					else
-						eachtime->var2s[i/2] |= 1 << 16;
-
+					eachtime->playersOnArea[i] = true;
 					playersOnArea[i] = true;
 				}
 				else
 				{
-					if (i & 1)
-						eachtime->vars[i/2] |= 1;
-					else
-						eachtime->vars[i/2] |= 1 << 16;
-
+					eachtime->playersInArea[i] = true;
 					playersInArea[i] = true;
 				}
 			}
 		}
 	}
 
-	if ((eachtime->sourceline->flags & ML_BOUNCY) == ML_BOUNCY)
+	if (eachtime->triggerOnExit)
 		inAndOut = true;
 
 	// Check if a new player entered.
diff --git a/src/p_saveg.c b/src/p_saveg.c
index c93756983..58fb7ad52 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1659,6 +1659,24 @@ static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveSector(ht->sector));
 }
 
+// SaveEachTimeThinker
+//
+// Loads a eachtime_t from a save game
+//
+static void SaveEachTimeThinker(const thinker_t *th, const UINT8 type)
+{
+	const eachtime_t *ht  = (const void *)th;
+	size_t i;
+	WRITEUINT8(save_p, type);
+	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+	for (i = 0; i < MAXPLAYERS; i++)
+	{
+		WRITECHAR(save_p, ht->playersInArea[i]);
+		WRITECHAR(save_p, ht->playersOnArea[i]);
+	}
+	WRITECHAR(save_p, ht->triggerOnExit);
+}
+
 // SaveRaiseThinker
 //
 // Saves a raise_t thinker
@@ -2250,7 +2268,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker)
 			{
-				SaveSpecialLevelThinker(th, tc_eachtime);
+				SaveEachTimeThinker(th, tc_eachtime);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_RaiseSector)
@@ -2788,6 +2806,25 @@ static thinker_t* LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeili
 	return &ht->thinker;
 }
 
+// LoadEachTimeThinker
+//
+// Loads a eachtime_t from a save game
+//
+static thinker_t* LoadEachTimeThinker(actionf_p1 thinker)
+{
+	size_t i;
+	eachtime_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ht->thinker.function.acp1 = thinker;
+	ht->sourceline = LoadLine(READUINT32(save_p));
+	for (i = 0; i < MAXPLAYERS; i++)
+	{
+		ht->playersInArea[i] = READCHAR(save_p);
+		ht->playersOnArea[i] = READCHAR(save_p);
+	}
+	ht->triggerOnExit = READCHAR(save_p);
+	return &ht->thinker;
+}
+
 // LoadRaiseThinker
 //
 // Loads a raise_t from a save game
@@ -3481,7 +3518,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_eachtime:
-					th = LoadSpecialLevelThinker((actionf_p1)T_EachTimeThinker, 0);
+					th = LoadEachTimeThinker((actionf_p1)T_EachTimeThinker);
 					break;
 
 				case tc_raisesector:
diff --git a/src/p_spec.c b/src/p_spec.c
index a72f56cc0..7a99b1fad 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6160,14 +6160,13 @@ static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline)
 /** Adds a thinker for Each-Time linedef executors. A linedef executor is run
   * only when a player enters the area and doesn't run again until they re-enter.
   *
-  * \param sec          Control sector that contains the lines of executors we will want to run.
   * \param sourceline   Control linedef.
   * \sa P_SpawnSpecials, T_EachTimeThinker
   * \author SSNTails <http://www.ssntails.org>
   */
-static void P_AddEachTimeThinker(sector_t *sec, line_t *sourceline)
+static void P_AddEachTimeThinker(line_t *sourceline)
 {
-	levelspecthink_t *eachtime;
+	eachtime_t *eachtime;
 
 	// create and initialize new thinker
 	eachtime = Z_Calloc(sizeof (*eachtime), PU_LEVSPEC, NULL);
@@ -6175,8 +6174,8 @@ static void P_AddEachTimeThinker(sector_t *sec, line_t *sourceline)
 
 	eachtime->thinker.function.acp1 = (actionf_p1)T_EachTimeThinker;
 
-	eachtime->sector = sec;
 	eachtime->sourceline = sourceline;
+	eachtime->triggerOnExit = !!(sourceline->flags & ML_BOUNCY);
 }
 
 /** Adds a camera scanner.
@@ -7160,7 +7159,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 			case 332:
 			case 335:
 				sec = sides[*lines[i].sidenum].sector - sectors;
-				P_AddEachTimeThinker(&sectors[sec], &lines[i]);
+				P_AddEachTimeThinker(&lines[i]);
 				break;
 
 			// No More Enemies Linedef Exec
@@ -7192,7 +7191,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 				if (lines[i].special == 322) // Each time
 				{
 					sec = sides[*lines[i].sidenum].sector - sectors;
-					P_AddEachTimeThinker(&sectors[sec], &lines[i]);
+					P_AddEachTimeThinker(&lines[i]);
 				}
 				break;
 
diff --git a/src/p_spec.h b/src/p_spec.h
index eb61ad7bf..8cccc96e4 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -320,6 +320,15 @@ typedef struct
 	sector_t *sector;   // Sector the thinker is from
 } levelspecthink_t;
 
+typedef struct
+{
+	thinker_t thinker;
+	line_t *sourceline; // Source line of the thinker
+	boolean playersInArea[MAXPLAYERS];
+	boolean playersOnArea[MAXPLAYERS];
+	boolean triggerOnExit;
+} eachtime_t;
+
 typedef enum
 {
 	RF_REVERSE  = 1,    //Lower when stood on
@@ -377,7 +386,7 @@ void T_FloatSector(levelspecthink_t *floater);
 void T_MarioBlockChecker(levelspecthink_t *block);
 void T_ThwompSector(levelspecthink_t *thwomp);
 void T_NoEnemiesSector(levelspecthink_t *nobaddies);
-void T_EachTimeThinker(levelspecthink_t *eachtime);
+void T_EachTimeThinker(eachtime_t *eachtime);
 void T_CameraScanner(elevator_t *elevator);
 void T_RaiseSector(raise_t *raise);
 

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 172/251] Refactor T_EachTimeThinker

---
 src/p_floor.c | 180 ++++++++++++++++----------------------------------
 1 file changed, 58 insertions(+), 122 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index a5c358621..2a0d09b65 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 (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 (!(sec->flags & SF_TRIGGERSPECIAL_TOUCH))
+		return false;
+
+	for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
 	{
-		if (inAndOut && !curPlayers[i] && oldPlayers[i])
-			return i;
-
-		if (curPlayers[i] && !oldPlayers[i])
-			return i;
+		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])
+				if (!P_IsPlayerValid(i))
 					continue;
 
-				if (!players[i].mo)
-					continue;
-
-				if (players[i].mo->health <= 0)
-					continue;
-
-				if ((netgame || multiplayer) && players[i].spectator)
-					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 ((netgame || multiplayer) && players[i].spectator)
-					continue;
-
-				if (!playersArea[i])
-					return;
-			}
+			if (P_IsPlayerValid(i) && playersArea[i])
+				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 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];
 	}
 }
 

From 099ad6cf201fa9888271a523c7b67bf050f990fc Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 17 Apr 2020 21:39:38 +0200
Subject: [PATCH 173/251] Remove sec assignments that have become superfluous

---
 src/p_spec.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index 7a99b1fad..295be09e9 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -7158,7 +7158,6 @@ void P_SpawnSpecials(boolean fromnetsave)
 			case 312:
 			case 332:
 			case 335:
-				sec = sides[*lines[i].sidenum].sector - sectors;
 				P_AddEachTimeThinker(&lines[i]);
 				break;
 
@@ -7189,10 +7188,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 				else
 					lines[i].callcount = sides[lines[i].sidenum[0]].textureoffset>>FRACBITS;
 				if (lines[i].special == 322) // Each time
-				{
-					sec = sides[*lines[i].sidenum].sector - sectors;
 					P_AddEachTimeThinker(&lines[i]);
-				}
 				break;
 
 			// NiGHTS trigger executors

From 9b27d004e3462d3861934f1196bc322055593c86 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 17 Apr 2020 22:54:35 +0200
Subject: [PATCH 174/251] Remove the spike thinker, which hasn't been necessary
 for a while now

---
 src/p_floor.c | 72 ---------------------------------------------------
 src/p_saveg.c | 10 -------
 src/p_spec.c  | 49 ++++-------------------------------
 src/p_spec.h  |  1 -
 4 files changed, 5 insertions(+), 127 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 2a0d09b65..52a348cb7 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1069,78 +1069,6 @@ void T_MarioBlock(levelspecthink_t *block)
 #undef low
 }
 
-void T_SpikeSector(levelspecthink_t *spikes)
-{
-	mobj_t *thing;
-	msecnode_t *node;
-	boolean dothepain;
-	sector_t *affectsec;
-
-	node = spikes->sector->touching_thinglist; // things touching this sector
-
-	for (; node; node = node->m_thinglist_next)
-	{
-		thing = node->m_thing;
-		if (!thing->player)
-			continue;
-
-		dothepain = false;
-		affectsec = &sectors[spikes->vars[0]];
-
-		if (affectsec == spikes->sector) // Applied to an actual sector
-		{
-			fixed_t affectfloor = P_GetSpecialBottomZ(thing, affectsec, affectsec);
-			fixed_t affectceil = P_GetSpecialTopZ(thing, affectsec, affectsec);
-
-			if (affectsec->flags & SF_FLIPSPECIAL_FLOOR)
-			{
-				if (!(thing->eflags & MFE_VERTICALFLIP) && thing->momz > 0)
-					continue;
-
-				if (thing->z == affectfloor)
-					dothepain = true;
-			}
-
-			if (affectsec->flags & SF_FLIPSPECIAL_CEILING)
-			{
-				if ((thing->eflags & MFE_VERTICALFLIP) && thing->momz < 0)
-					continue;
-
-				if (thing->z + thing->height == affectceil)
-					dothepain = true;
-			}
-		}
-		else
-		{
-			fixed_t affectfloor = P_GetSpecialBottomZ(thing, affectsec, spikes->sector);
-			fixed_t affectceil = P_GetSpecialTopZ(thing, affectsec, spikes->sector);
-			if (affectsec->flags & SF_FLIPSPECIAL_FLOOR)
-			{
-				if (!(thing->eflags & MFE_VERTICALFLIP) && thing->momz > 0)
-					continue;
-
-				if (thing->z == affectceil)
-					dothepain = true;
-			}
-
-			if (affectsec->flags & SF_FLIPSPECIAL_CEILING)
-			{
-				if ((thing->eflags & MFE_VERTICALFLIP) && thing->momz < 0)
-					continue;
-
-				if (thing->z + thing->height == affectfloor)
-					dothepain = true;
-			}
-		}
-
-		if (dothepain)
-		{
-			P_DamageMobj(thing, NULL, NULL, 1, DMG_SPIKE);
-			break;
-		}
-	}
-}
-
 void T_FloatSector(levelspecthink_t *floater)
 {
 	fixed_t cheeseheight;
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 58fb7ad52..c9d4bb5fb 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1273,7 +1273,6 @@ typedef enum
 	tc_startcrumble,
 	tc_marioblock,
 	tc_marioblockchecker,
-	tc_spikesector,
 	tc_floatsector,
 	tc_crushceiling,
 	tc_scroll,
@@ -2316,11 +2315,6 @@ static void P_NetArchiveThinkers(void)
 				SaveSpecialLevelThinker(th, tc_marioblockchecker);
 				continue;
 			}
-			else if (th->function.acp1 == (actionf_p1)T_SpikeSector)
-			{
-				SaveSpecialLevelThinker(th, tc_spikesector);
-				continue;
-			}
 			else if (th->function.acp1 == (actionf_p1)T_FloatSector)
 			{
 				SaveSpecialLevelThinker(th, tc_floatsector);
@@ -3547,10 +3541,6 @@ static void P_NetUnArchiveThinkers(void)
 					th = LoadSpecialLevelThinker((actionf_p1)T_MarioBlockChecker, 0);
 					break;
 
-				case tc_spikesector:
-					th = LoadSpecialLevelThinker((actionf_p1)T_SpikeSector, 0);
-					break;
-
 				case tc_floatsector:
 					th = LoadSpecialLevelThinker((actionf_p1)T_FloatSector, 0);
 					break;
diff --git a/src/p_spec.c b/src/p_spec.c
index 295be09e9..2dcc21cbe 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -119,7 +119,6 @@ static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline);
 static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinkerlist_t *secthinkers);
 static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec);
 static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer);
-static void P_AddSpikeThinker(sector_t *sec, INT32 referrer);
 static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee, UINT8 reverse);
 
 
@@ -4446,7 +4445,8 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
 				P_DamageMobj(player->mo, NULL, NULL, 1, DMG_ELECTRIC);
 			break;
 		case 5: // Spikes
-			// Don't do anything. In Soviet Russia, spikes find you.
+			if (roversector || P_MobjReadyToTrigger(player->mo, sector))
+				P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPIKE);
 			break;
 		case 6: // Death Pit (Camera Mod)
 		case 7: // Death Pit (No Camera Mod)
@@ -5754,7 +5754,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
 	thinker_t *th;
 	friction_t *f;
 	pusher_t *p;
-	levelspecthink_t *lst;
 	size_t sec2num;
 	size_t i;
 
@@ -5855,16 +5854,8 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
 		else if (th == &thlist[THINK_MAIN])
 			break;
 
-		// Should this FOF have spikeness?
-		if (th->function.acp1 == (actionf_p1)T_SpikeSector)
-		{
-			lst = (levelspecthink_t *)th;
-
-			if (lst->sector == sec2)
-				P_AddSpikeThinker(sec, (INT32)sec2num);
-		}
 		// Should this FOF have friction?
-		else if(th->function.acp1 == (actionf_p1)T_Friction)
+		if(th->function.acp1 == (actionf_p1)T_Friction)
 		{
 			f = (friction_t *)th;
 
@@ -5928,28 +5919,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
 // SPECIAL SPAWNING
 //
 
-/** Adds a spike thinker.
-  * Sector type Section1:5 will result in this effect.
-  *
-  * \param sec Sector in which to add the thinker.
-  * \param referrer If != sec, then we're dealing with a FOF
-  * \sa P_SpawnSpecials, T_SpikeSector
-  * \author SSNTails <http://www.ssntails.org>
-  */
-static void P_AddSpikeThinker(sector_t *sec, INT32 referrer)
-{
-	levelspecthink_t *spikes;
-
-	// create and initialize new thinker
-	spikes = Z_Calloc(sizeof (*spikes), PU_LEVSPEC, NULL);
-	P_AddThinker(THINK_MAIN, &spikes->thinker);
-
-	spikes->thinker.function.acp1 = (actionf_p1)T_SpikeSector;
-
-	spikes->sector = sec;
-	spikes->vars[0] = referrer;
-}
-
 /** Adds a float thinker.
   * Float thinkers cause solid 3Dfloors to float on water.
   *
@@ -6401,10 +6370,6 @@ void P_SpawnSpecials(boolean fromnetsave)
 		// Process Section 1
 		switch(GETSECSPECIAL(sector->special, 1))
 		{
-			case 5: // Spikes
-				P_AddSpikeThinker(sector, (INT32)(sector-sectors));
-				break;
-
 			case 15: // Bouncy sector
 				CheckForBouncySector = true;
 				break;
@@ -6450,9 +6415,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 	// Firstly, find out how many there are in each sector
 	for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
 	{
-		if (th->function.acp1 == (actionf_p1)T_SpikeSector)
-			secthinkers[((levelspecthink_t *)th)->sector - sectors].count++;
-		else if (th->function.acp1 == (actionf_p1)T_Friction)
+		if (th->function.acp1 == (actionf_p1)T_Friction)
 			secthinkers[((friction_t *)th)->affectee].count++;
 		else if (th->function.acp1 == (actionf_p1)T_Pusher)
 			secthinkers[((pusher_t *)th)->affectee].count++;
@@ -6472,9 +6435,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 	{
 		size_t secnum = (size_t)-1;
 
-		if (th->function.acp1 == (actionf_p1)T_SpikeSector)
-			secnum = ((levelspecthink_t *)th)->sector - sectors;
-		else if (th->function.acp1 == (actionf_p1)T_Friction)
+		if (th->function.acp1 == (actionf_p1)T_Friction)
 			secnum = ((friction_t *)th)->affectee;
 		else if (th->function.acp1 == (actionf_p1)T_Pusher)
 			secnum = ((pusher_t *)th)->affectee;
diff --git a/src/p_spec.h b/src/p_spec.h
index 8cccc96e4..79f6090fd 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -381,7 +381,6 @@ void T_ContinuousFalling(levelspecthink_t *faller);
 void T_BounceCheese(levelspecthink_t *bouncer);
 void T_StartCrumble(elevator_t *elevator);
 void T_MarioBlock(levelspecthink_t *block);
-void T_SpikeSector(levelspecthink_t *spikes);
 void T_FloatSector(levelspecthink_t *floater);
 void T_MarioBlockChecker(levelspecthink_t *block);
 void T_ThwompSector(levelspecthink_t *thwomp);

From 779b10681fa45f983513807ec67079d2e9e00f24 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 17 Apr 2020 23:32:39 +0200
Subject: [PATCH 175/251] Refactoring in T_BounceCheese

---
 src/p_floor.c | 69 +++++++++++++++++++++------------------------------
 1 file changed, 28 insertions(+), 41 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 52a348cb7..85304d779 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -682,11 +682,13 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 #define low vars[2]
 #define ceilingwasheight vars[3]
 #define floorwasheight vars[4]
+	fixed_t sectorheight;
 	fixed_t halfheight;
 	fixed_t waterheight;
 	fixed_t floorheight;
 	sector_t *actionsector;
 	INT32 i;
+	boolean remove;
 
 	if (bouncer->sector->crumblestate == 4 || bouncer->sector->crumblestate == 1
 		|| bouncer->sector->crumblestate == 2) // Oops! Crumbler says to remove yourself!
@@ -706,43 +708,28 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 		actionsector = &sectors[i];
 		actionsector->moved = true;
 
-		halfheight = abs(bouncer->sector->ceilingheight - bouncer->sector->floorheight) >> 1;
+		sectorheight = abs(bouncer->sector->ceilingheight - bouncer->sector->floorheight);
+		halfheight = sectorheight/2;
 
 		waterheight = P_SectorCheckWater(actionsector, bouncer->sector); // sorts itself out if there's no suitable water in the sector
 
-		floorheight = P_FloorzAtPos(actionsector->soundorg.x, actionsector->soundorg.y, bouncer->sector->floorheight, halfheight << 1);
+		floorheight = P_FloorzAtPos(actionsector->soundorg.x, actionsector->soundorg.y, bouncer->sector->floorheight, sectorheight);
+
+		remove = false;
 
 		// Water level is up to the ceiling.
 		if (waterheight > bouncer->sector->ceilingheight - halfheight && bouncer->sector->ceilingheight >= actionsector->ceilingheight) // Tails 01-08-2004
 		{
 			bouncer->sector->ceilingheight = actionsector->ceilingheight;
-			bouncer->sector->floorheight = bouncer->sector->ceilingheight - (halfheight*2);
-			T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, 0, 1, -1); // update things on ceiling
-			T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, 0, 0, -1); // update things on floor
-			P_RecalcPrecipInSector(actionsector);
-			bouncer->sector->ceilingdata = NULL;
-			bouncer->sector->floordata = NULL;
-			bouncer->sector->floorspeed = 0;
-			bouncer->sector->ceilspeed = 0;
-			bouncer->sector->moved = true;
-			P_RemoveThinker(&bouncer->thinker); // remove bouncer from actives
-			return;
+			bouncer->sector->floorheight = actionsector->ceilingheight - sectorheight;
+			remove = true;
 		}
 		// Water level is too shallow.
 		else if (waterheight < bouncer->sector->floorheight + halfheight && bouncer->sector->floorheight <= floorheight)
 		{
-			bouncer->sector->ceilingheight = floorheight + (halfheight << 1);
+			bouncer->sector->ceilingheight = floorheight + sectorheight;
 			bouncer->sector->floorheight = floorheight;
-			T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, 0, 1, -1); // update things on ceiling
-			T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, 0, 0, -1); // update things on floor
-			P_RecalcPrecipInSector(actionsector);
-			bouncer->sector->ceilingdata = NULL;
-			bouncer->sector->floordata = NULL;
-			bouncer->sector->floorspeed = 0;
-			bouncer->sector->ceilspeed = 0;
-			bouncer->sector->moved = true;
-			P_RemoveThinker(&bouncer->thinker); // remove bouncer from actives
-			return;
+			remove = true;
 		}
 		else
 		{
@@ -750,6 +737,20 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 			bouncer->floorwasheight = waterheight - halfheight;
 		}
 
+		if (remove)
+		{
+			T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, 0, 1, -1); // update things on ceiling
+			T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, 0, 0, -1); // update things on floor
+			P_RecalcPrecipInSector(actionsector);
+			bouncer->sector->ceilingdata = NULL;
+			bouncer->sector->floordata = NULL;
+			bouncer->sector->floorspeed = 0;
+			bouncer->sector->ceilspeed = 0;
+			bouncer->sector->moved = true;
+			P_RemoveThinker(&bouncer->thinker); // remove bouncer from actives
+			return;
+		}
+
 		T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight -
 			70*FRACUNIT, 0, 1, -1); // move ceiling
 		T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT,
@@ -758,29 +759,15 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 		bouncer->sector->floorspeed = -bouncer->speed/2;
 		bouncer->sector->ceilspeed = 42;
 
-		if (bouncer->sector->ceilingheight < bouncer->ceilingwasheight && bouncer->low == 0) // Down
+		if ((bouncer->sector->ceilingheight < bouncer->ceilingwasheight && bouncer->low == 0) // Down
+			|| (bouncer->sector->ceilingheight > bouncer->ceilingwasheight && bouncer->low)) // Up
 		{
 			if (abs(bouncer->speed) < 6*FRACUNIT)
 				bouncer->speed -= bouncer->speed/3;
 			else
 				bouncer->speed -= bouncer->speed/2;
 
-			bouncer->low = 1;
-			if (abs(bouncer->speed) > 6*FRACUNIT)
-			{
-				mobj_t *mp = (void *)&actionsector->soundorg;
-				actionsector->soundorg.z = bouncer->sector->floorheight;
-				S_StartSound(mp, sfx_splash);
-			}
-		}
-		else if (bouncer->sector->ceilingheight > bouncer->ceilingwasheight && bouncer->low) // Up
-		{
-			if (abs(bouncer->speed) < 6*FRACUNIT)
-				bouncer->speed -= bouncer->speed/3;
-			else
-				bouncer->speed -= bouncer->speed/2;
-
-			bouncer->low = 0;
+			bouncer->low = bouncer->low ? 0 : 1;
 			if (abs(bouncer->speed) > 6*FRACUNIT)
 			{
 				mobj_t *mp = (void *)&actionsector->soundorg;

From fd598f315e2f4717aff233384e5744bfbf035f30 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 17 Apr 2020 23:54:37 +0200
Subject: [PATCH 176/251] Add an enum for crumblestate

---
 src/p_floor.c | 29 ++++++++++-------------------
 src/p_mobj.c  |  2 +-
 src/p_setup.c |  2 +-
 src/p_spec.c  |  2 +-
 src/p_user.c  |  4 ++--
 src/r_defs.h  | 10 ++++++++++
 6 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 85304d779..0f1472810 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -690,10 +690,10 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 	INT32 i;
 	boolean remove;
 
-	if (bouncer->sector->crumblestate == 4 || bouncer->sector->crumblestate == 1
-		|| bouncer->sector->crumblestate == 2) // Oops! Crumbler says to remove yourself!
+	if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT
+		|| bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself!
 	{
-		bouncer->sector->crumblestate = 1;
+		bouncer->sector->crumblestate = CRUMBLE_WAIT;
 		bouncer->sector->ceilingdata = NULL;
 		bouncer->sector->ceilspeed = 0;
 		bouncer->sector->floordata = NULL;
@@ -817,15 +817,6 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 // T_StartCrumble ////////////////////////////////
 //////////////////////////////////////////////////
 // Crumbling platform Tails 03-11-2002
-//
-// DEFINITION OF THE 'CRUMBLESTATE'S:
-//
-// 0 - No crumble thinker
-// 1 - Don't float on water because this is supposed to wait for a crumble
-// 2 - Crumble thinker activated, but hasn't fallen yet
-// 3 - Crumble thinker is falling
-// 4 - Crumble thinker is about to restore to original position
-//
 void T_StartCrumble(elevator_t *elevator)
 {
 	ffloor_t *rover;
@@ -921,13 +912,13 @@ void T_StartCrumble(elevator_t *elevator)
 		// so set this to let other thinkers know what is
 		// about to happen.
 		if (elevator->distance < 0 && elevator->distance > -3)
-			elevator->sector->crumblestate = 4; // makes T_BounceCheese remove itself
+			elevator->sector->crumblestate = CRUMBLE_RESTORE; // makes T_BounceCheese remove itself
 	}
 
 	if ((elevator->floordestheight == 0 && elevator->direction == -1)
 		|| (elevator->floordestheight == 1 && elevator->direction == 1)) // Down
 	{
-		elevator->sector->crumblestate = 3; // Allow floating now.
+		elevator->sector->crumblestate = CRUMBLE_FALL; // Allow floating now.
 
 		// Only fall like this if it isn't meant to float on water
 		if (elevator->high != 42)
@@ -976,7 +967,7 @@ void T_StartCrumble(elevator_t *elevator)
 	}
 	else // Up (restore to original position)
 	{
-		elevator->sector->crumblestate = 1;
+		elevator->sector->crumblestate = CRUMBLE_WAIT;
 		elevator->sector->ceilingheight = elevator->ceilingwasheight;
 		elevator->sector->floorheight = elevator->floorwasheight;
 		elevator->sector->floordata = NULL;
@@ -1085,7 +1076,7 @@ void T_FloatSector(levelspecthink_t *floater)
 		else if (floater->sector->ceilingheight == actionsector->ceilingheight && waterheight > cheeseheight) // too high
 			;
 		// we have something to float in! Or we're for some reason above the ground, let's fall anyway
-		else if (floater->sector->crumblestate == 0 || floater->sector->crumblestate >= 3/* || floatanyway*/)
+		else if (floater->sector->crumblestate == CRUMBLE_NONE || floater->sector->crumblestate >= CRUMBLE_FALL/* || floatanyway*/)
 			EV_BounceSector(floater->sector, FRACUNIT, floater->sourceline);
 
 		P_RecalcPrecipInSector(actionsector);
@@ -1687,7 +1678,7 @@ void T_RaiseSector(raise_t *raise)
 	INT32 direction;
 	result_e res = 0;
 
-	if (raise->sector->crumblestate >= 3 || raise->sector->ceilingdata)
+	if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata)
 		return;
 
 	for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->tag, i)) >= 0 ;)
@@ -2489,7 +2480,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
 	if (sec->floordata)
 		return 0;
 
-	if (sec->crumblestate > 1)
+	if (sec->crumblestate >= CRUMBLE_ACTIVATED)
 		return 0;
 
 	// create and initialize new elevator thinker
@@ -2534,7 +2525,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
 	else
 		elevator->high = 0;
 
-	elevator->sector->crumblestate = 2;
+	elevator->sector->crumblestate = CRUMBLE_ACTIVATED;
 
 	for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
 	{
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 7e65c37ad..967e868ae 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -1691,7 +1691,7 @@ static void P_PushableCheckBustables(mobj_t *mo)
 				// Needs ML_EFFECT4 flag for pushables to break it
 				if (!(rover->master->flags & ML_EFFECT4)) continue;
 
-				if (!rover->master->frontsector->crumblestate)
+				if (rover->master->frontsector->crumblestate == CRUMBLE_NONE)
 				{
 					topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
 					bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
diff --git a/src/p_setup.c b/src/p_setup.c
index 700113d85..baccc294c 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -866,7 +866,7 @@ static void P_InitializeSector(sector_t *ss)
 	ss->camsec = -1;
 
 	ss->floorlightsec = ss->ceilinglightsec = -1;
-	ss->crumblestate = 0;
+	ss->crumblestate = CRUMBLE_NONE;
 
 	ss->touching_thinglist = NULL;
 
diff --git a/src/p_spec.c b/src/p_spec.c
index 2dcc21cbe..7d10a1152 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -5902,7 +5902,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
 	}
 
 	if ((flags & FF_CRUMBLE))
-		sec2->crumblestate = 1;
+		sec2->crumblestate = CRUMBLE_WAIT;
 
 	if ((flags & FF_FLOATBOB))
 	{
diff --git a/src/p_user.c b/src/p_user.c
index 994eb7007..3de69fbc5 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -2566,7 +2566,7 @@ static void P_CheckBustableBlocks(player_t *player)
 			{
 				if (!(rover->flags & FF_EXISTS)) continue;
 
-				if ((rover->flags & FF_BUSTUP)/* && !rover->master->frontsector->crumblestate*/)
+				if ((rover->flags & FF_BUSTUP)/* && rover->master->frontsector->crumblestate == CRUMBLE_NONE*/)
 				{
 					// If it's an FF_SHATTER, you can break it just by touching it.
 					if (rover->flags & FF_SHATTER)
@@ -12213,7 +12213,7 @@ void P_PlayerThink(player_t *player)
 		player->powers[pw_nocontrol]--;
 	else
 		player->powers[pw_nocontrol] = 0;
-	
+
 	//pw_super acts as a timer now
 	if (player->powers[pw_super]
 	&& (player->mo->state < &states[S_PLAY_SUPER_TRANS1]
diff --git a/src/r_defs.h b/src/r_defs.h
index 10c0721ac..4a8f5be34 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -277,6 +277,16 @@ typedef enum
 	SF_INVERTPRECIP            =  1<<4,
 } sectorflags_t;
 
+
+typedef enum
+{
+	CRUMBLE_NONE, // No crumble thinker
+	CRUMBLE_WAIT, // Don't float on water because this is supposed to wait for a crumble
+	CRUMBLE_ACTIVATED, // Crumble thinker activated, but hasn't fallen yet
+	CRUMBLE_FALL, // Crumble thinker is falling
+	CRUMBLE_RESTORE, // Crumble thinker is about to restore to original position
+} crumblestate_t;
+
 //
 // The SECTORS record, at runtime.
 // Stores things/mobjs.

From cc0f686c9505606e75602ee6ecaca6466c796046 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 18 Apr 2020 00:26:49 +0200
Subject: [PATCH 177/251] Refactor T_FloatSector

---
 src/p_floor.c | 43 ++++++++++++++++++++-----------------------
 src/p_saveg.c | 32 ++++++++++++++++++++++++++++++--
 src/p_spec.c  |  8 ++++----
 src/p_spec.h  | 10 +++++++++-
 4 files changed, 63 insertions(+), 30 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 0f1472810..e787d1e13 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1047,40 +1047,37 @@ void T_MarioBlock(levelspecthink_t *block)
 #undef low
 }
 
-void T_FloatSector(levelspecthink_t *floater)
+void T_FloatSector(floatthink_t *floater)
 {
 	fixed_t cheeseheight;
+	fixed_t waterheight;
 	sector_t *actionsector;
 	INT32 secnum;
 
-	cheeseheight = (floater->sector->ceilingheight + floater->sector->floorheight)>>1;
-
 	// Just find the first sector with the tag.
 	// Doesn't work with multiple sectors that have different floor/ceiling heights.
-	secnum = P_FindSectorFromTag((INT16)floater->vars[0], -1);
+	secnum = P_FindSectorFromTag(floater->tag, -1);
+	if (secnum <= 0)
+		return;
+	actionsector = &sectors[secnum];
 
-	if (secnum > 0)
-		actionsector = &sectors[secnum];
-	else
-		actionsector = NULL;
+	cheeseheight = (floater->sector->ceilingheight + floater->sector->floorheight)>>1;
 
-	if (actionsector)
-	{
-		//boolean floatanyway = false; // Ignore the crumblestate setting.
-		fixed_t waterheight = P_SectorCheckWater(actionsector, floater->sector); // find the highest suitable water block around
+	//boolean floatanyway = false; // Ignore the crumblestate setting.
+	waterheight = P_SectorCheckWater(actionsector, floater->sector); // find the highest suitable water block around
 
-		if (waterheight == cheeseheight) // same height, no floating needed
-			;
-		else if (floater->sector->floorheight == actionsector->floorheight && waterheight < cheeseheight) // too low
-			;
-		else if (floater->sector->ceilingheight == actionsector->ceilingheight && waterheight > cheeseheight) // too high
-			;
-		// we have something to float in! Or we're for some reason above the ground, let's fall anyway
-		else if (floater->sector->crumblestate == CRUMBLE_NONE || floater->sector->crumblestate >= CRUMBLE_FALL/* || floatanyway*/)
-			EV_BounceSector(floater->sector, FRACUNIT, floater->sourceline);
+	if (waterheight == cheeseheight) // same height, no floating needed
+		return;
 
-		P_RecalcPrecipInSector(actionsector);
-	}
+	if (floater->sector->floorheight == actionsector->floorheight && waterheight < cheeseheight) // too low
+		return;
+
+	if (floater->sector->ceilingheight == actionsector->ceilingheight && waterheight > cheeseheight) // too high
+		return;
+
+	// we have something to float in! Or we're for some reason above the ground, let's fall anyway
+	if (floater->sector->crumblestate == CRUMBLE_NONE || floater->sector->crumblestate >= CRUMBLE_FALL/* || floatanyway*/)
+		EV_BounceSector(floater->sector, FRACUNIT, floater->sourceline);
 }
 
 static mobj_t *SearchMarioNode(msecnode_t *node)
diff --git a/src/p_saveg.c b/src/p_saveg.c
index c9d4bb5fb..443480813 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1658,6 +1658,20 @@ static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveSector(ht->sector));
 }
 
+//
+// SaveFloatThinker
+//
+// Saves a floatthink_t thinker
+//
+static void SaveFloatThinker(const thinker_t *th, const UINT8 type)
+{
+	const floatthink_t *ht  = (const void *)th;
+	WRITEUINT8(save_p, type);
+	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+	WRITEUINT32(save_p, SaveSector(ht->sector));
+	WRITEINT16(save_p, ht->tag);
+}
+
 // SaveEachTimeThinker
 //
 // Loads a eachtime_t from a save game
@@ -2317,7 +2331,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_FloatSector)
 			{
-				SaveSpecialLevelThinker(th, tc_floatsector);
+				SaveFloatThinker(th, tc_floatsector);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_LaserFlash)
@@ -2800,6 +2814,20 @@ static thinker_t* LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeili
 	return &ht->thinker;
 }
 
+// LoadFloatThinker
+//
+// Loads a floatthink_t from a save game
+//
+static thinker_t* LoadFloatThinker(actionf_p1 thinker)
+{
+	floatthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ht->thinker.function.acp1 = thinker;
+	ht->sourceline = LoadLine(READUINT32(save_p));
+	ht->sector = LoadSector(READUINT32(save_p));
+	ht->tag = READINT16(save_p);
+	return &ht->thinker;
+}
+
 // LoadEachTimeThinker
 //
 // Loads a eachtime_t from a save game
@@ -3542,7 +3570,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_floatsector:
-					th = LoadSpecialLevelThinker((actionf_p1)T_FloatSector, 0);
+					th = LoadFloatThinker((actionf_p1)T_FloatSector);
 					break;
 
 				case tc_laserflash:
diff --git a/src/p_spec.c b/src/p_spec.c
index 7d10a1152..54a6d88d6 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -114,7 +114,7 @@ static void P_ResetColormapFader(sector_t *sector);
 static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc,
 	boolean ticbased, INT32 duration);
 static void P_AddBlockThinker(sector_t *sec, line_t *sourceline);
-static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline);
+static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline);
 //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec);
 static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinkerlist_t *secthinkers);
 static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec);
@@ -5927,9 +5927,9 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
   * \sa P_SpawnSpecials, T_FloatSector
   * \author SSNTails <http://www.ssntails.org>
   */
-static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline)
+static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline)
 {
-	levelspecthink_t *floater;
+	floatthink_t *floater;
 
 	// create and initialize new thinker
 	floater = Z_Calloc(sizeof (*floater), PU_LEVSPEC, NULL);
@@ -5938,7 +5938,7 @@ static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline)
 	floater->thinker.function.acp1 = (actionf_p1)T_FloatSector;
 
 	floater->sector = sec;
-	floater->vars[0] = tag;
+	floater->tag = (INT16)tag;
 	floater->sourceline = sourceline;
 }
 
diff --git a/src/p_spec.h b/src/p_spec.h
index 79f6090fd..78cf817ea 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -320,6 +320,14 @@ typedef struct
 	sector_t *sector;   // Sector the thinker is from
 } levelspecthink_t;
 
+typedef struct
+{
+	thinker_t thinker;
+	line_t *sourceline;
+	sector_t *sector;
+	INT16 tag;
+} floatthink_t;
+
 typedef struct
 {
 	thinker_t thinker;
@@ -381,7 +389,7 @@ void T_ContinuousFalling(levelspecthink_t *faller);
 void T_BounceCheese(levelspecthink_t *bouncer);
 void T_StartCrumble(elevator_t *elevator);
 void T_MarioBlock(levelspecthink_t *block);
-void T_FloatSector(levelspecthink_t *floater);
+void T_FloatSector(floatthink_t *floater);
 void T_MarioBlockChecker(levelspecthink_t *block);
 void T_ThwompSector(levelspecthink_t *thwomp);
 void T_NoEnemiesSector(levelspecthink_t *nobaddies);

From 70d262653eac26a01fe0f970f2f0a86af8b2d9a0 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 18 Apr 2020 01:08:01 +0200
Subject: [PATCH 178/251] Refactor T_MovePlane a little bit

---
 src/p_ceilng.c |  16 ++-
 src/p_floor.c  | 287 +++++++++++++++++++++++--------------------------
 src/p_spec.h   |   2 +-
 3 files changed, 141 insertions(+), 164 deletions(-)

diff --git a/src/p_ceilng.c b/src/p_ceilng.c
index c65156b6f..31a4895ba 100644
--- a/src/p_ceilng.c
+++ b/src/p_ceilng.c
@@ -47,8 +47,7 @@ void T_MoveCeiling(ceiling_t *ceiling)
 		case 0: // IN STASIS
 			break;
 		case 1: // UP
-			res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight, false,
-				1, ceiling->direction);
+			res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight, false, true, ceiling->direction);
 
 			if (ceiling->type == bounceCeiling)
 			{
@@ -159,8 +158,7 @@ void T_MoveCeiling(ceiling_t *ceiling)
 			break;
 
 		case -1: // DOWN
-			res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight,
-				ceiling->crush, 1, ceiling->direction);
+			res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, true, ceiling->direction);
 
 			if (ceiling->type == bounceCeiling)
 			{
@@ -314,11 +312,10 @@ void T_CrushCeiling(ceiling_t *ceiling)
 			if (ceiling->type == crushBothOnce)
 			{
 				// Move the floor
-				T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight-(ceiling->topheight-ceiling->bottomheight), false, 0, -ceiling->direction);
+				T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight-(ceiling->topheight-ceiling->bottomheight), false, false, -ceiling->direction);
 			}
 
-			res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight,
-				false, 1, ceiling->direction);
+			res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight, false, true, ceiling->direction);
 
 			if (res == pastdest)
 			{
@@ -357,11 +354,10 @@ void T_CrushCeiling(ceiling_t *ceiling)
 			if (ceiling->type == crushBothOnce)
 			{
 				// Move the floor
-				T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, 0, -ceiling->direction);
+				T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, false, -ceiling->direction);
 			}
 
-			res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight,
-				ceiling->crush, 1, ceiling->direction);
+			res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, true, ceiling->direction);
 
 			if (res == pastdest)
 			{
diff --git a/src/p_floor.c b/src/p_floor.c
index e787d1e13..83b22622f 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -30,146 +30,127 @@
 // Move a plane (floor or ceiling) and check for crushing
 //
 result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crush,
-	INT32 floorOrCeiling, INT32 direction)
+	boolean ceiling, INT32 direction)
 {
-	boolean flag;
 	fixed_t lastpos;
 	fixed_t destheight; // used to keep floors/ceilings from moving through each other
 	sector->moved = true;
 
-	switch (floorOrCeiling)
+	if (ceiling)
 	{
-		case 0:
-			// moving a floor
-			switch (direction)
-			{
-				case -1:
-					// Moving a floor down
-					if (sector->floorheight - speed < dest)
+		lastpos = sector->ceilingheight;
+		// moving a ceiling
+		switch (direction)
+		{
+			case -1:
+				// moving a ceiling down
+				// keep ceiling from moving through floors
+				destheight = (dest > sector->floorheight) ? dest : sector->floorheight;
+				if (sector->ceilingheight - speed < destheight)
+				{
+					sector->ceilingheight = destheight;
+					if (P_CheckSector(sector, crush))
 					{
-						lastpos = sector->floorheight;
-						sector->floorheight = dest;
-						flag = P_CheckSector(sector, crush);
-						if (flag && sector->numattached)
-						{
-							sector->floorheight = lastpos;
-							P_CheckSector(sector, crush);
-						}
-						return pastdest;
+						sector->ceilingheight = lastpos;
+						P_CheckSector(sector, crush);
 					}
-					else
+					return pastdest;
+				}
+				else
+				{
+					// crushing is possible
+					sector->ceilingheight -= speed;
+					if (P_CheckSector(sector, crush))
 					{
-						lastpos = sector->floorheight;
-						sector->floorheight -= speed;
-						flag = P_CheckSector(sector, crush);
-						if (flag && sector->numattached)
-						{
-							sector->floorheight = lastpos;
-							P_CheckSector(sector, crush);
-							return crushed;
-						}
+						sector->ceilingheight = lastpos;
+						P_CheckSector(sector, crush);
+						return crushed;
 					}
-					break;
+				}
+				break;
 
-				case 1:
-					// Moving a floor up
-					// keep floor from moving through ceilings
-					destheight = (dest < sector->ceilingheight) ? dest : sector->ceilingheight;
-					if (sector->floorheight + speed > destheight)
+			case 1:
+				// moving a ceiling up
+				if (sector->ceilingheight + speed > dest)
+				{
+					sector->ceilingheight = dest;
+					if (P_CheckSector(sector, crush) && sector->numattached)
 					{
-						lastpos = sector->floorheight;
-						sector->floorheight = destheight;
-						flag = P_CheckSector(sector, crush);
-						if (flag)
-						{
-							sector->floorheight = lastpos;
-							P_CheckSector(sector, crush);
-						}
-						return pastdest;
+						sector->ceilingheight = lastpos;
+						P_CheckSector(sector, crush);
 					}
-					else
+					return pastdest;
+				}
+				else
+				{
+					sector->ceilingheight += speed;
+					if (P_CheckSector(sector, crush) && sector->numattached)
 					{
-						// crushing is possible
-						lastpos = sector->floorheight;
-						sector->floorheight += speed;
-						flag = P_CheckSector(sector, crush);
-						if (flag)
-						{
-							sector->floorheight = lastpos;
-							P_CheckSector(sector, crush);
-							return crushed;
-						}
+						sector->ceilingheight = lastpos;
+						P_CheckSector(sector, crush);
+						return crushed;
 					}
-					break;
-			}
-			break;
+				}
+				break;
+		}
+	}
+	else
+	{
+		lastpos = sector->floorheight;
+		// moving a floor
+		switch (direction)
+		{
+			case -1:
+				// Moving a floor down
+				if (sector->floorheight - speed < dest)
+				{
+					sector->floorheight = dest;
+					if (P_CheckSector(sector, crush) && sector->numattached)
+					{
+						sector->floorheight = lastpos;
+						P_CheckSector(sector, crush);
+					}
+					return pastdest;
+				}
+				else
+				{
+					sector->floorheight -= speed;
+					if (P_CheckSector(sector, crush) && sector->numattached)
+					{
+						sector->floorheight = lastpos;
+						P_CheckSector(sector, crush);
+						return crushed;
+					}
+				}
+				break;
 
-		case 1:
-			// moving a ceiling
-			switch (direction)
-			{
-				case -1:
-					// moving a ceiling down
-					// keep ceiling from moving through floors
-					destheight = (dest > sector->floorheight) ? dest : sector->floorheight;
-					if (sector->ceilingheight - speed < destheight)
+			case 1:
+				// Moving a floor up
+				// keep floor from moving through ceilings
+				destheight = (dest < sector->ceilingheight) ? dest : sector->ceilingheight;
+				if (sector->floorheight + speed > destheight)
+				{
+					sector->floorheight = destheight;
+					if (P_CheckSector(sector, crush))
 					{
-						lastpos = sector->ceilingheight;
-						sector->ceilingheight = destheight;
-						flag = P_CheckSector(sector, crush);
-
-						if (flag)
-						{
-							sector->ceilingheight = lastpos;
-							P_CheckSector(sector, crush);
-						}
-						return pastdest;
+						sector->floorheight = lastpos;
+						P_CheckSector(sector, crush);
 					}
-					else
+					return pastdest;
+				}
+				else
+				{
+					// crushing is possible
+					sector->floorheight += speed;
+					if (P_CheckSector(sector, crush))
 					{
-						// crushing is possible
-						lastpos = sector->ceilingheight;
-						sector->ceilingheight -= speed;
-						flag = P_CheckSector(sector, crush);
-
-						if (flag)
-						{
-							sector->ceilingheight = lastpos;
-							P_CheckSector(sector, crush);
-							return crushed;
-						}
+						sector->floorheight = lastpos;
+						P_CheckSector(sector, crush);
+						return crushed;
 					}
-					break;
-
-				case 1:
-					// moving a ceiling up
-					if (sector->ceilingheight + speed > dest)
-					{
-						lastpos = sector->ceilingheight;
-						sector->ceilingheight = dest;
-						flag = P_CheckSector(sector, crush);
-						if (flag && sector->numattached)
-						{
-							sector->ceilingheight = lastpos;
-							P_CheckSector(sector, crush);
-						}
-						return pastdest;
-					}
-					else
-					{
-						lastpos = sector->ceilingheight;
-						sector->ceilingheight += speed;
-						flag = P_CheckSector(sector, crush);
-						if (flag && sector->numattached)
-						{
-							sector->ceilingheight = lastpos;
-							P_CheckSector(sector, crush);
-							return crushed;
-						}
-					}
-					break;
-			}
-			break;
+				}
+				break;
+		}
 	}
 
 	return ok;
@@ -192,7 +173,7 @@ void T_MoveFloor(floormove_t *movefloor)
 	res = T_MovePlane(movefloor->sector,
 	                  movefloor->speed,
 	                  movefloor->floordestheight,
-	                  movefloor->crush, 0, movefloor->direction);
+	                  movefloor->crush, false, movefloor->direction);
 
 	if (movefloor->type == bounceFloor)
 	{
@@ -385,7 +366,7 @@ void T_MoveElevator(elevator_t *elevator)
 			elevator->speed,
 			elevator->ceilingdestheight,
 			elevator->distance,
-			1,                          // move floor
+			true,                          // move ceiling
 			elevator->direction
 		);
 
@@ -395,7 +376,7 @@ void T_MoveElevator(elevator_t *elevator)
 			elevator->speed,
 			elevator->floordestheight,
 			elevator->distance,
-			0,                        // move ceiling
+			false,                        // move floor
 			elevator->direction
 		);
 
@@ -447,7 +428,7 @@ void T_MoveElevator(elevator_t *elevator)
 			elevator->speed,
 			elevator->floordestheight,
 			elevator->distance,
-			0,                          // move ceiling
+			false,                          // move floor
 			elevator->direction
 		);
 
@@ -459,7 +440,7 @@ void T_MoveElevator(elevator_t *elevator)
 				elevator->speed,
 				elevator->ceilingdestheight,
 				elevator->distance,
-				1,                        // move floor
+				true,                        // move ceiling
 				elevator->direction
 			);
 		}
@@ -739,8 +720,8 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 
 		if (remove)
 		{
-			T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, 0, 1, -1); // update things on ceiling
-			T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, 0, 0, -1); // update things on floor
+			T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, false, true, -1); // update things on ceiling
+			T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, false, false, -1); // update things on floor
 			P_RecalcPrecipInSector(actionsector);
 			bouncer->sector->ceilingdata = NULL;
 			bouncer->sector->floordata = NULL;
@@ -752,9 +733,9 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 		}
 
 		T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight -
-			70*FRACUNIT, 0, 1, -1); // move ceiling
+			70*FRACUNIT, false, true, -1); // move ceiling
 		T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT,
-			0, 0, -1); // move floor
+			false, false, -1); // move floor
 
 		bouncer->sector->floorspeed = -bouncer->speed/2;
 		bouncer->sector->ceilspeed = 42;
@@ -790,8 +771,8 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 		{
 			bouncer->sector->floorheight = bouncer->floorwasheight;
 			bouncer->sector->ceilingheight = bouncer->ceilingwasheight;
-			T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, 0, 1, -1); // update things on ceiling
-			T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, 0, 0, -1); // update things on floor
+			T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, false, true, -1); // update things on ceiling
+			T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, false, false, -1); // update things on floor
 			bouncer->sector->ceilingdata = NULL;
 			bouncer->sector->floordata = NULL;
 			bouncer->sector->floorspeed = 0;
@@ -940,8 +921,8 @@ void T_StartCrumble(elevator_t *elevator)
 				  elevator->sector,
 				  elevator->speed,
 				  dest,
-				  0,
-				  1, // move floor
+				  false,
+				  true, // move ceiling
 				  elevator->direction
 				);
 
@@ -955,8 +936,8 @@ void T_StartCrumble(elevator_t *elevator)
 					elevator->sector,
 					elevator->speed,
 					dest,
-					0,
-					0,                        // move ceiling
+					false,
+					false, // move floor
 					elevator->direction
 				);
 
@@ -1007,8 +988,8 @@ void T_MarioBlock(levelspecthink_t *block)
 	  block->sector,
 	  block->speed,
 	  block->sector->ceilingheight + 70*FRACUNIT * block->direction,
-	  0,
-	  1, // move floor
+	  false,
+	  true, // move ceiling
 	  block->direction
 	);
 
@@ -1017,8 +998,8 @@ void T_MarioBlock(levelspecthink_t *block)
 	  block->sector,
 	  block->speed,
 	  block->sector->floorheight + 70*FRACUNIT * block->direction,
-	  0,
-	  0, // move ceiling
+	  false,
+	  false, // move floor
 	  block->direction
 	);
 
@@ -1228,8 +1209,8 @@ void T_ThwompSector(levelspecthink_t *thwomp)
 			thwomp->sector,         // sector
 			thwomp->speed,          // speed
 			thwomp->floorwasheight, // dest
-			0,                      // crush
-			0,                      // floor or ceiling (0 for floor)
+			false,                      // crush
+			false,                  // ceiling?
 			thwomp->direction       // direction
 		);
 
@@ -1239,8 +1220,8 @@ void T_ThwompSector(levelspecthink_t *thwomp)
 				thwomp->sector,           // sector
 				thwomp->speed,            // speed
 				thwomp->ceilingwasheight, // dest
-				0,                        // crush
-				1,                        // floor or ceiling (1 for ceiling)
+				false,                        // crush
+				true,                     // ceiling?
 				thwomp->direction         // direction
 			);
 
@@ -1268,8 +1249,8 @@ void T_ThwompSector(levelspecthink_t *thwomp)
 			thwomp->speed,    // speed
 			P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight,
 				thwomp->sector->ceilingheight - thwomp->sector->floorheight), // dest
-			0,                  // crush
-			0,                  // floor or ceiling (0 for floor)
+			false,              // crush
+			false,              // ceiling?
 			thwomp->direction // direction
 		);
 
@@ -1283,8 +1264,8 @@ void T_ThwompSector(levelspecthink_t *thwomp)
 					- (thwomp->sector->floorheight + thwomp->speed))
 					+ (thwomp->sector->ceilingheight
 					- (thwomp->sector->floorheight + thwomp->speed/2)), // dest
-				0,                  // crush
-				1,                  // floor or ceiling (1 for ceiling)
+				false,             // crush
+				true,              // ceiling?
 				thwomp->direction // direction
 			);
 
@@ -1786,8 +1767,8 @@ void T_RaiseSector(raise_t *raise)
 		raise->sector,      // sector
 		speed,              // speed
 		ceilingdestination, // dest
-		0,                  // crush
-		1,                  // floor or ceiling (1 for ceiling)
+		false,              // crush
+		true,               // ceiling?
 		direction           // direction
 	);
 
@@ -1797,8 +1778,8 @@ void T_RaiseSector(raise_t *raise)
 			raise->sector,    // sector
 			speed,            // speed
 			floordestination, // dest
-			0,                // crush
-			0,                // floor or ceiling (0 for floor)
+			false,            // crush
+			false,            // ceiling?
 			direction         // direction
 		);
 
@@ -1900,9 +1881,9 @@ void T_PlaneDisplace(planedisplace_t *pd)
 	}
 
 	if (pd->type == pd_floor || pd->type == pd_both)
-		T_MovePlane(target, INT32_MAX/2, target->floorheight+diff, 0, 0, direction); // move floor
+		T_MovePlane(target, INT32_MAX/2, target->floorheight+diff, false, false, direction); // move floor
 	if (pd->type == pd_ceiling || pd->type == pd_both)
-		T_MovePlane(target, INT32_MAX/2, target->ceilingheight+diff, 0, 1, direction); // move ceiling
+		T_MovePlane(target, INT32_MAX/2, target->ceilingheight+diff, false, true, direction); // move ceiling
 
 	pd->last_height = control->floorheight;
 }
diff --git a/src/p_spec.h b/src/p_spec.h
index 78cf817ea..279d59d7d 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -368,7 +368,7 @@ typedef enum
 } result_e;
 
 result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crush,
-	INT32 floorOrCeiling, INT32 direction);
+	boolean ceiling, INT32 direction);
 INT32 EV_DoFloor(line_t *line, floor_e floortype);
 INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed);
 void EV_CrumbleChain(sector_t *sec, ffloor_t *rover);

From 7e2f95c3f5caafc49b583046eac5d547e6e18e5b Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 18 Apr 2020 01:42:13 +0200
Subject: [PATCH 179/251] Refactor T_ContinuousFalling

---
 src/p_floor.c | 83 +++++++++------------------------------------------
 src/p_saveg.c | 38 +++++++++++++++++++++--
 src/p_spec.h  | 15 ++++++++--
 3 files changed, 63 insertions(+), 73 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 83b22622f..4c6c7fa46 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -561,43 +561,18 @@ void T_MoveElevator(elevator_t *elevator)
 //
 // Useful for things like intermittent falling lava.
 //
-void T_ContinuousFalling(levelspecthink_t *faller)
+void T_ContinuousFalling(continuousfall_t *faller)
 {
-#define speed vars[0]
-#define direction vars[1]
-#define floorwasheight vars[2]
-#define ceilingwasheight vars[3]
-#define floordestheight vars[4]
-#define ceilingdestheight vars[5]
-
-	if (faller->direction == -1)
-	{
-		faller->sector->ceilingheight -= faller->speed;
-		faller->sector->floorheight -= faller->speed;
-	}
-	else
-	{
-		faller->sector->ceilingheight += faller->speed;
-		faller->sector->floorheight += faller->speed;
-	}
+	faller->sector->ceilingheight += faller->speed*faller->direction;
+	faller->sector->floorheight += faller->speed*faller->direction;
 
 	P_CheckSector(faller->sector, false);
 
-	if (faller->direction == -1) // Down
+	if ((faller->direction == -1 && faller->sector->ceilingheight <= faller->destheight)
+		|| (faller->direction == 1 && faller->sector->floorheight >= faller->destheight))
 	{
-		if (faller->sector->ceilingheight <= faller->ceilingdestheight)            // if destination height acheived
-		{
-			faller->sector->ceilingheight = faller->ceilingwasheight;
-			faller->sector->floorheight = faller->floorwasheight;
-		}
-	}
-	else // Up
-	{
-		if (faller->sector->floorheight >= faller->floordestheight)            // if destination height acheived
-		{
-			faller->sector->ceilingheight = faller->ceilingwasheight;
-			faller->sector->floorheight = faller->floorwasheight;
-		}
+		faller->sector->ceilingheight = faller->ceilingstartheight;
+		faller->sector->floorheight = faller->floorstartheight;
 	}
 
 	P_CheckSector(faller->sector, false); // you might think this is irrelevant. you would be wrong
@@ -605,12 +580,6 @@ void T_ContinuousFalling(levelspecthink_t *faller)
 	faller->sector->floorspeed = faller->speed*faller->direction;
 	faller->sector->ceilspeed = 42;
 	faller->sector->moved = true;
-#undef speed
-#undef direction
-#undef floorwasheight
-#undef ceilingwasheight
-#undef floordestheight
-#undef ceilingdestheight
 }
 
 //
@@ -2398,18 +2367,12 @@ INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
 }
 
 // For T_ContinuousFalling special
-INT32 EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boolean backwards)
+void EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boolean backwards)
 {
-#define speed vars[0]
-#define direction vars[1]
-#define floorwasheight vars[2]
-#define ceilingwasheight vars[3]
-#define floordestheight vars[4]
-#define ceilingdestheight vars[5]
-	levelspecthink_t *faller;
+	continuousfall_t *faller;
 
 	// workaround for when there is no back sector
-	if (backsector == NULL)
+	if (!backsector)
 		backsector = sec;
 
 	// create and initialize new thinker
@@ -2421,29 +2384,11 @@ INT32 EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, bool
 	faller->sector = sec;
 	faller->speed = spd;
 
-	faller->floorwasheight = sec->floorheight;
-	faller->ceilingwasheight = sec->ceilingheight;
+	faller->floorstartheight = sec->floorheight;
+	faller->ceilingstartheight = sec->ceilingheight;
 
-	if (backwards)
-	{
-		faller->ceilingdestheight = backsector->ceilingheight;
-		faller->floordestheight = faller->ceilingdestheight;
-		faller->direction = 1; // Up!
-	}
-	else
-	{
-		faller->floordestheight = backsector->floorheight;
-		faller->ceilingdestheight = faller->floordestheight;
-		faller->direction = -1;
-	}
-
-	return 1;
-#undef speed
-#undef direction
-#undef floorwasheight
-#undef ceilingwasheight
-#undef floordestheight
-#undef ceilingdestheight
+	faller->destheight = backwards ? backsector->ceilingheight : backsector->floorheight;
+	faller->direction = backwards ? 1 : -1;
 }
 
 // Some other 3dfloor special things Tails 03-11-2002 (Search p_mobj.c for description)
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 443480813..025784d00 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1658,6 +1658,23 @@ static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveSector(ht->sector));
 }
 
+//
+// SaveContinuousFallThinker
+//
+// Saves a continuousfall_t thinker
+//
+static void SaveContinuousFallThinker(const thinker_t *th, const UINT8 type)
+{
+	const continuousfall_t *ht  = (const void *)th;
+	WRITEUINT8(save_p, type);
+	WRITEUINT32(save_p, SaveSector(ht->sector));
+	WRITEFIXED(save_p, ht->speed);
+	WRITEINT32(save_p, ht->direction);
+	WRITEFIXED(save_p, ht->floorstartheight);
+	WRITEFIXED(save_p, ht->ceilingstartheight);
+	WRITEFIXED(save_p, ht->destheight);
+}
+
 //
 // SaveFloatThinker
 //
@@ -2266,7 +2283,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling)
 			{
-				SaveSpecialLevelThinker(th, tc_continuousfalling);
+				SaveContinuousFallThinker(th, tc_continuousfalling);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_ThwompSector)
@@ -2814,6 +2831,23 @@ static thinker_t* LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeili
 	return &ht->thinker;
 }
 
+// LoadContinuousFallThinker
+//
+// Loads a continuousfall_t from a save game
+//
+static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker)
+{
+	continuousfall_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ht->thinker.function.acp1 = thinker;
+	ht->sector = LoadSector(READUINT32(save_p));
+	ht->speed = READFIXED(save_p);
+	ht->direction = READINT32(save_p);
+	ht->floorstartheight = READFIXED(save_p);
+	ht->ceilingstartheight = READFIXED(save_p);
+	ht->destheight = READFIXED(save_p);
+	return &ht->thinker;
+}
+
 // LoadFloatThinker
 //
 // Loads a floatthink_t from a save game
@@ -3528,7 +3562,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_continuousfalling:
-					th = LoadSpecialLevelThinker((actionf_p1)T_ContinuousFalling, 3);
+					th = LoadContinuousFallThinker((actionf_p1)T_ContinuousFalling);
 					break;
 
 				case tc_thwomp:
diff --git a/src/p_spec.h b/src/p_spec.h
index 279d59d7d..db755b5c9 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -320,6 +320,17 @@ typedef struct
 	sector_t *sector;   // Sector the thinker is from
 } levelspecthink_t;
 
+typedef struct
+{
+	thinker_t thinker;
+	sector_t *sector;
+	fixed_t speed;
+	INT32 direction;
+	fixed_t floorstartheight;
+	fixed_t ceilingstartheight;
+	fixed_t destheight;
+} continuousfall_t;
+
 typedef struct
 {
 	thinker_t thinker;
@@ -378,14 +389,14 @@ INT32 EV_BounceSector(sector_t *sector, fixed_t momz, line_t *sourceline);
 INT32 EV_StartCrumble(sector_t *sector, ffloor_t *rover,
 	boolean floating, player_t *player, fixed_t origalpha, boolean crumblereturn);
 
-INT32 EV_DoContinuousFall(sector_t *sec, sector_t *pbacksector, fixed_t spd, boolean backwards);
+void EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boolean backwards);
 
 INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher);
 
 void T_MoveFloor(floormove_t *movefloor);
 
 void T_MoveElevator(elevator_t *elevator);
-void T_ContinuousFalling(levelspecthink_t *faller);
+void T_ContinuousFalling(continuousfall_t *faller);
 void T_BounceCheese(levelspecthink_t *bouncer);
 void T_StartCrumble(elevator_t *elevator);
 void T_MarioBlock(levelspecthink_t *block);

From 003860597908c93ac7f905dc21d6db45862f4876 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 18 Apr 2020 02:05:23 +0200
Subject: [PATCH 180/251] Make T_MarioBlock use its own thinker data structure

---
 src/p_floor.c | 55 +++++++++++++++++----------------------------------
 src/p_saveg.c | 38 +++++++++++++++++++++++++++++++++--
 src/p_spec.h  | 15 ++++++++++++--
 3 files changed, 67 insertions(+), 41 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 4c6c7fa46..bef57014c 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -941,17 +941,10 @@ void T_StartCrumble(elevator_t *elevator)
 //////////////////////////////////////////////////
 // Mario hits a block!
 //
-void T_MarioBlock(levelspecthink_t *block)
+void T_MarioBlock(mariothink_t *block)
 {
 	INT32 i;
 
-#define speed vars[1]
-#define direction vars[2]
-#define floorwasheight vars[3]
-#define ceilingwasheight vars[4]
-#define distance vars[5]
-#define low vars[6]
-
 	T_MovePlane
 	(
 	  block->sector,
@@ -972,12 +965,12 @@ void T_MarioBlock(levelspecthink_t *block)
 	  block->direction
 	);
 
-	if (block->sector->ceilingheight >= block->ceilingwasheight + 32*FRACUNIT) // Go back down now..
-		block->direction = -block->direction;
-	else if (block->sector->ceilingheight <= block->ceilingwasheight)
+	if (block->sector->ceilingheight >= block->ceilingstartheight + 32*FRACUNIT) // Go back down now..
+		block->direction *= -1;
+	else if (block->sector->ceilingheight <= block->ceilingstartheight)
 	{
-		block->sector->ceilingheight = block->ceilingwasheight;
-		block->sector->floorheight = block->floorwasheight;
+		block->sector->ceilingheight = block->ceilingstartheight;
+		block->sector->floorheight = block->floorstartheight;
 		P_RemoveThinker(&block->thinker);
 		block->sector->floordata = NULL;
 		block->sector->ceilingdata = NULL;
@@ -986,15 +979,8 @@ void T_MarioBlock(levelspecthink_t *block)
 		block->direction = 0;
 	}
 
-	for (i = -1; (i = P_FindSectorFromTag((INT16)block->vars[0], i)) >= 0 ;)
+	for (i = -1; (i = P_FindSectorFromTag(block->tag, i)) >= 0 ;)
 		P_RecalcPrecipInSector(&sectors[i]);
-
-#undef speed
-#undef direction
-#undef floorwasheight
-#undef ceilingwasheight
-#undef distance
-#undef low
 }
 
 void T_FloatSector(floatthink_t *floater)
@@ -2460,11 +2446,11 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
 	return 1;
 }
 
-INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
+void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
 {
 	sector_t *roversec = rover->master->frontsector;
 	fixed_t topheight = *rover->topheight;
-	levelspecthink_t *block;
+	mariothink_t *block;
 	mobj_t *thing;
 	fixed_t oldx = 0, oldy = 0, oldz = 0;
 
@@ -2472,7 +2458,7 @@ INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
 	I_Assert(puncher->player != NULL);
 
 	if (roversec->floordata || roversec->ceilingdata)
-		return 0;
+		return;
 
 	if (!(rover->flags & FF_SOLID))
 		rover->flags |= (FF_SOLID|FF_RENDERALL|FF_CUTLEVEL);
@@ -2480,8 +2466,9 @@ INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
 	// Find an item to pop out!
 	thing = SearchMarioNode(roversec->touching_thinglist);
 
-	// Found something!
-	if (thing)
+	if (!thing)
+		S_StartSound(puncher, sfx_mario1); // "Thunk!" sound - puncher is "close enough".
+	else // Found something!
 	{
 		const boolean itsamonitor = (thing->flags & MF_MONITOR) == MF_MONITOR;
 		// create and initialize new elevator thinker
@@ -2494,13 +2481,11 @@ INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
 
 		// Set up the fields
 		block->sector = roversec;
-		block->vars[0] = sector->tag; // actionsector
-		block->vars[1] = 4*FRACUNIT; // speed
-		block->vars[2] = 1; // Up // direction
-		block->vars[3] = block->sector->floorheight; // floorwasheight
-		block->vars[4] = block->sector->ceilingheight; // ceilingwasheight
-		block->vars[5] = FRACUNIT; // distance
-		block->vars[6] = 1; // low
+		block->speed = 4*FRACUNIT;
+		block->direction = 1;
+		block->floorstartheight = block->sector->floorheight;
+		block->ceilingstartheight = block->sector->ceilingheight;
+		block->tag = (INT16)sector->tag;
 
 		if (itsamonitor)
 		{
@@ -2541,8 +2526,4 @@ INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
 			P_SetThingPosition(thing);
 		}
 	}
-	else
-		S_StartSound(puncher, sfx_mario1); // "Thunk!" sound - puncher is "close enough".
-
-	return 1;
 }
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 025784d00..e9d2e0836 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1675,6 +1675,23 @@ static void SaveContinuousFallThinker(const thinker_t *th, const UINT8 type)
 	WRITEFIXED(save_p, ht->destheight);
 }
 
+//
+// SaveMarioBlockThinker
+//
+// Saves a mariothink_t thinker
+//
+static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type)
+{
+	const mariothink_t *ht  = (const void *)th;
+	WRITEUINT8(save_p, type);
+	WRITEUINT32(save_p, SaveSector(ht->sector));
+	WRITEFIXED(save_p, ht->speed);
+	WRITEINT32(save_p, ht->direction);
+	WRITEFIXED(save_p, ht->floorstartheight);
+	WRITEFIXED(save_p, ht->ceilingstartheight);
+	WRITEINT16(save_p, ht->tag);
+}
+
 //
 // SaveFloatThinker
 //
@@ -2338,7 +2355,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_MarioBlock)
 			{
-				SaveSpecialLevelThinker(th, tc_marioblock);
+				SaveMarioBlockThinker(th, tc_marioblock);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker)
@@ -2848,6 +2865,23 @@ static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
+// LoadMarioBlockThinker
+//
+// Loads a mariothink_t from a save game
+//
+static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker)
+{
+	mariothink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ht->thinker.function.acp1 = thinker;
+	ht->sector = LoadSector(READUINT32(save_p));
+	ht->speed = READFIXED(save_p);
+	ht->direction = READINT32(save_p);
+	ht->floorstartheight = READFIXED(save_p);
+	ht->ceilingstartheight = READFIXED(save_p);
+	ht->tag = READINT16(save_p);
+	return &ht->thinker;
+}
+
 // LoadFloatThinker
 //
 // Loads a floatthink_t from a save game
@@ -3596,7 +3630,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_marioblock:
-					th = LoadSpecialLevelThinker((actionf_p1)T_MarioBlock, 3);
+					th = LoadMarioBlockThinker((actionf_p1)T_MarioBlock);
 					break;
 
 				case tc_marioblockchecker:
diff --git a/src/p_spec.h b/src/p_spec.h
index db755b5c9..946b01bcf 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -331,6 +331,17 @@ typedef struct
 	fixed_t destheight;
 } continuousfall_t;
 
+typedef struct
+{
+	thinker_t thinker;
+	sector_t *sector;
+	fixed_t speed;
+	INT32 direction;
+	fixed_t floorstartheight;
+	fixed_t ceilingstartheight;
+	INT16 tag;
+} mariothink_t;
+
 typedef struct
 {
 	thinker_t thinker;
@@ -391,7 +402,7 @@ INT32 EV_StartCrumble(sector_t *sector, ffloor_t *rover,
 
 void EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boolean backwards);
 
-INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher);
+void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher);
 
 void T_MoveFloor(floormove_t *movefloor);
 
@@ -399,7 +410,7 @@ void T_MoveElevator(elevator_t *elevator);
 void T_ContinuousFalling(continuousfall_t *faller);
 void T_BounceCheese(levelspecthink_t *bouncer);
 void T_StartCrumble(elevator_t *elevator);
-void T_MarioBlock(levelspecthink_t *block);
+void T_MarioBlock(mariothink_t *block);
 void T_FloatSector(floatthink_t *floater);
 void T_MarioBlockChecker(levelspecthink_t *block);
 void T_ThwompSector(levelspecthink_t *thwomp);

From 29d33f0a931fd3e0908ecdc5291c0538a4c6af8b Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 18 Apr 2020 09:21:04 +0200
Subject: [PATCH 181/251] Refactor T_NoEnemiesSector

---
 src/p_floor.c | 61 +++++++++++++++++++++------------------------------
 src/p_saveg.c | 28 +++++++++++++++++++++--
 src/p_spec.c  |  9 +++-----
 src/p_spec.h  |  8 ++++++-
 4 files changed, 61 insertions(+), 45 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index bef57014c..e46b0b4fb 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1281,21 +1281,37 @@ void T_ThwompSector(levelspecthink_t *thwomp)
 #undef ceilingwasheight
 }
 
+static boolean T_SectorHasEnemies(sector_t *sec)
+{
+	msecnode_t *node = sec->touching_thinglist; // things touching this sector
+	mobj_t *mo;
+	while (node)
+	{
+		mo = node->m_thing;
+
+		if ((mo->flags & (MF_ENEMY|MF_BOSS))
+			&& mo->health > 0
+			&& mo->z < sec->ceilingheight
+			&& mo->z + mo->height > sec->floorheight)
+			return true;
+
+		node = node->m_thinglist_next;
+	}
+
+	return false;
+}
+
 //
 // T_NoEnemiesThinker
 //
 // Runs a linedef exec when no more MF_ENEMY/MF_BOSS objects with health are in the area
 // \sa P_AddNoEnemiesThinker
 //
-void T_NoEnemiesSector(levelspecthink_t *nobaddies)
+void T_NoEnemiesSector(noenemies_t *nobaddies)
 {
 	size_t i;
-	fixed_t upperbound, lowerbound;
 	sector_t *sec = NULL;
-	sector_t *targetsec = NULL;
 	INT32 secnum = -1;
-	msecnode_t *node;
-	mobj_t *thing;
 	boolean FOFsector = false;
 
 	while ((secnum = P_FindSectorFromLineTag(nobaddies->sourceline, secnum)) >= 0)
@@ -1316,40 +1332,13 @@ void T_NoEnemiesSector(levelspecthink_t *nobaddies)
 
 			while ((targetsecnum = P_FindSectorFromLineTag(sec->lines[i], targetsecnum)) >= 0)
 			{
-				targetsec = &sectors[targetsecnum];
-
-				upperbound = targetsec->ceilingheight;
-				lowerbound = targetsec->floorheight;
-				node = targetsec->touching_thinglist; // things touching this sector
-				while (node)
-				{
-					thing = node->m_thing;
-
-					if ((thing->flags & (MF_ENEMY|MF_BOSS)) && thing->health > 0
-					&& thing->z < upperbound && thing->z+thing->height > lowerbound)
-						return;
-
-					node = node->m_thinglist_next;
-				}
-			}
-		}
-
-		if (!FOFsector)
-		{
-			upperbound = sec->ceilingheight;
-			lowerbound = sec->floorheight;
-			node = sec->touching_thinglist; // things touching this sector
-			while (node)
-			{
-				thing = node->m_thing;
-
-				if ((thing->flags & (MF_ENEMY|MF_BOSS)) && thing->health > 0
-				&& thing->z < upperbound && thing->z+thing->height > lowerbound)
+				if (T_SectorHasEnemies(&sectors[targetsecnum]))
 					return;
-
-				node = node->m_thinglist_next;
 			}
 		}
+
+		if (!FOFsector && T_SectorHasEnemies(sec))
+			return;
 	}
 
 	CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", nobaddies->sourceline->tag);
diff --git a/src/p_saveg.c b/src/p_saveg.c
index e9d2e0836..afcd9867e 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1658,6 +1658,18 @@ static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveSector(ht->sector));
 }
 
+//
+// SaveNoEnemiesThinker
+//
+// Saves a noenemies_t thinker
+//
+static void SaveNoEnemiesThinker(const thinker_t *th, const UINT8 type)
+{
+	const noenemies_t *ht  = (const void *)th;
+	WRITEUINT8(save_p, type);
+	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+}
+
 //
 // SaveContinuousFallThinker
 //
@@ -2310,7 +2322,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector)
 			{
-				SaveSpecialLevelThinker(th, tc_noenemies);
+				SaveNoEnemiesThinker(th, tc_noenemies);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker)
@@ -2848,6 +2860,18 @@ static thinker_t* LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeili
 	return &ht->thinker;
 }
 
+// LoadNoEnemiesThinker
+//
+// Loads a noenemies_t from a save game
+//
+static thinker_t* LoadNoEnemiesThinker(actionf_p1 thinker)
+{
+	noenemies_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ht->thinker.function.acp1 = thinker;
+	ht->sourceline = LoadLine(READUINT32(save_p));
+	return &ht->thinker;
+}
+
 // LoadContinuousFallThinker
 //
 // Loads a continuousfall_t from a save game
@@ -3604,7 +3628,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_noenemies:
-					th = LoadSpecialLevelThinker((actionf_p1)T_NoEnemiesSector, 0);
+					th = LoadNoEnemiesThinker((actionf_p1)T_NoEnemiesSector);
 					break;
 
 				case tc_eachtime:
diff --git a/src/p_spec.c b/src/p_spec.c
index 54a6d88d6..6bcac18f9 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6107,14 +6107,13 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin
 /** Adds a thinker which checks if any MF_ENEMY objects with health are in the defined area.
   * If not, a linedef executor is run once.
   *
-  * \param sec          Control sector.
   * \param sourceline   Control linedef.
   * \sa P_SpawnSpecials, T_NoEnemiesSector
   * \author SSNTails <http://www.ssntails.org>
   */
-static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline)
+static inline void P_AddNoEnemiesThinker(line_t *sourceline)
 {
-	levelspecthink_t *nobaddies;
+	noenemies_t *nobaddies;
 
 	// create and initialize new thinker
 	nobaddies = Z_Calloc(sizeof (*nobaddies), PU_LEVSPEC, NULL);
@@ -6122,7 +6121,6 @@ static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline)
 
 	nobaddies->thinker.function.acp1 = (actionf_p1)T_NoEnemiesSector;
 
-	nobaddies->sector = sec;
 	nobaddies->sourceline = sourceline;
 }
 
@@ -7124,8 +7122,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			// No More Enemies Linedef Exec
 			case 313:
-				sec = sides[*lines[i].sidenum].sector - sectors;
-				P_AddNoEnemiesThinker(&sectors[sec], &lines[i]);
+				P_AddNoEnemiesThinker(&lines[i]);
 				break;
 
 			// Pushable linedef executors (count # of pushables)
diff --git a/src/p_spec.h b/src/p_spec.h
index 946b01bcf..ef98be5c4 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -320,6 +320,12 @@ typedef struct
 	sector_t *sector;   // Sector the thinker is from
 } levelspecthink_t;
 
+typedef struct
+{
+	thinker_t thinker;
+	line_t *sourceline; // Source line of the thinker
+} noenemies_t;
+
 typedef struct
 {
 	thinker_t thinker;
@@ -414,7 +420,7 @@ void T_MarioBlock(mariothink_t *block);
 void T_FloatSector(floatthink_t *floater);
 void T_MarioBlockChecker(levelspecthink_t *block);
 void T_ThwompSector(levelspecthink_t *thwomp);
-void T_NoEnemiesSector(levelspecthink_t *nobaddies);
+void T_NoEnemiesSector(noenemies_t *nobaddies);
 void T_EachTimeThinker(eachtime_t *eachtime);
 void T_CameraScanner(elevator_t *elevator);
 void T_RaiseSector(raise_t *raise);

From 08f1e03e791c35dc70345130c61f6b532570abe3 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 18 Apr 2020 10:26:03 +0200
Subject: [PATCH 182/251] Refactor T_ThwompSector

---
 src/p_floor.c | 273 ++++++++++++++++++++++----------------------------
 src/p_saveg.c |  46 ++++++++-
 src/p_spec.c  |  35 +++----
 src/p_spec.h  |  17 +++-
 4 files changed, 196 insertions(+), 175 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index e46b0b4fb..774606563 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1104,164 +1104,74 @@ void T_MarioBlockChecker(levelspecthink_t *block)
 	}
 }
 
+static boolean P_IsPlayerValid(size_t playernum)
+{
+	if (!playeringame[playernum])
+		return false;
+
+	if (!players[playernum].mo)
+		return false;
+
+	if (players[playernum].mo->health <= 0)
+		return false;
+
+	if (players[playernum].spectator)
+		return false;
+
+	return true;
+}
+
 // This is the Thwomp's 'brain'. It looks around for players nearby, and if
 // it finds any, **SMASH**!!! Muahahhaa....
-void T_ThwompSector(levelspecthink_t *thwomp)
+void T_ThwompSector(thwomp_t *thwomp)
 {
-#define speed vars[1]
-#define direction vars[2]
-#define distance vars[3]
-#define floorwasheight vars[4]
-#define ceilingwasheight vars[5]
 	fixed_t thwompx, thwompy;
 	sector_t *actionsector;
 	ffloor_t *rover = NULL;
 	INT32 secnum;
+	fixed_t speed;
 
 	// If you just crashed down, wait a second before coming back up.
-	if (--thwomp->distance > 0)
-	{
-		sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture;
+	if (--thwomp->delay > 0)
 		return;
-	}
 
 	// Just find the first sector with the tag.
 	// Doesn't work with multiple sectors that have different floor/ceiling heights.
-	secnum = P_FindSectorFromTag((INT16)thwomp->vars[0], -1);
+	secnum = P_FindSectorFromTag(thwomp->tag, -1);
 
-	if (secnum > 0)
-	{
-		actionsector = &sectors[secnum];
-
-		// Look for thwomp FFloor
-		for (rover = actionsector->ffloors; rover; rover = rover->next)
-		{
-			if (rover->master == thwomp->sourceline)
-				break;
-		}
-	}
-	else
+	if (secnum <= 0)
 		return; // Bad bad bad!
 
+	actionsector = &sectors[secnum];
+
+	// Look for thwomp FOF
+	for (rover = actionsector->ffloors; rover; rover = rover->next)
+	{
+		if (rover->master == thwomp->sourceline)
+			break;
+	}
+
+	if (!rover)
+		return; // Didn't find any FOFs, so bail out
+
 	thwompx = actionsector->soundorg.x;
 	thwompy = actionsector->soundorg.y;
 
-	if (thwomp->direction > 0) // Moving back up..
+	if (thwomp->direction == 0) // Not going anywhere, so look for players.
 	{
-		result_e res = 0;
-
-		// Set the texture from the lower one (normal)
-		sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture;
-		/// \note this should only have to be done once, but is already done repeatedly, above
-
-		if (thwomp->sourceline->flags & ML_EFFECT5)
-			thwomp->speed = thwomp->sourceline->dx/8;
-		else
-			thwomp->speed = 2*FRACUNIT;
-
-		res = T_MovePlane
-		(
-			thwomp->sector,         // sector
-			thwomp->speed,          // speed
-			thwomp->floorwasheight, // dest
-			false,                      // crush
-			false,                  // ceiling?
-			thwomp->direction       // direction
-		);
-
-		if (res == ok || res == pastdest)
-			T_MovePlane
-			(
-				thwomp->sector,           // sector
-				thwomp->speed,            // speed
-				thwomp->ceilingwasheight, // dest
-				false,                        // crush
-				true,                     // ceiling?
-				thwomp->direction         // direction
-			);
-
-		if (res == pastdest)
-			thwomp->direction = 0; // stop moving
-
-		thwomp->sector->ceilspeed = 42;
-		thwomp->sector->floorspeed = thwomp->speed*thwomp->direction;
-	}
-	else if (thwomp->direction < 0) // Crashing down!
-	{
-		result_e res = 0;
-
-		// Set the texture from the upper one (angry)
-		sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].toptexture;
-
-		if (thwomp->sourceline->flags & ML_EFFECT5)
-			thwomp->speed = thwomp->sourceline->dy/8;
-		else
-			thwomp->speed = 10*FRACUNIT;
-
-		res = T_MovePlane
-		(
-			thwomp->sector,   // sector
-			thwomp->speed,    // speed
-			P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight,
-				thwomp->sector->ceilingheight - thwomp->sector->floorheight), // dest
-			false,              // crush
-			false,              // ceiling?
-			thwomp->direction // direction
-		);
-
-		if (res == ok || res == pastdest)
-			T_MovePlane
-			(
-				thwomp->sector,   // sector
-				thwomp->speed,    // speed
-				P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight,
-					thwomp->sector->ceilingheight
-					- (thwomp->sector->floorheight + thwomp->speed))
-					+ (thwomp->sector->ceilingheight
-					- (thwomp->sector->floorheight + thwomp->speed/2)), // dest
-				false,             // crush
-				true,              // ceiling?
-				thwomp->direction // direction
-			);
-
-		if (res == pastdest)
-		{
-			mobj_t *mp = (void *)&actionsector->soundorg;
-
-			if (!rover || (rover->flags & FF_EXISTS))
-			{
-				if (thwomp->sourceline->flags & ML_EFFECT4)
-					S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS);
-				else
-					S_StartSound(mp, sfx_thwomp);
-			}
-
-			thwomp->direction = 1; // start heading back up
-			thwomp->distance = TICRATE; // but only after a small delay
-		}
-
-		thwomp->sector->ceilspeed = 42;
-		thwomp->sector->floorspeed = thwomp->speed*thwomp->direction;
-	}
-	else // Not going anywhere, so look for players.
-	{
-		if (!rover || (rover->flags & FF_EXISTS))
+		if (rover->flags & FF_EXISTS)
 		{
 			UINT8 i;
 			// scan the players to find victims!
 			for (i = 0; i < MAXPLAYERS; i++)
 			{
-				if (!playeringame[i])
-					continue;
-				if (players[i].spectator)
-					continue;
-				if (!players[i].mo)
-					continue;
-				if (!players[i].mo->health)
+				if (!P_IsPlayerValid(i))
 					continue;
+
 				if (players[i].mo->z > thwomp->sector->ceilingheight)
 					continue;
-				if (P_AproxDistance(thwompx - players[i].mo->x, thwompy - players[i].mo->y) > 96 * FRACUNIT)
+
+				if (P_AproxDistance(thwompx - players[i].mo->x, thwompy - players[i].mo->y) > 96*FRACUNIT)
 					continue;
 
 				thwomp->direction = -1;
@@ -1272,13 +1182,89 @@ void T_ThwompSector(levelspecthink_t *thwomp)
 		thwomp->sector->ceilspeed = 0;
 		thwomp->sector->floorspeed = 0;
 	}
+	else
+	{
+		result_e res = 0;
+
+		if (thwomp->direction > 0) //Moving back up..
+		{
+			// Set the texture from the lower one (normal)
+			sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture;
+
+			speed = thwomp->retractspeed;
+
+			res = T_MovePlane
+			(
+				thwomp->sector,           // sector
+				speed,                    // speed
+				thwomp->floorstartheight, // dest
+				false,                    // crush
+				false,                    // ceiling?
+				thwomp->direction         // direction
+			);
+
+			if (res == ok || res == pastdest)
+				T_MovePlane
+				(
+					thwomp->sector,             // sector
+					speed,                      // speed
+					thwomp->ceilingstartheight, // dest
+					false,                      // crush
+					true,                       // ceiling?
+					thwomp->direction           // direction
+				);
+
+			if (res == pastdest)
+				thwomp->direction = 0; // stop moving
+			}
+		else // Crashing down!
+		{
+			// Set the texture from the upper one (angry)
+			sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].toptexture;
+
+			speed = thwomp->crushspeed;
+
+			res = T_MovePlane
+			(
+				thwomp->sector,   // sector
+				speed,            // speed
+				P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight,
+					thwomp->sector->ceilingheight - thwomp->sector->floorheight), // dest
+				false,              // crush
+				false,              // ceiling?
+				thwomp->direction // direction
+			);
+
+			if (res == ok || res == pastdest)
+				T_MovePlane
+				(
+					thwomp->sector,   // sector
+					speed,            // speed
+					P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight,
+						thwomp->sector->ceilingheight
+						- (thwomp->sector->floorheight + speed))
+						+ (thwomp->sector->ceilingheight
+						- (thwomp->sector->floorheight + speed/2)), // dest
+					false,             // crush
+					true,              // ceiling?
+					thwomp->direction // direction
+				);
+
+			if (res == pastdest)
+			{
+				if (rover->flags & FF_EXISTS)
+					S_StartSound((void *)&actionsector->soundorg, thwomp->sound);
+
+				thwomp->direction = 1; // start heading back up
+				thwomp->delay = TICRATE; // but only after a small delay
+			}
+		}
+
+		thwomp->sector->ceilspeed = 42;
+		thwomp->sector->floorspeed = speed*thwomp->direction;
+	}
 
 	P_RecalcPrecipInSector(actionsector);
-#undef speed
-#undef direction
-#undef distance
-#undef floorwasheight
-#undef ceilingwasheight
 }
 
 static boolean T_SectorHasEnemies(sector_t *sec)
@@ -1375,23 +1361,6 @@ static boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec)
 	return false;
 }
 
-static boolean P_IsPlayerValid(size_t playernum)
-{
-	if (!playeringame[playernum])
-		return false;
-
-	if (!players[playernum].mo)
-		return false;
-
-	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;
diff --git a/src/p_saveg.c b/src/p_saveg.c
index afcd9867e..888eb96ca 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1704,6 +1704,27 @@ static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT16(save_p, ht->tag);
 }
 
+//
+// SaveThwompThinker
+//
+// Saves a thwomp_t thinker
+//
+static void SaveThwompThinker(const thinker_t *th, const UINT8 type)
+{
+	const thwomp_t *ht  = (const void *)th;
+	WRITEUINT8(save_p, type);
+	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+	WRITEUINT32(save_p, SaveSector(ht->sector));
+	WRITEFIXED(save_p, ht->crushspeed);
+	WRITEFIXED(save_p, ht->retractspeed);
+	WRITEINT32(save_p, ht->direction);
+	WRITEFIXED(save_p, ht->floorstartheight);
+	WRITEFIXED(save_p, ht->ceilingstartheight);
+	WRITEINT32(save_p, ht->delay);
+	WRITEINT16(save_p, ht->tag);
+	WRITEUINT16(save_p, ht->sound);
+}
+
 //
 // SaveFloatThinker
 //
@@ -2317,7 +2338,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_ThwompSector)
 			{
-				SaveSpecialLevelThinker(th, tc_thwomp);
+				SaveThwompThinker(th, tc_thwomp);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector)
@@ -2906,6 +2927,27 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
+// LoadThwompThinker
+//
+// Loads a thwomp_t from a save game
+//
+static thinker_t* LoadThwompThinker(actionf_p1 thinker)
+{
+	thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ht->thinker.function.acp1 = thinker;
+	ht->sourceline = LoadLine(READUINT32(save_p));
+	ht->sector = LoadSector(READUINT32(save_p));
+	ht->crushspeed = READFIXED(save_p);
+	ht->retractspeed = READFIXED(save_p);
+	ht->direction = READINT32(save_p);
+	ht->floorstartheight = READFIXED(save_p);
+	ht->ceilingstartheight = READFIXED(save_p);
+	ht->delay = READINT32(save_p);
+	ht->tag = READINT16(save_p);
+	ht->sound = READUINT16(save_p);
+	return &ht->thinker;
+}
+
 // LoadFloatThinker
 //
 // Loads a floatthink_t from a save game
@@ -3624,7 +3666,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_thwomp:
-					th = LoadSpecialLevelThinker((actionf_p1)T_ThwompSector, 3);
+					th = LoadThwompThinker((actionf_p1)T_ThwompSector);
 					break;
 
 				case tc_noenemies:
diff --git a/src/p_spec.c b/src/p_spec.c
index 6bcac18f9..921bcef26 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6068,12 +6068,7 @@ static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean
   */
 static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, line_t *sourceline)
 {
-#define speed vars[1]
-#define direction vars[2]
-#define distance vars[3]
-#define floorwasheight vars[4]
-#define ceilingwasheight vars[5]
-	levelspecthink_t *thwomp;
+	thwomp_t *thwomp;
 
 	// You *probably* already have a thwomp in this sector. If you've combined it with something
 	// else that uses the floordata/ceilingdata, you must be weird.
@@ -6087,21 +6082,21 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin
 	thwomp->thinker.function.acp1 = (actionf_p1)T_ThwompSector;
 
 	// set up the fields according to the type of elevator action
-	thwomp->sector = sec;
-	thwomp->vars[0] = actionsector->tag;
-	thwomp->floorwasheight = thwomp->sector->floorheight;
-	thwomp->ceilingwasheight = thwomp->sector->ceilingheight;
-	thwomp->direction = 0;
-	thwomp->distance = 1;
 	thwomp->sourceline = sourceline;
-	thwomp->sector->floordata = thwomp;
-	thwomp->sector->ceilingdata = thwomp;
-	return;
-#undef speed
-#undef direction
-#undef distance
-#undef floorwasheight
-#undef ceilingwasheight
+	thwomp->sector = sec;
+	thwomp->crushspeed = (sourceline->flags & ML_EFFECT5) ? sourceline->dy >> 3 : 10*FRACUNIT;
+	thwomp->retractspeed = (sourceline->flags & ML_EFFECT5) ? sourceline->dx >> 3 : 2*FRACUNIT;
+	thwomp->direction = 0;
+	thwomp->floorstartheight = sec->floorheight;
+	thwomp->ceilingstartheight = sec->ceilingheight;
+	thwomp->delay = 1;
+	thwomp->tag = actionsector->tag;
+	thwomp->sound = (sourceline->flags & ML_EFFECT4) ? sides[sourceline->sidenum[0]].textureoffset >> FRACBITS : sfx_thwomp;
+
+	sec->floordata = thwomp;
+	sec->ceilingdata = thwomp;
+	// Start with 'resting' texture
+	sides[sourceline->sidenum[0]].midtexture = sides[sourceline->sidenum[0]].bottomtexture;
 }
 
 /** Adds a thinker which checks if any MF_ENEMY objects with health are in the defined area.
diff --git a/src/p_spec.h b/src/p_spec.h
index ef98be5c4..5e54b568f 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -348,6 +348,21 @@ typedef struct
 	INT16 tag;
 } mariothink_t;
 
+typedef struct
+{
+	thinker_t thinker;
+	line_t *sourceline;
+	sector_t *sector;
+	fixed_t crushspeed;
+	fixed_t retractspeed;
+	INT32 direction;
+	fixed_t floorstartheight;
+	fixed_t ceilingstartheight;
+	INT32 delay;
+	INT16 tag;
+	UINT16 sound;
+} thwomp_t;
+
 typedef struct
 {
 	thinker_t thinker;
@@ -419,7 +434,7 @@ void T_StartCrumble(elevator_t *elevator);
 void T_MarioBlock(mariothink_t *block);
 void T_FloatSector(floatthink_t *floater);
 void T_MarioBlockChecker(levelspecthink_t *block);
-void T_ThwompSector(levelspecthink_t *thwomp);
+void T_ThwompSector(thwomp_t *thwomp);
 void T_NoEnemiesSector(noenemies_t *nobaddies);
 void T_EachTimeThinker(eachtime_t *eachtime);
 void T_CameraScanner(elevator_t *elevator);

From ab172673631e96a96c2f31ef32d4e54c160d1e35 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 18 Apr 2020 10:45:21 +0200
Subject: [PATCH 183/251] Make T_BounceCheese use its own thinker struct

---
 src/p_floor.c | 28 ++++++----------------------
 src/p_saveg.c | 40 ++++++++++++++++++++++++++++++++++++++--
 src/p_spec.h  | 14 +++++++++++++-
 3 files changed, 57 insertions(+), 25 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 774606563..6e0599f70 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -625,13 +625,8 @@ static fixed_t P_SectorCheckWater(sector_t *analyzesector,
 //////////////////////////////////////////////////
 // Bounces a floating cheese
 
-void T_BounceCheese(levelspecthink_t *bouncer)
+void T_BounceCheese(bouncecheese_t *bouncer)
 {
-#define speed vars[0]
-#define distance vars[1]
-#define low vars[2]
-#define ceilingwasheight vars[3]
-#define floorwasheight vars[4]
 	fixed_t sectorheight;
 	fixed_t halfheight;
 	fixed_t waterheight;
@@ -709,7 +704,7 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 		bouncer->sector->floorspeed = -bouncer->speed/2;
 		bouncer->sector->ceilspeed = 42;
 
-		if ((bouncer->sector->ceilingheight < bouncer->ceilingwasheight && bouncer->low == 0) // Down
+		if ((bouncer->sector->ceilingheight < bouncer->ceilingwasheight && !bouncer->low) // Down
 			|| (bouncer->sector->ceilingheight > bouncer->ceilingwasheight && bouncer->low)) // Up
 		{
 			if (abs(bouncer->speed) < 6*FRACUNIT)
@@ -717,7 +712,7 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 			else
 				bouncer->speed -= bouncer->speed/2;
 
-			bouncer->low = bouncer->low ? 0 : 1;
+			bouncer->low = !bouncer->low;
 			if (abs(bouncer->speed) > 6*FRACUNIT)
 			{
 				mobj_t *mp = (void *)&actionsector->soundorg;
@@ -756,11 +751,6 @@ void T_BounceCheese(levelspecthink_t *bouncer)
 		if (actionsector)
 			P_RecalcPrecipInSector(actionsector);
 	}
-#undef speed
-#undef distance
-#undef low
-#undef ceilingwasheight
-#undef floorwasheight
 }
 
 //////////////////////////////////////////////////
@@ -2283,10 +2273,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
 // Used for bobbing platforms on the water
 INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
 {
-#define speed vars[0]
-#define distance vars[1]
-#define low vars[2]
-	levelspecthink_t *bouncer;
+	bouncecheese_t *bouncer;
 
 	// create and initialize new thinker
 	if (sec->ceilingdata) // One at a time, ma'am.
@@ -2298,16 +2285,13 @@ INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
 	bouncer->thinker.function.acp1 = (actionf_p1)T_BounceCheese;
 
 	// set up the fields according to the type of elevator action
+	bouncer->sourceline = sourceline;
 	bouncer->sector = sec;
 	bouncer->speed = momz/2;
-	bouncer->sourceline = sourceline;
 	bouncer->distance = FRACUNIT;
-	bouncer->low = 1;
+	bouncer->low = true;
 
 	return 1;
-#undef speed
-#undef distance
-#undef low
 }
 
 // For T_ContinuousFalling special
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 888eb96ca..48e910dcd 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1670,6 +1670,24 @@ static void SaveNoEnemiesThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveLine(ht->sourceline));
 }
 
+//
+// SaveBounceCheeseThinker
+//
+// Saves a bouncecheese_t thinker
+//
+static void SaveBounceCheeseThinker(const thinker_t *th, const UINT8 type)
+{
+	const bouncecheese_t *ht  = (const void *)th;
+	WRITEUINT8(save_p, type);
+	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+	WRITEUINT32(save_p, SaveSector(ht->sector));
+	WRITEFIXED(save_p, ht->speed);
+	WRITEFIXED(save_p, ht->distance);
+	WRITEFIXED(save_p, ht->floorwasheight);
+	WRITEFIXED(save_p, ht->ceilingwasheight);
+	WRITECHAR(save_p, ht->low);
+}
+
 //
 // SaveContinuousFallThinker
 //
@@ -2378,7 +2396,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_BounceCheese)
 			{
-				SaveSpecialLevelThinker(th, tc_bouncecheese);
+				SaveBounceCheeseThinker(th, tc_bouncecheese);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_StartCrumble)
@@ -2893,6 +2911,24 @@ static thinker_t* LoadNoEnemiesThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
+// LoadBounceCheeseThinker
+//
+// Loads a bouncecheese_t from a save game
+//
+static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker)
+{
+	bouncecheese_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ht->thinker.function.acp1 = thinker;
+	ht->sourceline = LoadLine(READUINT32(save_p));
+	ht->sector = LoadSector(READUINT32(save_p));
+	ht->speed = READFIXED(save_p);
+	ht->distance = READFIXED(save_p);
+	ht->floorwasheight = READFIXED(save_p);
+	ht->ceilingwasheight = READFIXED(save_p);
+	ht->low = READCHAR(save_p);
+	return &ht->thinker;
+}
+
 // LoadContinuousFallThinker
 //
 // Loads a continuousfall_t from a save game
@@ -3688,7 +3724,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_bouncecheese:
-					th = LoadSpecialLevelThinker((actionf_p1)T_BounceCheese, 2);
+					th = LoadBounceCheeseThinker((actionf_p1)T_BounceCheese);
 					break;
 
 				case tc_startcrumble:
diff --git a/src/p_spec.h b/src/p_spec.h
index 5e54b568f..8897304af 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -337,6 +337,18 @@ typedef struct
 	fixed_t destheight;
 } continuousfall_t;
 
+typedef struct
+{
+	thinker_t thinker;
+	line_t *sourceline;
+	sector_t *sector;
+	fixed_t speed;
+	fixed_t distance;
+	fixed_t floorwasheight;
+	fixed_t ceilingwasheight;
+	boolean low;
+} bouncecheese_t;
+
 typedef struct
 {
 	thinker_t thinker;
@@ -429,7 +441,7 @@ void T_MoveFloor(floormove_t *movefloor);
 
 void T_MoveElevator(elevator_t *elevator);
 void T_ContinuousFalling(continuousfall_t *faller);
-void T_BounceCheese(levelspecthink_t *bouncer);
+void T_BounceCheese(bouncecheese_t *bouncer);
 void T_StartCrumble(elevator_t *elevator);
 void T_MarioBlock(mariothink_t *block);
 void T_FloatSector(floatthink_t *floater);

From da594db3fcded48f85ed613a04ea415dc1c64d47 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 18 Apr 2020 10:52:58 +0200
Subject: [PATCH 184/251] Remove return values from a few elevator functions
 that don't use them

---
 src/p_floor.c | 18 +++++-------------
 src/p_spec.h  |  6 +++---
 2 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 6e0599f70..eeb2a6b84 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1800,9 +1800,9 @@ void T_PlaneDisplace(planedisplace_t *pd)
 // (egg capsule button), P_PlayerInSpecialSector (buttons),
 // and P_SpawnSpecials (continuous floor movers and instant lower).
 //
-INT32 EV_DoFloor(line_t *line, floor_e floortype)
+void EV_DoFloor(line_t *line, floor_e floortype)
 {
-	INT32 rtn = 0, firstone = 1;
+	INT32 firstone = 1;
 	INT32 secnum = -1;
 	sector_t *sec;
 	floormove_t *dofloor;
@@ -1815,7 +1815,6 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype)
 			continue; // then don't add another one
 
 		// new floor thinker
-		rtn = 1;
 		dofloor = Z_Calloc(sizeof (*dofloor), PU_LEVSPEC, NULL);
 		P_AddThinker(THINK_MAIN, &dofloor->thinker);
 
@@ -2005,8 +2004,6 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype)
 
 		firstone = 0;
 	}
-
-	return rtn;
 }
 
 // SoM: Boom elevator support.
@@ -2019,10 +2016,9 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype)
 //
 // jff 2/22/98 new type to move floor and ceiling in parallel
 //
-INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
+void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
 {
 	INT32 secnum = -1;
-	INT32 rtn = 0;
 	sector_t *sec;
 	elevator_t *elevator;
 
@@ -2036,7 +2032,6 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
 			continue;
 
 		// create and initialize new elevator thinker
-		rtn = 1;
 		elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
 		P_AddThinker(THINK_MAIN, &elevator->thinker);
 		sec->floordata = elevator;
@@ -2138,7 +2133,6 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
 				break;
 		}
 	}
-	return rtn;
 }
 
 void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
@@ -2271,13 +2265,13 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
 }
 
 // Used for bobbing platforms on the water
-INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
+void EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
 {
 	bouncecheese_t *bouncer;
 
 	// create and initialize new thinker
 	if (sec->ceilingdata) // One at a time, ma'am.
-		return 0;
+		return;
 
 	bouncer = Z_Calloc(sizeof (*bouncer), PU_LEVSPEC, NULL);
 	P_AddThinker(THINK_MAIN, &bouncer->thinker);
@@ -2290,8 +2284,6 @@ INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
 	bouncer->speed = momz/2;
 	bouncer->distance = FRACUNIT;
 	bouncer->low = true;
-
-	return 1;
 }
 
 // For T_ContinuousFalling special
diff --git a/src/p_spec.h b/src/p_spec.h
index 8897304af..2d535fd25 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -424,10 +424,10 @@ typedef enum
 
 result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crush,
 	boolean ceiling, INT32 direction);
-INT32 EV_DoFloor(line_t *line, floor_e floortype);
-INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed);
+void EV_DoFloor(line_t *line, floor_e floortype);
+void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed);
 void EV_CrumbleChain(sector_t *sec, ffloor_t *rover);
-INT32 EV_BounceSector(sector_t *sector, fixed_t momz, line_t *sourceline);
+void EV_BounceSector(sector_t *sector, fixed_t momz, line_t *sourceline);
 
 // Some other special 3dfloor types
 INT32 EV_StartCrumble(sector_t *sector, ffloor_t *rover,

From 54cbd66999f370cb296280b6dae27c46fdf3f5bd Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 18 Apr 2020 11:05:58 +0200
Subject: [PATCH 185/251] Eradicate levelspecthink_t

---
 src/p_floor.c |  8 +----
 src/p_saveg.c | 84 +++++++++++++++++----------------------------------
 src/p_spec.c  |  2 +-
 src/p_spec.h  | 18 +++++------
 4 files changed, 38 insertions(+), 74 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index eeb2a6b84..179cf73c7 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1071,26 +1071,20 @@ static mobj_t *SearchMarioNode(msecnode_t *node)
 	return thing;
 }
 
-void T_MarioBlockChecker(levelspecthink_t *block)
+void T_MarioBlockChecker(mariocheck_t *block)
 {
 	line_t *masterline = block->sourceline;
-	if (block->vars[2] == 1) // Don't update the textures when the block's being bumped upwards.
-		return;
 	if (SearchMarioNode(block->sector->touching_thinglist))
 	{
 		sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].bottomtexture; // Update textures
 		if (masterline->backsector)
-		{
 			block->sector->ceilingpic = block->sector->floorpic = masterline->backsector->ceilingpic; // Update flats to be backside's ceiling
-		}
 	}
 	else
 	{
 		sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].toptexture;
 		if (masterline->backsector)
-		{
 			block->sector->ceilingpic = block->sector->floorpic = masterline->backsector->floorpic; // Update flats to be backside's floor
-		}
 	}
 }
 
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 48e910dcd..0fef92d01 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1639,25 +1639,6 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, mobj->mobjnum);
 }
 
-//
-// SaveSpecialLevelThinker
-//
-// Saves a levelspecthink_t thinker
-//
-static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type)
-{
-	const levelspecthink_t *ht  = (const void *)th;
-	size_t i;
-	WRITEUINT8(save_p, type);
-	for (i = 0; i < 16; i++)
-	{
-		WRITEFIXED(save_p, ht->vars[i]); //var[16]
-		WRITEFIXED(save_p, ht->var2s[i]); //var[16]
-	}
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
-	WRITEUINT32(save_p, SaveSector(ht->sector));
-}
-
 //
 // SaveNoEnemiesThinker
 //
@@ -1722,6 +1703,19 @@ static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT16(save_p, ht->tag);
 }
 
+//
+// SaveMarioCheckThinker
+//
+// Saves a mariocheck_t thinker
+//
+static void SaveMarioCheckThinker(const thinker_t *th, const UINT8 type)
+{
+	const mariocheck_t *ht  = (const void *)th;
+	WRITEUINT8(save_p, type);
+	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+	WRITEUINT32(save_p, SaveSector(ht->sector));
+}
+
 //
 // SaveThwompThinker
 //
@@ -2411,7 +2405,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker)
 			{
-				SaveSpecialLevelThinker(th, tc_marioblockchecker);
+				SaveMarioCheckThinker(th, tc_marioblockchecker);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_FloatSector)
@@ -2864,41 +2858,6 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 	return &mobj->thinker;
 }
 
-//
-// LoadSpecialLevelThinker
-//
-// Loads a levelspecthink_t from a save game
-//
-// floorOrCeiling:
-//		0 - Don't set
-//		1 - Floor Only
-//		2 - Ceiling Only
-//		3 - Both
-//
-static thinker_t* LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeiling)
-{
-	levelspecthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
-	size_t i;
-	ht->thinker.function.acp1 = thinker;
-	for (i = 0; i < 16; i++)
-	{
-		ht->vars[i] = READFIXED(save_p); //var[16]
-		ht->var2s[i] = READFIXED(save_p); //var[16]
-	}
-	ht->sourceline = LoadLine(READUINT32(save_p));
-	ht->sector = LoadSector(READUINT32(save_p));
-
-	if (ht->sector)
-	{
-		if (floorOrCeiling & 2)
-			ht->sector->ceilingdata = ht;
-		if (floorOrCeiling & 1)
-			ht->sector->floordata = ht;
-	}
-
-	return &ht->thinker;
-}
-
 // LoadNoEnemiesThinker
 //
 // Loads a noenemies_t from a save game
@@ -2963,6 +2922,19 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
+// LoadMarioCheckThinker
+//
+// Loads a mariocheck_t from a save game
+//
+static thinker_t* LoadMarioCheckThinker(actionf_p1 thinker)
+{
+	mariocheck_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ht->thinker.function.acp1 = thinker;
+	ht->sourceline = LoadLine(READUINT32(save_p));
+	ht->sector = LoadSector(READUINT32(save_p));
+	return &ht->thinker;
+}
+
 // LoadThwompThinker
 //
 // Loads a thwomp_t from a save game
@@ -3736,7 +3708,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_marioblockchecker:
-					th = LoadSpecialLevelThinker((actionf_p1)T_MarioBlockChecker, 0);
+					th = LoadMarioCheckThinker((actionf_p1)T_MarioBlockChecker);
 					break;
 
 				case tc_floatsector:
diff --git a/src/p_spec.c b/src/p_spec.c
index 921bcef26..728bacab1 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -5983,7 +5983,7 @@ static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control,
   */
 static void P_AddBlockThinker(sector_t *sec, line_t *sourceline)
 {
-	levelspecthink_t *block;
+	mariocheck_t *block;
 
 	// create and initialize new elevator thinker
 	block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL);
diff --git a/src/p_spec.h b/src/p_spec.h
index 2d535fd25..e243e3a61 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -311,15 +311,6 @@ typedef struct
 	line_t *sourceline;
 } elevator_t;
 
-typedef struct
-{
-	thinker_t thinker;
-	fixed_t vars[16];   // Misc. variables
-	fixed_t var2s[16];   // Second misc variables buffer.
-	line_t *sourceline; // Source line of the thinker
-	sector_t *sector;   // Sector the thinker is from
-} levelspecthink_t;
-
 typedef struct
 {
 	thinker_t thinker;
@@ -360,6 +351,13 @@ typedef struct
 	INT16 tag;
 } mariothink_t;
 
+typedef struct
+{
+	thinker_t thinker;
+	line_t *sourceline;
+	sector_t *sector;
+} mariocheck_t;
+
 typedef struct
 {
 	thinker_t thinker;
@@ -445,7 +443,7 @@ void T_BounceCheese(bouncecheese_t *bouncer);
 void T_StartCrumble(elevator_t *elevator);
 void T_MarioBlock(mariothink_t *block);
 void T_FloatSector(floatthink_t *floater);
-void T_MarioBlockChecker(levelspecthink_t *block);
+void T_MarioBlockChecker(mariocheck_t *block);
 void T_ThwompSector(thwomp_t *thwomp);
 void T_NoEnemiesSector(noenemies_t *nobaddies);
 void T_EachTimeThinker(eachtime_t *eachtime);

From c031008eab4d44bf2c9113630c331b53e740b798 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 18 Apr 2020 15:17:25 +0200
Subject: [PATCH 186/251] Enable SF_TRIGGERSPECIAL_TOUCH for sectors with spike
 damage

---
 src/p_spec.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/p_spec.c b/src/p_spec.c
index 728bacab1..32e4f111c 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6363,6 +6363,12 @@ void P_SpawnSpecials(boolean fromnetsave)
 		// Process Section 1
 		switch(GETSECSPECIAL(sector->special, 1))
 		{
+			case 5: // Spikes
+				//Terrible hack to replace an even worse hack:
+				//Spike damage automatically sets SF_TRIGGERSPECIAL_TOUCH.
+				//Yes, this also affects other specials on the same sector. Sorry.
+				sector->flags |= SF_TRIGGERSPECIAL_TOUCH;
+				break;
 			case 15: // Bouncy sector
 				CheckForBouncySector = true;
 				break;

From f6e2c7063f77c399313b31e92a4278d2ba314cc4 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Mon, 20 Apr 2020 23:40:41 +0200
Subject: [PATCH 187/251] Rename lumpinfo_t.name2 to lumpinfo_t.fullname

---
 src/lua_script.c |  4 ++--
 src/p_setup.c    |  4 ++--
 src/w_wad.c      | 47 ++++++++++++++++++++++++-----------------------
 src/w_wad.h      |  2 +-
 4 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/src/lua_script.c b/src/lua_script.c
index 1bc89180e..7adf62fcc 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -441,9 +441,9 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump)
 	else // If it's not a .lua file, copy the lump name in too.
 	{
 		lumpinfo_t *lump_p = &wadfiles[wad]->lumpinfo[lump];
-		len += 1 + strlen(lump_p->name2); // length of file name, '|', and lump name
+		len += 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name
 		name = malloc(len+1);
-		sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->name2);
+		sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->fullname);
 		name[len] = '\0';
 	}
 
diff --git a/src/p_setup.c b/src/p_setup.c
index 700113d85..6396dbd90 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -3777,12 +3777,12 @@ static lumpinfo_t* FindFolder(const char *folName, UINT16 *start, UINT16 *end, l
 {
 	UINT16 numlumps = *pnumlumps;
 	size_t i = *pi;
-	if (!stricmp(lumpinfo->name2, folName))
+	if (!stricmp(lumpinfo->fullname, folName))
 	{
 		lumpinfo++;
 		*start = ++i;
 		for (; i < numlumps; i++, lumpinfo++)
-			if (strnicmp(lumpinfo->name2, folName, strlen(folName)))
+			if (strnicmp(lumpinfo->fullname, folName, strlen(folName)))
 				break;
 		lumpinfo--;
 		*end = i-- - *start;
diff --git a/src/w_wad.c b/src/w_wad.c
index 1008aca8f..45b1de086 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -117,7 +117,7 @@ void W_Shutdown(void)
 		fclose(wadfiles[numwadfiles]->handle);
 		Z_Free(wadfiles[numwadfiles]->filename);
 		while (wadfiles[numwadfiles]->numlumps--)
-			Z_Free(wadfiles[numwadfiles]->lumpinfo[wadfiles[numwadfiles]->numlumps].name2);
+			Z_Free(wadfiles[numwadfiles]->lumpinfo[wadfiles[numwadfiles]->numlumps].fullname);
 
 		Z_Free(wadfiles[numwadfiles]->lumpinfo);
 		Z_Free(wadfiles[numwadfiles]);
@@ -206,9 +206,9 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum, boolean mainfile)
 		for(; posStart < posEnd; posStart++)
 		{
 			lumpinfo_t *lump_p = &wadfiles[wadnum]->lumpinfo[posStart];
-			size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name
+			size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name
 			char *name = malloc(length + 1);
-			sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->name2);
+			sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname);
 			name[length] = '\0';
 			CONS_Printf(M_GetText("Loading SOC from %s\n"), name);
 			DEH_LoadDehackedLumpPwad(wadnum, posStart, mainfile);
@@ -235,9 +235,9 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum, boolean mainfile)
 		for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++)
 			if (memcmp(lump_p->name,"SOC_",4)==0) // Check for generic SOC lump
 			{	// shameless copy+paste of code from LUA_LoadLump
-				size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name
+				size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name
 				char *name = malloc(length + 1);
-				sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->name2);
+				sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname);
 				name[length] = '\0';
 
 				CONS_Printf(M_GetText("Loading SOC from %s\n"), name);
@@ -340,9 +340,10 @@ static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const
 	fseek(handle, 0, SEEK_SET);
 	strcpy(lumpinfo->name, lumpname);
 	// Allocate the lump's full name.
-	lumpinfo->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
-	strcpy(lumpinfo->name2, lumpname);
-	lumpinfo->name2[8] = '\0';
+	lumpinfo->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
+	strcpy(lumpinfo->fullname, lumpname);
+	lumpinfo->fullname[8] = '\0';
+
 	*numlumps = 1;
 	return lumpinfo;
 }
@@ -430,9 +431,9 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
 		memset(lump_p->name, 0x00, 9);
 		strncpy(lump_p->name, fileinfo->name, 8);
 		// Allocate the lump's full name.
-		lump_p->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
-		strncpy(lump_p->name2, fileinfo->name, 8);
-		lump_p->name2[8] = '\0';
+		lump_p->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
+		strncpy(lump_p->fullname, fileinfo->name, 8);
+		lump_p->fullname[8] = '\0';
 	}
 	free(fileinfov);
 	*nlmp = numlumps;
@@ -598,8 +599,8 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 		memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
 		strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
 
-		lump_p->name2 = Z_Calloc(zentry.namelen + 1, PU_STATIC, NULL);
-		strncpy(lump_p->name2, fullname, zentry.namelen);
+		lump_p->fullname = Z_Calloc(zentry.namelen + 1, PU_STATIC, NULL);
+		strncpy(lump_p->fullname, fullname, zentry.namelen);
 
 		free(fullname);
 
@@ -637,7 +638,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 		// skip and ignore comments/extra fields
 		if ((fseek(handle, lump_p->position, SEEK_SET) != 0) || (fread(&zlentry, 1, sizeof(zlentry_t), handle) < sizeof(zlentry_t)))
 		{
-			CONS_Alert(CONS_ERROR, "Local headers for lump %s are corrupt\n", lump_p->name2);
+			CONS_Alert(CONS_ERROR, "Local headers for lump %s are corrupt\n", lump_p->fullname);
 			Z_Free(lumpinfo);
 			return NULL;
 		}
@@ -947,10 +948,10 @@ UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlum
 	name_length = strlen(name);
 	for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
 	{
-		if (strnicmp(name, lump_p->name2, name_length) == 0)
+		if (strnicmp(name, lump_p->fullname, name_length) == 0)
 		{
 			/* SLADE is special and puts a single directory entry. Skip that. */
-			if (strlen(lump_p->name2) == name_length)
+			if (strlen(lump_p->fullname) == name_length)
 				i++;
 			break;
 		}
@@ -967,7 +968,7 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
 	lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
 	for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
 	{
-		if (strnicmp(name, lump_p->name2, strlen(name)))
+		if (strnicmp(name, lump_p->fullname, strlen(name)))
 			break;
 	}
 	return i;
@@ -981,7 +982,7 @@ UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump)
 	lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
 	for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
 	{
-		if (!strnicmp(name, lump_p->name2, strlen(name)))
+		if (!strnicmp(name, lump_p->fullname, strlen(name)))
 		{
 			return i;
 		}
@@ -1151,7 +1152,7 @@ boolean W_IsLumpWad(lumpnum_t lumpnum)
 {
 	if (wadfiles[WADFILENUM(lumpnum)]->type == RET_PK3)
 	{
-		const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->name2;
+		const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->fullname;
 
 		if (strlen(lumpfullName) < 4)
 			return false; // can't possibly be a WAD can it?
@@ -1169,7 +1170,7 @@ boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
 {
 	if (wadfiles[wad]->type == RET_PK3)
 	{
-		const char *name = wadfiles[wad]->lumpinfo[lump].name2;
+		const char *name = wadfiles[wad]->lumpinfo[lump].fullname;
 
 		return (name[strlen(name)-1] == '/'); // folders end in '/'
 	}
@@ -1247,7 +1248,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
 		{
 			size_t bytesread = fread(dest, 1, size, handle);
 			if (R_IsLumpPNG((UINT8 *)dest, bytesread))
-				W_ThrowPNGError(l->name2, wadfiles[wad]->filename);
+				W_ThrowPNGError(l->fullname, wadfiles[wad]->filename);
 			return bytesread;
 		}
 #else
@@ -1289,7 +1290,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
 			Z_Free(decData);
 #ifdef NO_PNG_LUMPS
 			if (R_IsLumpPNG((UINT8 *)dest, size))
-				W_ThrowPNGError(l->name2, wadfiles[wad]->filename);
+				W_ThrowPNGError(l->fullname, wadfiles[wad]->filename);
 #endif
 			return size;
 #else
@@ -1352,7 +1353,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
 
 #ifdef NO_PNG_LUMPS
 			if (R_IsLumpPNG((UINT8 *)dest, size))
-				W_ThrowPNGError(l->name2, wadfiles[wad]->filename);
+				W_ThrowPNGError(l->fullname, wadfiles[wad]->filename);
 #endif
 			return size;
 		}
diff --git a/src/w_wad.h b/src/w_wad.h
index d4455ba14..3cf9585a4 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -67,7 +67,7 @@ typedef struct
 	unsigned long position; // filelump_t filepos
 	unsigned long disksize; // filelump_t size
 	char name[9]; // filelump_t name[]
-	char *name2; // Used by PK3s. Dynamically allocated name.
+	char *fullname; // Used by PK3s. Dynamically allocated name.
 	size_t size; // real (uncompressed) size
 	compmethod compression; // lump compression method
 } lumpinfo_t;

From 29a94ee26aae3c45bd35463428bdcef9020b6734 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Tue, 21 Apr 2020 10:21:41 +0200
Subject: [PATCH 188/251] Add a longname field to lumpinfo_t

---
 src/w_wad.c | 32 ++++++++++++++++++++++++++------
 src/w_wad.h |  7 ++++---
 2 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/src/w_wad.c b/src/w_wad.c
index 45b1de086..22856d155 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -114,13 +114,18 @@ void W_Shutdown(void)
 {
 	while (numwadfiles--)
 	{
-		fclose(wadfiles[numwadfiles]->handle);
-		Z_Free(wadfiles[numwadfiles]->filename);
-		while (wadfiles[numwadfiles]->numlumps--)
-			Z_Free(wadfiles[numwadfiles]->lumpinfo[wadfiles[numwadfiles]->numlumps].fullname);
+		wadfile_t *wad = wadfiles[numwadfiles];
 
-		Z_Free(wadfiles[numwadfiles]->lumpinfo);
-		Z_Free(wadfiles[numwadfiles]);
+		fclose(wad->handle);
+		Z_Free(wad->filename);
+		while (wad->numlumps--)
+		{
+			Z_Free(wad->lumpinfo[wad->numlumps].longname);
+			Z_Free(wad->lumpinfo[wad->numlumps].fullname);
+		}
+
+		Z_Free(wad->lumpinfo);
+		Z_Free(wad);
 	}
 }
 
@@ -339,6 +344,12 @@ static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const
 	lumpinfo->size = ftell(handle);
 	fseek(handle, 0, SEEK_SET);
 	strcpy(lumpinfo->name, lumpname);
+
+	// Allocate the lump's long name.
+	lumpinfo->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
+	strcpy(lumpinfo->longname, lumpname);
+	lumpinfo->longname[8] = '\0';
+
 	// Allocate the lump's full name.
 	lumpinfo->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
 	strcpy(lumpinfo->fullname, lumpname);
@@ -430,6 +441,12 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
 			lump_p->compression = CM_NOCOMPRESSION;
 		memset(lump_p->name, 0x00, 9);
 		strncpy(lump_p->name, fileinfo->name, 8);
+
+		// Allocate the lump's long name.
+		lump_p->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
+		strncpy(lump_p->longname, fileinfo->name, 8);
+		lump_p->longname[8] = '\0';
+
 		// Allocate the lump's full name.
 		lump_p->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
 		strncpy(lump_p->fullname, fileinfo->name, 8);
@@ -599,6 +616,9 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
 		memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
 		strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
 
+		lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL);
+		strlcpy(lump_p->longname, trimname, dotpos - trimname + 1);
+
 		lump_p->fullname = Z_Calloc(zentry.namelen + 1, PU_STATIC, NULL);
 		strncpy(lump_p->fullname, fullname, zentry.namelen);
 
diff --git a/src/w_wad.h b/src/w_wad.h
index 3cf9585a4..3af6148f4 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -66,9 +66,10 @@ typedef struct
 {
 	unsigned long position; // filelump_t filepos
 	unsigned long disksize; // filelump_t size
-	char name[9]; // filelump_t name[]
-	char *fullname; // Used by PK3s. Dynamically allocated name.
-	size_t size; // real (uncompressed) size
+	char name[9];           // filelump_t name[] e.g. "LongEntr"
+	char *longname;         //                   e.g. "LongEntryName"
+	char *fullname;         //                   e.g. "Folder/Subfolder/LongEntryName.extension"
+	size_t size;            // real (uncompressed) size
 	compmethod compression; // lump compression method
 } lumpinfo_t;
 

From 0ddd2fea217949948d1b3bcf4525bd6bdf3827b2 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Tue, 21 Apr 2020 11:08:18 +0200
Subject: [PATCH 189/251] Let W_CheckNumForName(Pwad) find entries with long
 names

---
 src/w_wad.c | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/src/w_wad.c b/src/w_wad.c
index 22856d155..f273753c8 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -92,7 +92,7 @@ typedef struct
 
 typedef struct lumpnum_cache_s
 {
-	char lumpname[8];
+	char lumpname[32];
 	lumpnum_t lumpnum;
 } lumpnum_cache_t;
 
@@ -922,16 +922,14 @@ const char *W_CheckNameForNum(lumpnum_t lumpnum)
 UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
 {
 	UINT16 i;
-	static char uname[9];
-
-	memset(uname, 0x00, sizeof uname);
-	strncpy(uname, name, 8);
-	uname[8] = 0;
-	strupr(uname);
+	static char uname[256 + 1];
 
 	if (!TestValidLump(wad,0))
 		return INT16_MAX;
 
+	strlcpy(uname, name, sizeof uname);
+	strupr(uname);
+
 	//
 	// scan forward
 	// start at 'startlump', useful parameter when there are multiple
@@ -941,7 +939,7 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
 	{
 		lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
 		for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
-			if (memcmp(lump_p->name,uname,8) == 0)
+			if (!strcmp(lump_p->longname, uname))
 				return i;
 	}
 
@@ -1027,7 +1025,7 @@ lumpnum_t W_CheckNumForName(const char *name)
 	// most recent entries first
 	for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--)
 	{
-		if (strncmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name, 8) == 0)
+		if (strcmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0)
 		{
 			lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1);
 			return lumpnumcache[lumpnumcacheindex].lumpnum;
@@ -1047,7 +1045,7 @@ lumpnum_t W_CheckNumForName(const char *name)
 	{
 		// Update the cache.
 		lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1);
-		strncpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 8);
+		strlcpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 32);
 		lumpnumcache[lumpnumcacheindex].lumpnum = (i<<16)+check;
 
 		return lumpnumcache[lumpnumcacheindex].lumpnum;

From 25affe6948acc3274c04a9f4a3e3df666d8a6fd5 Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Wed, 22 Apr 2020 18:58:40 +0200
Subject: [PATCH 190/251] Make emerald hunt shards spawn at correct heights,
 and add Float option.

---
 extras/conf/SRB2-22.cfg |  2 ++
 src/p_mobj.c            |  5 +++--
 src/p_mobj.h            |  3 +++
 src/p_setup.c           | 28 +++++++++++++++++++---------
 4 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg
index 585fa7857..ea783908a 100644
--- a/extras/conf/SRB2-22.cfg
+++ b/extras/conf/SRB2-22.cfg
@@ -3900,6 +3900,8 @@ thingtypes
 		{
 			title = "Emerald Hunt Location";
 			sprite = "SHRDA0";
+			flags8height = 24;
+			flags8text = "[8] Float";
 		}
 		321
 		{
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 7e65c37ad..10f051891 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -11616,7 +11616,7 @@ void P_MovePlayerToStarpost(INT32 playernum)
 mapthing_t *huntemeralds[MAXHUNTEMERALDS];
 INT32 numhuntemeralds;
 
-static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t offset, const boolean flip)
+fixed_t P_GetMobjSpawnHeight(mobjtype_t mobjtype, fixed_t x, fixed_t y, fixed_t offset, boolean flip)
 {
 	const subsector_t *ss = R_PointInSubsector(x, y);
 
@@ -11633,7 +11633,7 @@ static fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x,
 			+ offset;
 }
 
-static fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y)
+fixed_t P_GetMapThingSpawnHeight(mobjtype_t mobjtype, mapthing_t* mthing, fixed_t x, fixed_t y)
 {
 	fixed_t offset = mthing->z << FRACBITS;
 	boolean flip = (!!(mobjinfo[mobjtype].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP));
@@ -11673,6 +11673,7 @@ static fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthin
 
 	// Ring-like items, may float additional units with MTF_AMBUSH.
 	case MT_SPIKEBALL:
+	case MT_EMERHUNT:
 	case MT_EMERALDSPAWN:
 	case MT_TOKEN:
 	case MT_EMBLEM:
diff --git a/src/p_mobj.h b/src/p_mobj.h
index 5deb288e4..9e7e340a6 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -451,6 +451,9 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing);
 void P_MovePlayerToStarpost(INT32 playernum);
 void P_AfterPlayerSpawn(INT32 playernum);
 
+fixed_t P_GetMobjSpawnHeight(mobjtype_t mobjtype, fixed_t x, fixed_t y, fixed_t offset, boolean flip);
+fixed_t P_GetMapThingSpawnHeight(mobjtype_t mobjtype, mapthing_t* mthing, fixed_t x, fixed_t y);
+
 mobj_t *P_SpawnMapThing(mapthing_t *mthing);
 void P_SpawnHoop(mapthing_t *mthing);
 void P_SetBonusTime(mobj_t *mobj);
diff --git a/src/p_setup.c b/src/p_setup.c
index 700113d85..50df3c01a 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -695,6 +695,7 @@ static void P_SpawnEmeraldHunt(void)
 {
 	INT32 emer1, emer2, emer3;
 	INT32 timeout = 0; // keeps from getting stuck
+	fixed_t x, y, z;
 
 	emer1 = emer2 = emer3 = 0;
 
@@ -719,21 +720,30 @@ static void P_SpawnEmeraldHunt(void)
 
 	//decrement spawn values to the actual number because zero is valid.
 	if (emer1--)
-		P_SpawnMobj(huntemeralds[emer1]->x<<FRACBITS,
-			huntemeralds[emer1]->y<<FRACBITS,
-			huntemeralds[emer1]->z<<FRACBITS, MT_EMERHUNT);
+	{
+		x = huntemeralds[emer1]->x<<FRACBITS;
+		y = huntemeralds[emer1]->y<<FRACBITS;
+		z = P_GetMapThingSpawnHeight(MT_EMERHUNT, huntemeralds[emer1], x, y);
+		P_SpawnMobj(x, y, z, MT_EMERHUNT);
+	}
 
 	if (emer2--)
-		P_SetMobjStateNF(P_SpawnMobj(huntemeralds[emer2]->x<<FRACBITS,
-			huntemeralds[emer2]->y<<FRACBITS,
-			huntemeralds[emer2]->z<<FRACBITS, MT_EMERHUNT),
+	{
+		x = huntemeralds[emer2]->x<<FRACBITS;
+		y = huntemeralds[emer2]->y<<FRACBITS;
+		z = P_GetMapThingSpawnHeight(MT_EMERHUNT, huntemeralds[emer2], x, y);
+		P_SetMobjStateNF(P_SpawnMobj(x, y, z, MT_EMERHUNT),
 		mobjinfo[MT_EMERHUNT].spawnstate+1);
+	}
 
 	if (emer3--)
-		P_SetMobjStateNF(P_SpawnMobj(huntemeralds[emer3]->x<<FRACBITS,
-			huntemeralds[emer3]->y<<FRACBITS,
-			huntemeralds[emer3]->z<<FRACBITS, MT_EMERHUNT),
+	{
+		x = huntemeralds[emer3]->x<<FRACBITS;
+		y = huntemeralds[emer3]->y<<FRACBITS;
+		z = P_GetMapThingSpawnHeight(MT_EMERHUNT, huntemeralds[emer3], x, y);
+		P_SetMobjStateNF(P_SpawnMobj(x, y, z, MT_EMERHUNT),
 		mobjinfo[MT_EMERHUNT].spawnstate+2);
+	}
 }
 
 static void P_SpawnMapThings(boolean spawnemblems)

From b254cb186b5cae2f234e933af9eb28517ced04b0 Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Wed, 22 Apr 2020 20:38:58 +0200
Subject: [PATCH 191/251] Fix a mistake with P_SpawnEmeraldHunt and make it
 more concise.

---
 src/p_setup.c | 45 +++++++++++++--------------------------------
 1 file changed, 13 insertions(+), 32 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index 50df3c01a..9bc334ff0 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -691,58 +691,39 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum)
 }
 #endif
 
-static void P_SpawnEmeraldHunt(void)
+static void P_SpawnEmeraldHunt(int amount)
 {
-	INT32 emer1, emer2, emer3;
+	INT32 emer[amount];
 	INT32 timeout = 0; // keeps from getting stuck
 	fixed_t x, y, z;
 
-	emer1 = emer2 = emer3 = 0;
-
 	//increment spawn numbers because zero is valid.
-	emer1 = (P_RandomKey(numhuntemeralds)) + 1;
+	emer[0] = (P_RandomKey(numhuntemeralds)) + 1;
 	while (timeout++ < 100)
 	{
-		emer2 = (P_RandomKey(numhuntemeralds)) + 1;
+		emer[1] = (P_RandomKey(numhuntemeralds)) + 1;
 
-		if (emer2 != emer1)
+		if (emer[1] != emer[0])
 			break;
 	}
 
 	timeout = 0;
 	while (timeout++ < 100)
 	{
-		emer3 = (P_RandomKey(numhuntemeralds)) + 1;
+		emer[2] = (P_RandomKey(numhuntemeralds)) + 1;
 
-		if (emer3 != emer2 && emer3 != emer1)
+		if (emer[2] != emer[1] && emer[2] != emer[0])
 			break;
 	}
 
 	//decrement spawn values to the actual number because zero is valid.
-	if (emer1--)
+	for (int i = 0; i < amount; i++)
 	{
-		x = huntemeralds[emer1]->x<<FRACBITS;
-		y = huntemeralds[emer1]->y<<FRACBITS;
-		z = P_GetMapThingSpawnHeight(MT_EMERHUNT, huntemeralds[emer1], x, y);
-		P_SpawnMobj(x, y, z, MT_EMERHUNT);
-	}
-
-	if (emer2--)
-	{
-		x = huntemeralds[emer2]->x<<FRACBITS;
-		y = huntemeralds[emer2]->y<<FRACBITS;
-		z = P_GetMapThingSpawnHeight(MT_EMERHUNT, huntemeralds[emer2], x, y);
+		x = huntemeralds[emer[i]-1]->x<<FRACBITS;
+		y = huntemeralds[emer[i]-1]->y<<FRACBITS;
+		z = P_GetMapThingSpawnHeight(MT_EMERHUNT, huntemeralds[emer[i]-1], x, y);
 		P_SetMobjStateNF(P_SpawnMobj(x, y, z, MT_EMERHUNT),
-		mobjinfo[MT_EMERHUNT].spawnstate+1);
-	}
-
-	if (emer3--)
-	{
-		x = huntemeralds[emer3]->x<<FRACBITS;
-		y = huntemeralds[emer3]->y<<FRACBITS;
-		z = P_GetMapThingSpawnHeight(MT_EMERHUNT, huntemeralds[emer3], x, y);
-		P_SetMobjStateNF(P_SpawnMobj(x, y, z, MT_EMERHUNT),
-		mobjinfo[MT_EMERHUNT].spawnstate+2);
+		mobjinfo[MT_EMERHUNT].spawnstate+i);
 	}
 }
 
@@ -791,7 +772,7 @@ static void P_SpawnMapThings(boolean spawnemblems)
 
 	// random emeralds for hunt
 	if (numhuntemeralds)
-		P_SpawnEmeraldHunt();
+		P_SpawnEmeraldHunt(3);
 }
 
 // Experimental groovy write function!

From 01a12976314d38eee2e01132483687823e56a467 Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Wed, 22 Apr 2020 22:46:12 +0200
Subject: [PATCH 192/251] Make P_SpawnEmeraldHunt even more concise, using
 Fisher-Yates shuffle.

---
 src/p_setup.c | 45 +++++++++++++++++----------------------------
 1 file changed, 17 insertions(+), 28 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index 9bc334ff0..0e9c915fe 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -691,39 +691,28 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum)
 }
 #endif
 
-static void P_SpawnEmeraldHunt(int amount)
+static void P_SpawnEmeraldHunt(void)
 {
-	INT32 emer[amount];
-	INT32 timeout = 0; // keeps from getting stuck
+	INT32 emer[3], num[numhuntemeralds], randomkey;
 	fixed_t x, y, z;
 
-	//increment spawn numbers because zero is valid.
-	emer[0] = (P_RandomKey(numhuntemeralds)) + 1;
-	while (timeout++ < 100)
+	for (int i = 0; i < numhuntemeralds; i++)
+		num[i] = i;
+
+	for (int i = 0; i < 3; i++)
 	{
-		emer[1] = (P_RandomKey(numhuntemeralds)) + 1;
+		// generate random index, shuffle afterwards
+		randomkey = P_RandomKey(numhuntemeralds--);
+		emer[i] = num[randomkey];
+		num[randomkey] = num[numhuntemeralds];
+		num[numhuntemeralds] = emer[i];
 
-		if (emer[1] != emer[0])
-			break;
-	}
-
-	timeout = 0;
-	while (timeout++ < 100)
-	{
-		emer[2] = (P_RandomKey(numhuntemeralds)) + 1;
-
-		if (emer[2] != emer[1] && emer[2] != emer[0])
-			break;
-	}
-
-	//decrement spawn values to the actual number because zero is valid.
-	for (int i = 0; i < amount; i++)
-	{
-		x = huntemeralds[emer[i]-1]->x<<FRACBITS;
-		y = huntemeralds[emer[i]-1]->y<<FRACBITS;
-		z = P_GetMapThingSpawnHeight(MT_EMERHUNT, huntemeralds[emer[i]-1], x, y);
+		// spawn emerald
+		x = huntemeralds[emer[i]]->x<<FRACBITS;
+		y = huntemeralds[emer[i]]->y<<FRACBITS;
+		z = P_GetMapThingSpawnHeight(MT_EMERHUNT, huntemeralds[emer[i]], x, y);
 		P_SetMobjStateNF(P_SpawnMobj(x, y, z, MT_EMERHUNT),
-		mobjinfo[MT_EMERHUNT].spawnstate+i);
+			mobjinfo[MT_EMERHUNT].spawnstate+i);
 	}
 }
 
@@ -772,7 +761,7 @@ static void P_SpawnMapThings(boolean spawnemblems)
 
 	// random emeralds for hunt
 	if (numhuntemeralds)
-		P_SpawnEmeraldHunt(3);
+		P_SpawnEmeraldHunt();
 }
 
 // Experimental groovy write function!

From e26788d01444068366544bf51510b54bcd5d2649 Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Wed, 22 Apr 2020 23:10:43 +0200
Subject: [PATCH 193/251] Fix variable-length array definition, just in case.

---
 src/p_setup.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index 0e9c915fe..7ee26d68b 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -693,7 +693,7 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum)
 
 static void P_SpawnEmeraldHunt(void)
 {
-	INT32 emer[3], num[numhuntemeralds], randomkey;
+	INT32 emer[3], num[MAXHUNTEMERALDS], randomkey;
 	fixed_t x, y, z;
 
 	for (int i = 0; i < numhuntemeralds; i++)

From f85bfc87f5ffad7b65f21c28d41c10493d0c88e4 Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Wed, 22 Apr 2020 23:17:18 +0200
Subject: [PATCH 194/251] Move variable declarations outside of for loops.

---
 src/p_setup.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index 7ee26d68b..86a30e326 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -693,13 +693,13 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum)
 
 static void P_SpawnEmeraldHunt(void)
 {
-	INT32 emer[3], num[MAXHUNTEMERALDS], randomkey;
+	INT32 emer[3], num[MAXHUNTEMERALDS], i, randomkey;
 	fixed_t x, y, z;
 
-	for (int i = 0; i < numhuntemeralds; i++)
+	for (i = 0; i < numhuntemeralds; i++)
 		num[i] = i;
 
-	for (int i = 0; i < 3; i++)
+	for (i = 0; i < 3; i++)
 	{
 		// generate random index, shuffle afterwards
 		randomkey = P_RandomKey(numhuntemeralds--);

From 67f511a55e5db11147853ce4edd0f6d89efe66db Mon Sep 17 00:00:00 2001
From: sphere <spherallic@gmail.com>
Date: Wed, 22 Apr 2020 23:38:10 +0200
Subject: [PATCH 195/251] Restore carelessly removed const keywords.

---
 src/p_mobj.c | 4 ++--
 src/p_mobj.h | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/p_mobj.c b/src/p_mobj.c
index 10f051891..27cb0b456 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -11616,7 +11616,7 @@ void P_MovePlayerToStarpost(INT32 playernum)
 mapthing_t *huntemeralds[MAXHUNTEMERALDS];
 INT32 numhuntemeralds;
 
-fixed_t P_GetMobjSpawnHeight(mobjtype_t mobjtype, fixed_t x, fixed_t y, fixed_t offset, boolean flip)
+fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t offset, const boolean flip)
 {
 	const subsector_t *ss = R_PointInSubsector(x, y);
 
@@ -11633,7 +11633,7 @@ fixed_t P_GetMobjSpawnHeight(mobjtype_t mobjtype, fixed_t x, fixed_t y, fixed_t
 			+ offset;
 }
 
-fixed_t P_GetMapThingSpawnHeight(mobjtype_t mobjtype, mapthing_t* mthing, fixed_t x, fixed_t y)
+fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y)
 {
 	fixed_t offset = mthing->z << FRACBITS;
 	boolean flip = (!!(mobjinfo[mobjtype].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP));
diff --git a/src/p_mobj.h b/src/p_mobj.h
index 9e7e340a6..eda7383df 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -451,8 +451,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing);
 void P_MovePlayerToStarpost(INT32 playernum);
 void P_AfterPlayerSpawn(INT32 playernum);
 
-fixed_t P_GetMobjSpawnHeight(mobjtype_t mobjtype, fixed_t x, fixed_t y, fixed_t offset, boolean flip);
-fixed_t P_GetMapThingSpawnHeight(mobjtype_t mobjtype, mapthing_t* mthing, fixed_t x, fixed_t y);
+fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t offset, const boolean flip);
+fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y);
 
 mobj_t *P_SpawnMapThing(mapthing_t *mthing);
 void P_SpawnHoop(mapthing_t *mthing);

From 9ec4ba38246c2841661da7c191f5f40e81be78da Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Fri, 24 Apr 2020 14:05:15 +0200
Subject: [PATCH 196/251] Add a minimum delay between connections

---
 src/d_clisrv.c | 22 ++++++++++++++++++++++
 src/d_clisrv.h |  2 +-
 src/d_netcmd.c |  1 +
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 3603bb20d..f7755c148 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -85,6 +85,10 @@ tic_t jointimeout = (10*TICRATE);
 static boolean sendingsavegame[MAXNETNODES]; // Are we sending the savegame?
 static tic_t freezetimeout[MAXNETNODES]; // Until when can this node freeze the server before getting a timeout?
 
+// Incremented by cv_joindelay when a client joins, decremented each tic.
+// If higher than cv_joindelay * 2 (3 joins in a short timespan), joins are temporarily disabled.
+static tic_t joindelay = 0;
+
 UINT16 pingmeasurecount = 1;
 UINT32 realpingtable[MAXPLAYERS]; //the base table of ping where an average will be sent to everyone.
 UINT32 playerpingtable[MAXPLAYERS]; //table of player latency values.
@@ -3077,6 +3081,8 @@ consvar_t cv_allownewplayer = {"allowjoin", "On", CV_NETVAR, CV_OnOff, NULL, 0,
 consvar_t cv_joinnextround = {"joinnextround", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; /// \todo not done
 static CV_PossibleValue_t maxplayers_cons_t[] = {{2, "MIN"}, {32, "MAX"}, {0, NULL}};
 consvar_t cv_maxplayers = {"maxplayers", "8", CV_SAVE, maxplayers_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+static CV_PossibleValue_t joindelay_cons_t[] = {{1, "MIN"}, {3600, "MAX"}, {0, "Off"}, {0, NULL}};
+consvar_t cv_joindelay = {"joindelay", "10", CV_SAVE, joindelay_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 static CV_PossibleValue_t rejointimeout_cons_t[] = {{1, "MIN"}, {60 * FRACUNIT, "MAX"}, {0, "Off"}, {0, NULL}};
 consvar_t cv_rejointimeout = {"rejointimeout", "Off", CV_SAVE|CV_FLOAT, rejointimeout_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 
@@ -3164,6 +3170,8 @@ void SV_ResetServer(void)
 	neededtic = maketic;
 	tictoclear = maketic;
 
+	joindelay = 0;
+
 	for (i = 0; i < MAXNETNODES; i++)
 		ResetNode(i);
 
@@ -3613,6 +3621,9 @@ static void HandleConnect(SINT8 node)
 		SV_SendRefuse(node, M_GetText("No players from\nthis node."));
 	else if (luafiletransfers)
 		SV_SendRefuse(node, M_GetText("The server is broadcasting a file\nrequested by a Lua script.\nPlease wait a bit and then\ntry rejoining."));
+	else if (netgame && joindelay > 2 * (tic_t)cv_joindelay.value * TICRATE)
+		SV_SendRefuse(node, va(M_GetText("Too many people are connecting.\nPlease wait %d seconds and then\ntry rejoining."),
+			(joindelay - 2 * cv_joindelay.value * TICRATE) / TICRATE));
 	else
 	{
 #ifndef NONET
@@ -3670,6 +3681,7 @@ static void HandleConnect(SINT8 node)
 				DEBFILE("send savegame\n");
 			}
 			SV_AddWaitingPlayers(names[0], names[1]);
+			joindelay += cv_joindelay.value * TICRATE;
 			player_joining = true;
 		}
 #else
@@ -5038,12 +5050,21 @@ void NetUpdate(void)
 				hu_resynching = true;
 		}
 	}
+
 	Net_AckTicker();
+
 	// Handle timeouts to prevent definitive freezes from happenning
 	if (server)
+	{
 		for (i = 1; i < MAXNETNODES; i++)
 			if (nodeingame[i] && freezetimeout[i] < I_GetTime())
 				Net_ConnectionTimeout(i);
+
+		// In case the cvar value was lowered
+		if (joindelay)
+			joindelay = min(joindelay - 1, 3 * cv_joindelay.value * TICRATE);
+	}
+
 	nowtime /= NEWTICRATERATIO;
 	if (nowtime > resptime)
 	{
@@ -5051,6 +5072,7 @@ void NetUpdate(void)
 		M_Ticker();
 		CON_Ticker();
 	}
+
 	SV_FileSendTicker();
 }
 
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index 7e5061ff2..463240a2a 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -515,7 +515,7 @@ extern UINT32 realpingtable[MAXPLAYERS];
 extern UINT32 playerpingtable[MAXPLAYERS];
 extern tic_t servermaxping;
 
-extern consvar_t cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_rejointimeout;
+extern consvar_t cv_allownewplayer, cv_joinnextround, cv_maxplayers, cv_joindelay, cv_rejointimeout;
 extern consvar_t cv_resynchattempts, cv_blamecfail;
 extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
 
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 1fd53499a..dfc7351f5 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -573,6 +573,7 @@ void D_RegisterServerCommands(void)
 
 	// d_clisrv
 	CV_RegisterVar(&cv_maxplayers);
+	CV_RegisterVar(&cv_joindelay);
 	CV_RegisterVar(&cv_rejointimeout);
 	CV_RegisterVar(&cv_resynchattempts);
 	CV_RegisterVar(&cv_maxsend);

From c90cc3b58f4999eeefac820d25f5b9065fa28938 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Fri, 24 Apr 2020 15:38:07 +0200
Subject: [PATCH 197/251] Add a menu option for the minimum join delay

---
 src/m_menu.c | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/m_menu.c b/src/m_menu.c
index 1069f0f30..c5f10b2bd 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -1583,7 +1583,7 @@ static menuitem_t OP_ServerOptionsMenu[] =
 	{IT_HEADER, NULL, "General", NULL, 0},
 #ifndef NONET
 	{IT_STRING | IT_CVAR | IT_CV_STRING,
-	                         NULL, "Server name",                      &cv_servername,          7},
+	                         NULL, "Server name",                      &cv_servername,           7},
 	{IT_STRING | IT_CVAR,    NULL, "Max Players",                      &cv_maxplayers,          21},
 	{IT_STRING | IT_CVAR,    NULL, "Allow Add-on Downloading",         &cv_downloading,         26},
 	{IT_STRING | IT_CVAR,    NULL, "Allow players to join",            &cv_allownewplayer,      31},
@@ -1628,8 +1628,9 @@ static menuitem_t OP_ServerOptionsMenu[] =
 
 #ifndef NONET
 	{IT_HEADER, NULL, "Advanced", NULL, 225},
-	{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server",        &cv_masterserver,        231},
-	{IT_STRING | IT_CVAR,    NULL, "Attempts to resynchronise",        &cv_resynchattempts,     245},
+	{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server",        &cv_masterserver,       231},
+	{IT_STRING | IT_CVAR,    NULL, "Join delay",                       &cv_joindelay,          246},
+	{IT_STRING | IT_CVAR,    NULL, "Attempts to resynchronise",        &cv_resynchattempts,    251},
 #endif
 };
 
@@ -10822,7 +10823,8 @@ static void M_ServerOptions(INT32 choice)
 		OP_ServerOptionsMenu[ 3].status = IT_GRAYEDOUT; // Allow add-on downloading
 		OP_ServerOptionsMenu[ 4].status = IT_GRAYEDOUT; // Allow players to join
 		OP_ServerOptionsMenu[35].status = IT_GRAYEDOUT; // Master server
-		OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Attempts to resynchronise
+		OP_ServerOptionsMenu[36].status = IT_GRAYEDOUT; // Minimum delay between joins
+		OP_ServerOptionsMenu[37].status = IT_GRAYEDOUT; // Attempts to resynchronise
 	}
 	else
 	{
@@ -10834,6 +10836,7 @@ static void M_ServerOptions(INT32 choice)
 			? IT_GRAYEDOUT
 			: (IT_STRING | IT_CVAR | IT_CV_STRING));
 		OP_ServerOptionsMenu[36].status = IT_STRING | IT_CVAR;
+		OP_ServerOptionsMenu[37].status = IT_STRING | IT_CVAR;
 	}
 #endif
 

From 2419b65f793a45cb3552cb527614906cc052b64d Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Fri, 24 Apr 2020 16:40:09 +0100
Subject: [PATCH 198/251] Sync crumblestate in netgames

---
 src/p_saveg.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 259e58168..cfa93ef2f 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -755,6 +755,7 @@ static void P_NetUnArchiveColormaps(void)
 // diff3 flags
 #define SD_TAGLIST   0x01
 #define SD_COLORMAP  0x02
+#define SD_CRUMBLESTATE 0x03
 
 #define LD_FLAG     0x01
 #define LD_SPECIAL  0x02
@@ -834,6 +835,8 @@ static void P_NetArchiveWorld(void)
 
 		if (ss->extra_colormap != spawnss->extra_colormap)
 			diff3 |= SD_COLORMAP;
+		if (ss->crumblestate)
+			diff3 |= SD_CRUMBLESTATE;
 
 		// Check if any of the sector's FOFs differ from how they spawned
 		if (ss->ffloors)
@@ -901,6 +904,8 @@ static void P_NetArchiveWorld(void)
 			if (diff3 & SD_COLORMAP)
 				WRITEUINT32(put, CheckAddNetColormapToList(ss->extra_colormap));
 					// returns existing index if already added, or appends to net_colormaps and returns new index
+			if (diff3 & SD_CRUMBLESTATE)
+				WRITEINT32(put, ss->crumblestate);
 
 			// Special case: save the stats of all modified ffloors along with their ffloor "number"s
 			// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
@@ -1105,6 +1110,8 @@ static void P_NetUnArchiveWorld(void)
 
 		if (diff3 & SD_COLORMAP)
 			sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(get));
+		if (diff3 & SD_CRUMBLESTATE)
+			sectors[i].crumblestate = READINT32(get);
 
 		if (diff & SD_FFLOORS)
 		{

From 9df5d6e1e016ef36049687c1bd5df34c5940bb89 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Fri, 24 Apr 2020 16:53:54 +0100
Subject: [PATCH 199/251] These are flags! Serves me right for just rushing
 this out

---
 src/p_saveg.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index cfa93ef2f..7093ea93d 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -755,7 +755,7 @@ static void P_NetUnArchiveColormaps(void)
 // diff3 flags
 #define SD_TAGLIST   0x01
 #define SD_COLORMAP  0x02
-#define SD_CRUMBLESTATE 0x03
+#define SD_CRUMBLESTATE 0x04
 
 #define LD_FLAG     0x01
 #define LD_SPECIAL  0x02

From e4f2c1dc70d89fc3ac1a3ae1af7f2f560f1a352c Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Fri, 24 Apr 2020 18:33:35 +0200
Subject: [PATCH 200/251] Fix mouse being grabbed in intermission and cutscenes

---
 src/sdl/i_video.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index c042d141c..ec7bfc1c4 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -372,7 +372,9 @@ static boolean IgnoreMouse(void)
 		return false;
 	if (menuactive)
 		return !M_MouseNeeded();
-	if (paused || con_destlines || chat_on || gamestate != GS_LEVEL)
+	if (paused || con_destlines || chat_on)
+		return true;
+	if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION && gamestate != GS_CUTSCENE)
 		return true;
 	return false;
 }

From 08a7fcbe8db5629a8dbd57602b8cd44dc9abe593 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Fri, 24 Apr 2020 20:26:57 +0100
Subject: [PATCH 201/251] Split off FOF archiving-related code into their own
 functions

---
 src/p_saveg.c | 173 +++++++++++++++++++++++++++-----------------------
 1 file changed, 93 insertions(+), 80 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index f6e31fc3a..15e11a27b 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -772,6 +772,95 @@ static void P_NetUnArchiveColormaps(void)
 #define LD_S2BOTTEX 0x04
 #define LD_S2MIDTEX 0x08
 
+#define FD_FLAGS 0x01
+#define FD_ALPHA 0x02
+
+// Check if any of the sector's FOFs differ from how they spawned
+static boolean CheckFFloorDiff(sector_t *ss)
+{
+	ffloor_t *rover;
+
+	for (rover = ss->ffloors; rover; rover = rover->next)
+	{
+		if (rover->flags != rover->spawnflags
+		|| rover->alpha != rover->spawnalpha)
+			{
+				return true; // we found an FOF that changed!
+				// don't bother checking for more, we do that later
+			}
+	}
+	return false;
+}
+
+// Special case: save the stats of all modified ffloors along with their ffloor "number"s
+// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
+static void ArchiveFFloors(UINT8 *put, sector_t *ss)
+{
+	size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc
+	ffloor_t *rover;
+	UINT8 fflr_diff;
+	for (rover = ss->ffloors; rover; rover = rover->next)
+	{
+		fflr_diff = 0; // reset diff flags
+		if (rover->flags != rover->spawnflags)
+			fflr_diff |= FD_FLAGS;
+		if (rover->alpha != rover->spawnalpha)
+			fflr_diff |= FD_ALPHA;
+
+		if (fflr_diff)
+		{
+			WRITEUINT16(put, j); // save ffloor "number"
+			WRITEUINT8(put, fflr_diff);
+			if (fflr_diff & FD_FLAGS)
+				WRITEUINT32(put, rover->flags);
+			if (fflr_diff & FD_ALPHA)
+				WRITEINT16(put, rover->alpha);
+		}
+		j++;
+	}
+	WRITEUINT16(put, 0xffff);
+}
+
+static void UnArchiveFFloors(UINT8 *get, sector_t *ss)
+{
+	UINT16 j = 0; // number of current ffloor in loop
+	UINT16 fflr_i; // saved ffloor "number" of next modified ffloor
+	UINT16 fflr_diff; // saved ffloor diff
+	ffloor_t *rover;
+
+	rover = ss->ffloors;
+	if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case...
+		I_Error("Sector does not have any ffloors!");
+
+	fflr_i = READUINT16(get); // get first modified ffloor's number ready
+	for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here?
+	{
+		if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already
+			break;
+		// should NEVER need to be checked
+		//if (rover == NULL)
+			//break;
+		if (j != fflr_i) // this ffloor was not modified
+		{
+			j++;
+			rover = rover->next;
+			continue;
+		}
+
+		fflr_diff = READUINT8(get);
+
+		if (fflr_diff & FD_FLAGS)
+			rover->flags = READUINT32(get);
+		if (fflr_diff & FD_ALPHA)
+			rover->alpha = READINT16(get);
+
+		fflr_i = READUINT16(get); // get next ffloor "number" ready
+
+		j++;
+		rover = rover->next;
+	}
+}
+
 //
 // P_NetArchiveWorld
 //
@@ -838,20 +927,8 @@ static void P_NetArchiveWorld(void)
 		if (ss->crumblestate)
 			diff3 |= SD_CRUMBLESTATE;
 
-		// Check if any of the sector's FOFs differ from how they spawned
-		if (ss->ffloors)
-		{
-			ffloor_t *rover;
-			for (rover = ss->ffloors; rover; rover = rover->next)
-			{
-				if (rover->flags != rover->spawnflags
-				|| rover->alpha != rover->spawnalpha)
-					{
-						diff |= SD_FFLOORS; // we found an FOF that changed!
-						break; // don't bother checking for more, we do that later
-					}
-			}
-		}
+		if (ss->ffloors && CheckFFloorDiff(ss))
+			diff |= SD_FFLOORS;
 
 		if (diff3)
 			diff2 |= SD_DIFF3;
@@ -906,35 +983,8 @@ static void P_NetArchiveWorld(void)
 					// returns existing index if already added, or appends to net_colormaps and returns new index
 			if (diff3 & SD_CRUMBLESTATE)
 				WRITEINT32(put, ss->crumblestate);
-
-			// Special case: save the stats of all modified ffloors along with their ffloor "number"s
-			// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
 			if (diff & SD_FFLOORS)
-			{
-				size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc
-				ffloor_t *rover;
-				UINT8 fflr_diff;
-				for (rover = ss->ffloors; rover; rover = rover->next)
-				{
-					fflr_diff = 0; // reset diff flags
-					if (rover->flags != rover->spawnflags)
-						fflr_diff |= 1;
-					if (rover->alpha != rover->spawnalpha)
-						fflr_diff |= 2;
-
-					if (fflr_diff)
-					{
-						WRITEUINT16(put, j); // save ffloor "number"
-						WRITEUINT8(put, fflr_diff);
-						if (fflr_diff & 1)
-							WRITEUINT32(put, rover->flags);
-						if (fflr_diff & 2)
-							WRITEINT16(put, rover->alpha);
-					}
-					j++;
-				}
-				WRITEUINT16(put, 0xffff);
-			}
+				ArchiveFFloors(put, ss);
 		}
 	}
 
@@ -1114,44 +1164,7 @@ static void P_NetUnArchiveWorld(void)
 			sectors[i].crumblestate = READINT32(get);
 
 		if (diff & SD_FFLOORS)
-		{
-			UINT16 j = 0; // number of current ffloor in loop
-			UINT16 fflr_i; // saved ffloor "number" of next modified ffloor
-			UINT16 fflr_diff; // saved ffloor diff
-			ffloor_t *rover;
-
-			rover = sectors[i].ffloors;
-			if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case...
-				I_Error("Sector does not have any ffloors!");
-
-			fflr_i = READUINT16(get); // get first modified ffloor's number ready
-			for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here?
-			{
-				if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already
-					break;
-				// should NEVER need to be checked
-				//if (rover == NULL)
-					//break;
-				if (j != fflr_i) // this ffloor was not modified
-				{
-					j++;
-					rover = rover->next;
-					continue;
-				}
-
-				fflr_diff = READUINT8(get);
-
-				if (fflr_diff & 1)
-					rover->flags = READUINT32(get);
-				if (fflr_diff & 2)
-					rover->alpha = READINT16(get);
-
-				fflr_i = READUINT16(get); // get next ffloor "number" ready
-
-				j++;
-				rover = rover->next;
-			}
-		}
+			UnArchiveFFloors(get, sectors[i]);
 	}
 
 	for (;;)

From 2d45decbb0de5964f86c5dfc57f9167b17f3a71a Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Fri, 24 Apr 2020 20:28:01 +0100
Subject: [PATCH 202/251] remove statsec and statline as they appear to be
 entirely unused

---
 src/p_saveg.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 15e11a27b..e5f6cc75d 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -867,7 +867,6 @@ static void UnArchiveFFloors(UINT8 *get, sector_t *ss)
 static void P_NetArchiveWorld(void)
 {
 	size_t i;
-	INT32 statsec = 0, statline = 0;
 	const line_t *li = lines;
 	const line_t *spawnli = spawnlines;
 	const side_t *si;
@@ -938,8 +937,6 @@ static void P_NetArchiveWorld(void)
 
 		if (diff)
 		{
-			statsec++;
-
 			WRITEUINT16(put, i);
 			WRITEUINT8(put, diff);
 			if (diff & SD_DIFF2)
@@ -1033,7 +1030,6 @@ static void P_NetArchiveWorld(void)
 
 		if (diff)
 		{
-			statline++;
 			WRITEINT16(put, i);
 			WRITEUINT8(put, diff);
 			if (diff & LD_DIFF2)

From c1d2b8301b064b30ef1f4ac0e7f079fc61b313cb Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Fri, 24 Apr 2020 20:40:50 +0100
Subject: [PATCH 203/251] split sector/lines archiving-related code into their
 own functions too

---
 src/p_saveg.c | 242 +++++++++++++++++++++++++++-----------------------
 1 file changed, 133 insertions(+), 109 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index e5f6cc75d..860e3b86a 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -861,28 +861,13 @@ static void UnArchiveFFloors(UINT8 *get, sector_t *ss)
 	}
 }
 
-//
-// P_NetArchiveWorld
-//
-static void P_NetArchiveWorld(void)
+static void ArchiveSectors(UINT8 *put)
 {
 	size_t i;
-	const line_t *li = lines;
-	const line_t *spawnli = spawnlines;
-	const side_t *si;
-	const side_t *spawnsi;
-	UINT8 *put;
-
 	const sector_t *ss = sectors;
 	const sector_t *spawnss = spawnsectors;
 	UINT8 diff, diff2, diff3;
 
-	// initialize colormap vars because paranoia
-	ClearNetColormaps();
-
-	WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
-	put = save_p;
-
 	for (i = 0; i < numsectors; i++, ss++, spawnss++)
 	{
 		diff = diff2 = diff3 = 0;
@@ -986,8 +971,90 @@ static void P_NetArchiveWorld(void)
 	}
 
 	WRITEUINT16(put, 0xffff);
+}
+
+static void UnArchiveSectors(UINT8 *get)
+{
+	UINT16 i;
+	UINT8 diff, diff2, diff3;
+	for (;;)
+	{
+		i = READUINT16(get);
+
+		if (i == 0xffff)
+			break;
+
+		if (i > numsectors)
+			I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors));
+
+		diff = READUINT8(get);
+		if (diff & SD_DIFF2)
+			diff2 = READUINT8(get);
+		else
+			diff2 = 0;
+		if (diff2 & SD_DIFF3)
+			diff3 = READUINT8(get);
+		else
+			diff3 = 0;
+
+		if (diff & SD_FLOORHT)
+			sectors[i].floorheight = READFIXED(get);
+		if (diff & SD_CEILHT)
+			sectors[i].ceilingheight = READFIXED(get);
+		if (diff & SD_FLOORPIC)
+		{
+			sectors[i].floorpic = P_AddLevelFlatRuntime((char *)get);
+			get += 8;
+		}
+		if (diff & SD_CEILPIC)
+		{
+			sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)get);
+			get += 8;
+		}
+		if (diff & SD_LIGHT)
+			sectors[i].lightlevel = READINT16(get);
+		if (diff & SD_SPECIAL)
+			sectors[i].special = READINT16(get);
+
+		if (diff2 & SD_FXOFFS)
+			sectors[i].floor_xoffs = READFIXED(get);
+		if (diff2 & SD_FYOFFS)
+			sectors[i].floor_yoffs = READFIXED(get);
+		if (diff2 & SD_CXOFFS)
+			sectors[i].ceiling_xoffs = READFIXED(get);
+		if (diff2 & SD_CYOFFS)
+			sectors[i].ceiling_yoffs = READFIXED(get);
+		if (diff2 & SD_FLOORANG)
+			sectors[i].floorpic_angle  = READANGLE(get);
+		if (diff2 & SD_CEILANG)
+			sectors[i].ceilingpic_angle = READANGLE(get);
+		if (diff2 & SD_TAG)
+			sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag
+		if (diff3 & SD_TAGLIST)
+		{
+			sectors[i].firsttag = READINT32(get);
+			sectors[i].nexttag = READINT32(get);
+		}
+
+		if (diff3 & SD_COLORMAP)
+			sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(get));
+		if (diff3 & SD_CRUMBLESTATE)
+			sectors[i].crumblestate = READINT32(get);
+
+		if (diff & SD_FFLOORS)
+			UnArchiveFFloors(get, sectors[i]);
+	}
+}
+
+static void ArchiveLines(UINT8 *put)
+{
+	size_t i;
+	const line_t *li = lines;
+	const line_t *spawnli = spawnlines;
+	const side_t *si;
+	const side_t *spawnsi;
+	UINT8 diff, diff2, diff3;
 
-	// do lines
 	for (i = 0; i < numlines; i++, spawnli++, li++)
 	{
 		diff = diff2 = diff3 = 0;
@@ -1063,106 +1130,15 @@ static void P_NetArchiveWorld(void)
 		}
 	}
 	WRITEUINT16(put, 0xffff);
-	R_ClearTextureNumCache(false);
-
-	save_p = put;
 }
 
-//
-// P_NetUnArchiveWorld
-//
-static void P_NetUnArchiveWorld(void)
+static void UnArchiveLines(UINT8 *get)
 {
 	UINT16 i;
 	line_t *li;
 	side_t *si;
-	UINT8 *get;
 	UINT8 diff, diff2, diff3;
 
-	if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD)
-		I_Error("Bad $$$.sav at archive block World");
-
-	// initialize colormap vars because paranoia
-	ClearNetColormaps();
-
-	// count the level's ffloors so that colormap loading can have an upper limit
-	for (i = 0; i < numsectors; i++)
-	{
-		ffloor_t *rover;
-		for (rover = sectors[i].ffloors; rover; rover = rover->next)
-			num_ffloors++;
-	}
-
-	get = save_p;
-
-	for (;;)
-	{
-		i = READUINT16(get);
-
-		if (i == 0xffff)
-			break;
-
-		if (i > numsectors)
-			I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors));
-
-		diff = READUINT8(get);
-		if (diff & SD_DIFF2)
-			diff2 = READUINT8(get);
-		else
-			diff2 = 0;
-		if (diff2 & SD_DIFF3)
-			diff3 = READUINT8(get);
-		else
-			diff3 = 0;
-
-		if (diff & SD_FLOORHT)
-			sectors[i].floorheight = READFIXED(get);
-		if (diff & SD_CEILHT)
-			sectors[i].ceilingheight = READFIXED(get);
-		if (diff & SD_FLOORPIC)
-		{
-			sectors[i].floorpic = P_AddLevelFlatRuntime((char *)get);
-			get += 8;
-		}
-		if (diff & SD_CEILPIC)
-		{
-			sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)get);
-			get += 8;
-		}
-		if (diff & SD_LIGHT)
-			sectors[i].lightlevel = READINT16(get);
-		if (diff & SD_SPECIAL)
-			sectors[i].special = READINT16(get);
-
-		if (diff2 & SD_FXOFFS)
-			sectors[i].floor_xoffs = READFIXED(get);
-		if (diff2 & SD_FYOFFS)
-			sectors[i].floor_yoffs = READFIXED(get);
-		if (diff2 & SD_CXOFFS)
-			sectors[i].ceiling_xoffs = READFIXED(get);
-		if (diff2 & SD_CYOFFS)
-			sectors[i].ceiling_yoffs = READFIXED(get);
-		if (diff2 & SD_FLOORANG)
-			sectors[i].floorpic_angle  = READANGLE(get);
-		if (diff2 & SD_CEILANG)
-			sectors[i].ceilingpic_angle = READANGLE(get);
-		if (diff2 & SD_TAG)
-			sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag
-		if (diff3 & SD_TAGLIST)
-		{
-			sectors[i].firsttag = READINT32(get);
-			sectors[i].nexttag = READINT32(get);
-		}
-
-		if (diff3 & SD_COLORMAP)
-			sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(get));
-		if (diff3 & SD_CRUMBLESTATE)
-			sectors[i].crumblestate = READINT32(get);
-
-		if (diff & SD_FFLOORS)
-			UnArchiveFFloors(get, sectors[i]);
-	}
-
 	for (;;)
 	{
 		i = READUINT16(get);
@@ -1209,6 +1185,54 @@ static void P_NetUnArchiveWorld(void)
 		if (diff2 & LD_S2MIDTEX)
 			si->midtexture = READINT32(get);
 	}
+}
+
+//
+// P_NetArchiveWorld
+//
+static void P_NetArchiveWorld(void)
+{
+	UINT8 *put;
+
+	// initialize colormap vars because paranoia
+	ClearNetColormaps();
+
+	WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
+	put = save_p;
+
+	ArchiveSectors(put);
+	ArchiveLines(put);
+	R_ClearTextureNumCache(false);
+
+	save_p = put;
+}
+
+//
+// P_NetUnArchiveWorld
+//
+static void P_NetUnArchiveWorld(void)
+{
+	UINT16 i;
+	UINT8 *get;
+
+	if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD)
+		I_Error("Bad $$$.sav at archive block World");
+
+	// initialize colormap vars because paranoia
+	ClearNetColormaps();
+
+	// count the level's ffloors so that colormap loading can have an upper limit
+	for (i = 0; i < numsectors; i++)
+	{
+		ffloor_t *rover;
+		for (rover = sectors[i].ffloors; rover; rover = rover->next)
+			num_ffloors++;
+	}
+
+	get = save_p;
+
+	UnArchiveSectors(get);
+	UnArchiveLines(get);
 
 	save_p = get;
 }

From 1e61229cb7fe76961a89b18f85f49124b10ab0ef Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Fri, 24 Apr 2020 20:57:48 +0100
Subject: [PATCH 204/251] we don't actually need put/get pointers at all (plus
 with everything put into functions they wouldn't work properly anyway)

---
 src/p_saveg.c | 202 ++++++++++++++++++++++++--------------------------
 1 file changed, 96 insertions(+), 106 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 860e3b86a..e2bc9dd61 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -794,7 +794,7 @@ static boolean CheckFFloorDiff(sector_t *ss)
 
 // Special case: save the stats of all modified ffloors along with their ffloor "number"s
 // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
-static void ArchiveFFloors(UINT8 *put, sector_t *ss)
+static void ArchiveFFloors(sector_t *ss)
 {
 	size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc
 	ffloor_t *rover;
@@ -809,19 +809,19 @@ static void ArchiveFFloors(UINT8 *put, sector_t *ss)
 
 		if (fflr_diff)
 		{
-			WRITEUINT16(put, j); // save ffloor "number"
-			WRITEUINT8(put, fflr_diff);
+			WRITEUINT16(save_p, j); // save ffloor "number"
+			WRITEUINT8(save_p, fflr_diff);
 			if (fflr_diff & FD_FLAGS)
-				WRITEUINT32(put, rover->flags);
+				WRITEUINT32(save_p, rover->flags);
 			if (fflr_diff & FD_ALPHA)
-				WRITEINT16(put, rover->alpha);
+				WRITEINT16(save_p, rover->alpha);
 		}
 		j++;
 	}
-	WRITEUINT16(put, 0xffff);
+	WRITEUINT16(save_p, 0xffff);
 }
 
-static void UnArchiveFFloors(UINT8 *get, sector_t *ss)
+static void UnArchiveFFloors(sector_t *ss)
 {
 	UINT16 j = 0; // number of current ffloor in loop
 	UINT16 fflr_i; // saved ffloor "number" of next modified ffloor
@@ -832,7 +832,7 @@ static void UnArchiveFFloors(UINT8 *get, sector_t *ss)
 	if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case...
 		I_Error("Sector does not have any ffloors!");
 
-	fflr_i = READUINT16(get); // get first modified ffloor's number ready
+	fflr_i = READUINT16(save_p); // get first modified ffloor's number ready
 	for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here?
 	{
 		if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already
@@ -847,21 +847,21 @@ static void UnArchiveFFloors(UINT8 *get, sector_t *ss)
 			continue;
 		}
 
-		fflr_diff = READUINT8(get);
+		fflr_diff = READUINT8(save_p);
 
 		if (fflr_diff & FD_FLAGS)
-			rover->flags = READUINT32(get);
+			rover->flags = READUINT32(save_p);
 		if (fflr_diff & FD_ALPHA)
-			rover->alpha = READINT16(get);
+			rover->alpha = READINT16(save_p);
 
-		fflr_i = READUINT16(get); // get next ffloor "number" ready
+		fflr_i = READUINT16(save_p); // get next ffloor "number" ready
 
 		j++;
 		rover = rover->next;
 	}
 }
 
-static void ArchiveSectors(UINT8 *put)
+static void ArchiveSectors(void)
 {
 	size_t i;
 	const sector_t *ss = sectors;
@@ -922,64 +922,64 @@ static void ArchiveSectors(UINT8 *put)
 
 		if (diff)
 		{
-			WRITEUINT16(put, i);
-			WRITEUINT8(put, diff);
+			WRITEUINT16(save_p, i);
+			WRITEUINT8(save_p, diff);
 			if (diff & SD_DIFF2)
-				WRITEUINT8(put, diff2);
+				WRITEUINT8(save_p, diff2);
 			if (diff2 & SD_DIFF3)
-				WRITEUINT8(put, diff3);
+				WRITEUINT8(save_p, diff3);
 			if (diff & SD_FLOORHT)
-				WRITEFIXED(put, ss->floorheight);
+				WRITEFIXED(save_p, ss->floorheight);
 			if (diff & SD_CEILHT)
-				WRITEFIXED(put, ss->ceilingheight);
+				WRITEFIXED(save_p, ss->ceilingheight);
 			if (diff & SD_FLOORPIC)
-				WRITEMEM(put, levelflats[ss->floorpic].name, 8);
+				WRITEMEM(save_p, levelflats[ss->floorpic].name, 8);
 			if (diff & SD_CEILPIC)
-				WRITEMEM(put, levelflats[ss->ceilingpic].name, 8);
+				WRITEMEM(save_p, levelflats[ss->ceilingpic].name, 8);
 			if (diff & SD_LIGHT)
-				WRITEINT16(put, ss->lightlevel);
+				WRITEINT16(save_p, ss->lightlevel);
 			if (diff & SD_SPECIAL)
-				WRITEINT16(put, ss->special);
+				WRITEINT16(save_p, ss->special);
 			if (diff2 & SD_FXOFFS)
-				WRITEFIXED(put, ss->floor_xoffs);
+				WRITEFIXED(save_p, ss->floor_xoffs);
 			if (diff2 & SD_FYOFFS)
-				WRITEFIXED(put, ss->floor_yoffs);
+				WRITEFIXED(save_p, ss->floor_yoffs);
 			if (diff2 & SD_CXOFFS)
-				WRITEFIXED(put, ss->ceiling_xoffs);
+				WRITEFIXED(save_p, ss->ceiling_xoffs);
 			if (diff2 & SD_CYOFFS)
-				WRITEFIXED(put, ss->ceiling_yoffs);
+				WRITEFIXED(save_p, ss->ceiling_yoffs);
 			if (diff2 & SD_FLOORANG)
-				WRITEANGLE(put, ss->floorpic_angle);
+				WRITEANGLE(save_p, ss->floorpic_angle);
 			if (diff2 & SD_CEILANG)
-				WRITEANGLE(put, ss->ceilingpic_angle);
+				WRITEANGLE(save_p, ss->ceilingpic_angle);
 			if (diff2 & SD_TAG) // save only the tag
-				WRITEINT16(put, ss->tag);
+				WRITEINT16(save_p, ss->tag);
 			if (diff3 & SD_TAGLIST) // save both firsttag and nexttag
 			{ // either of these could be changed even if tag isn't
-				WRITEINT32(put, ss->firsttag);
-				WRITEINT32(put, ss->nexttag);
+				WRITEINT32(save_p, ss->firsttag);
+				WRITEINT32(save_p, ss->nexttag);
 			}
 
 			if (diff3 & SD_COLORMAP)
-				WRITEUINT32(put, CheckAddNetColormapToList(ss->extra_colormap));
+				WRITEUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap));
 					// returns existing index if already added, or appends to net_colormaps and returns new index
 			if (diff3 & SD_CRUMBLESTATE)
-				WRITEINT32(put, ss->crumblestate);
+				WRITEINT32(save_p, ss->crumblestate);
 			if (diff & SD_FFLOORS)
-				ArchiveFFloors(put, ss);
+				ArchiveFFloors(save_p, ss);
 		}
 	}
 
-	WRITEUINT16(put, 0xffff);
+	WRITEUINT16(save_p, 0xffff);
 }
 
-static void UnArchiveSectors(UINT8 *get)
+static void UnArchiveSectors(void)
 {
 	UINT16 i;
 	UINT8 diff, diff2, diff3;
 	for (;;)
 	{
-		i = READUINT16(get);
+		i = READUINT16(save_p);
 
 		if (i == 0xffff)
 			break;
@@ -987,66 +987,66 @@ static void UnArchiveSectors(UINT8 *get)
 		if (i > numsectors)
 			I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors));
 
-		diff = READUINT8(get);
+		diff = READUINT8(save_p);
 		if (diff & SD_DIFF2)
-			diff2 = READUINT8(get);
+			diff2 = READUINT8(save_p);
 		else
 			diff2 = 0;
 		if (diff2 & SD_DIFF3)
-			diff3 = READUINT8(get);
+			diff3 = READUINT8(save_p);
 		else
 			diff3 = 0;
 
 		if (diff & SD_FLOORHT)
-			sectors[i].floorheight = READFIXED(get);
+			sectors[i].floorheight = READFIXED(save_p);
 		if (diff & SD_CEILHT)
-			sectors[i].ceilingheight = READFIXED(get);
+			sectors[i].ceilingheight = READFIXED(save_p);
 		if (diff & SD_FLOORPIC)
 		{
-			sectors[i].floorpic = P_AddLevelFlatRuntime((char *)get);
-			get += 8;
+			sectors[i].floorpic = P_AddLevelFlatRuntime((char *)save_p);
+			save_p += 8;
 		}
 		if (diff & SD_CEILPIC)
 		{
-			sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)get);
-			get += 8;
+			sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)save_p);
+			save_p += 8;
 		}
 		if (diff & SD_LIGHT)
-			sectors[i].lightlevel = READINT16(get);
+			sectors[i].lightlevel = READINT16(save_p);
 		if (diff & SD_SPECIAL)
-			sectors[i].special = READINT16(get);
+			sectors[i].special = READINT16(save_p);
 
 		if (diff2 & SD_FXOFFS)
-			sectors[i].floor_xoffs = READFIXED(get);
+			sectors[i].floor_xoffs = READFIXED(save_p);
 		if (diff2 & SD_FYOFFS)
-			sectors[i].floor_yoffs = READFIXED(get);
+			sectors[i].floor_yoffs = READFIXED(save_p);
 		if (diff2 & SD_CXOFFS)
-			sectors[i].ceiling_xoffs = READFIXED(get);
+			sectors[i].ceiling_xoffs = READFIXED(save_p);
 		if (diff2 & SD_CYOFFS)
-			sectors[i].ceiling_yoffs = READFIXED(get);
+			sectors[i].ceiling_yoffs = READFIXED(save_p);
 		if (diff2 & SD_FLOORANG)
-			sectors[i].floorpic_angle  = READANGLE(get);
+			sectors[i].floorpic_angle  = READANGLE(save_p);
 		if (diff2 & SD_CEILANG)
-			sectors[i].ceilingpic_angle = READANGLE(get);
+			sectors[i].ceilingpic_angle = READANGLE(save_p);
 		if (diff2 & SD_TAG)
-			sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag
+			sectors[i].tag = READINT16(save_p); // DON'T use P_ChangeSectorTag
 		if (diff3 & SD_TAGLIST)
 		{
-			sectors[i].firsttag = READINT32(get);
-			sectors[i].nexttag = READINT32(get);
+			sectors[i].firsttag = READINT32(save_p);
+			sectors[i].nexttag = READINT32(save_p);
 		}
 
 		if (diff3 & SD_COLORMAP)
-			sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(get));
+			sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p));
 		if (diff3 & SD_CRUMBLESTATE)
-			sectors[i].crumblestate = READINT32(get);
+			sectors[i].crumblestate = READINT32(save_p);
 
 		if (diff & SD_FFLOORS)
-			UnArchiveFFloors(get, sectors[i]);
+			UnArchiveFFloors(save_p, sectors[i]);
 	}
 }
 
-static void ArchiveLines(UINT8 *put)
+static void ArchiveLines(void)
 {
 	size_t i;
 	const line_t *li = lines;
@@ -1097,42 +1097,42 @@ static void ArchiveLines(UINT8 *put)
 
 		if (diff)
 		{
-			WRITEINT16(put, i);
-			WRITEUINT8(put, diff);
+			WRITEINT16(save_p, i);
+			WRITEUINT8(save_p, diff);
 			if (diff & LD_DIFF2)
-				WRITEUINT8(put, diff2);
+				WRITEUINT8(save_p, diff2);
 			if (diff & LD_FLAG)
-				WRITEINT16(put, li->flags);
+				WRITEINT16(save_p, li->flags);
 			if (diff & LD_SPECIAL)
-				WRITEINT16(put, li->special);
+				WRITEINT16(save_p, li->special);
 			if (diff & LD_CLLCOUNT)
-				WRITEINT16(put, li->callcount);
+				WRITEINT16(save_p, li->callcount);
 
 			si = &sides[li->sidenum[0]];
 			if (diff & LD_S1TEXOFF)
-				WRITEFIXED(put, si->textureoffset);
+				WRITEFIXED(save_p, si->textureoffset);
 			if (diff & LD_S1TOPTEX)
-				WRITEINT32(put, si->toptexture);
+				WRITEINT32(save_p, si->toptexture);
 			if (diff & LD_S1BOTTEX)
-				WRITEINT32(put, si->bottomtexture);
+				WRITEINT32(save_p, si->bottomtexture);
 			if (diff & LD_S1MIDTEX)
-				WRITEINT32(put, si->midtexture);
+				WRITEINT32(save_p, si->midtexture);
 
 			si = &sides[li->sidenum[1]];
 			if (diff2 & LD_S2TEXOFF)
-				WRITEFIXED(put, si->textureoffset);
+				WRITEFIXED(save_p, si->textureoffset);
 			if (diff2 & LD_S2TOPTEX)
-				WRITEINT32(put, si->toptexture);
+				WRITEINT32(save_p, si->toptexture);
 			if (diff2 & LD_S2BOTTEX)
-				WRITEINT32(put, si->bottomtexture);
+				WRITEINT32(save_p, si->bottomtexture);
 			if (diff2 & LD_S2MIDTEX)
-				WRITEINT32(put, si->midtexture);
+				WRITEINT32(save_p, si->midtexture);
 		}
 	}
-	WRITEUINT16(put, 0xffff);
+	WRITEUINT16(save_p, 0xffff);
 }
 
-static void UnArchiveLines(UINT8 *get)
+static void UnArchiveLines(void)
 {
 	UINT16 i;
 	line_t *li;
@@ -1141,49 +1141,49 @@ static void UnArchiveLines(UINT8 *get)
 
 	for (;;)
 	{
-		i = READUINT16(get);
+		i = READUINT16(save_p);
 
 		if (i == 0xffff)
 			break;
 		if (i > numlines)
 			I_Error("Invalid line number %u from server", i);
 
-		diff = READUINT8(get);
+		diff = READUINT8(save_p);
 		li = &lines[i];
 
 		if (diff & LD_DIFF2)
-			diff2 = READUINT8(get);
+			diff2 = READUINT8(save_p);
 		else
 			diff2 = 0;
 
 		diff3 = 0;
 
 		if (diff & LD_FLAG)
-			li->flags = READINT16(get);
+			li->flags = READINT16(save_p);
 		if (diff & LD_SPECIAL)
-			li->special = READINT16(get);
+			li->special = READINT16(save_p);
 		if (diff & LD_CLLCOUNT)
-			li->callcount = READINT16(get);
+			li->callcount = READINT16(save_p);
 
 		si = &sides[li->sidenum[0]];
 		if (diff & LD_S1TEXOFF)
-			si->textureoffset = READFIXED(get);
+			si->textureoffset = READFIXED(save_p);
 		if (diff & LD_S1TOPTEX)
-			si->toptexture = READINT32(get);
+			si->toptexture = READINT32(save_p);
 		if (diff & LD_S1BOTTEX)
-			si->bottomtexture = READINT32(get);
+			si->bottomtexture = READINT32(save_p);
 		if (diff & LD_S1MIDTEX)
-			si->midtexture = READINT32(get);
+			si->midtexture = READINT32(save_p);
 
 		si = &sides[li->sidenum[1]];
 		if (diff2 & LD_S2TEXOFF)
-			si->textureoffset = READFIXED(get);
+			si->textureoffset = READFIXED(save_p);
 		if (diff2 & LD_S2TOPTEX)
-			si->toptexture = READINT32(get);
+			si->toptexture = READINT32(save_p);
 		if (diff2 & LD_S2BOTTEX)
-			si->bottomtexture = READINT32(get);
+			si->bottomtexture = READINT32(save_p);
 		if (diff2 & LD_S2MIDTEX)
-			si->midtexture = READINT32(get);
+			si->midtexture = READINT32(save_p);
 	}
 }
 
@@ -1192,19 +1192,14 @@ static void UnArchiveLines(UINT8 *get)
 //
 static void P_NetArchiveWorld(void)
 {
-	UINT8 *put;
-
 	// initialize colormap vars because paranoia
 	ClearNetColormaps();
 
 	WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
-	put = save_p;
 
-	ArchiveSectors(put);
-	ArchiveLines(put);
+	ArchiveSectors();
+	ArchiveLines();
 	R_ClearTextureNumCache(false);
-
-	save_p = put;
 }
 
 //
@@ -1213,7 +1208,6 @@ static void P_NetArchiveWorld(void)
 static void P_NetUnArchiveWorld(void)
 {
 	UINT16 i;
-	UINT8 *get;
 
 	if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD)
 		I_Error("Bad $$$.sav at archive block World");
@@ -1229,12 +1223,8 @@ static void P_NetUnArchiveWorld(void)
 			num_ffloors++;
 	}
 
-	get = save_p;
-
-	UnArchiveSectors(get);
-	UnArchiveLines(get);
-
-	save_p = get;
+	UnArchiveSectors();
+	UnArchiveLines();
 }
 
 //

From e406a7bef5b029dc49b8861f89557644f8649c2c Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Fri, 24 Apr 2020 20:58:38 +0100
Subject: [PATCH 205/251] no diff3 needed for line archiving

---
 src/p_saveg.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index e2bc9dd61..541b42426 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1053,11 +1053,11 @@ static void ArchiveLines(void)
 	const line_t *spawnli = spawnlines;
 	const side_t *si;
 	const side_t *spawnsi;
-	UINT8 diff, diff2, diff3;
+	UINT8 diff, diff2; // no diff3
 
 	for (i = 0; i < numlines; i++, spawnli++, li++)
 	{
-		diff = diff2 = diff3 = 0;
+		diff = diff2 = 0;
 
 		if (li->special != spawnli->special)
 			diff |= LD_SPECIAL;
@@ -1137,7 +1137,7 @@ static void UnArchiveLines(void)
 	UINT16 i;
 	line_t *li;
 	side_t *si;
-	UINT8 diff, diff2, diff3;
+	UINT8 diff, diff2; // no diff3
 
 	for (;;)
 	{
@@ -1156,8 +1156,6 @@ static void UnArchiveLines(void)
 		else
 			diff2 = 0;
 
-		diff3 = 0;
-
 		if (diff & LD_FLAG)
 			li->flags = READINT16(save_p);
 		if (diff & LD_SPECIAL)

From 7dda5f6b946079925e86f83325c0889a16e842d3 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Fri, 24 Apr 2020 22:29:41 +0100
Subject: [PATCH 206/251] created P_GetFFloorID to get an "ID" of an FOF in its
 target sector (an opposite to P_GetFFloorByID you could say!), rewrote
 floor/ceiling rover archiving code to use both P_GetFFloorID and
 P_GetFFloorByID

---
 src/p_saveg.c | 66 ++++++++-------------------------------------------
 src/p_spec.c  | 31 +++++++++++++++++++++++-
 src/p_spec.h  |  1 +
 3 files changed, 41 insertions(+), 57 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 541b42426..e63409386 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1518,42 +1518,14 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 
 	if (diff2 & MD2_FLOORROVER)
 	{
-		ffloor_t *rover;
-		size_t i = 0;
-		UINT32 roverindex = 0;
-
-		for (rover = mobj->floorrover->target->ffloors; rover; rover = rover->next)
-		{
-			if (rover == mobj->floorrover)
-			{
-				roverindex = i;
-				break;
-			}
-			i++;
-		}
-
-		WRITEUINT32(save_p, (UINT32)(mobj->floorrover->target - sectors));
-		WRITEUINT32(save_p, rover ? roverindex : i); // store max index to denote invalid ffloor ref
+		WRITEUINT32(save_p, SaveSector(mobj->floorrover->target));
+		WRITEUINT16(save_p, P_GetFFloorID(mobj->floorrover));
 	}
 
 	if (diff2 & MD2_CEILINGROVER)
 	{
-		ffloor_t *rover;
-		size_t i = 0;
-		UINT32 roverindex = 0;
-
-		for (rover = mobj->ceilingrover->target->ffloors; rover; rover = rover->next)
-		{
-			if (rover == mobj->ceilingrover)
-			{
-				roverindex = i;
-				break;
-			}
-			i++;
-		}
-
-		WRITEUINT32(save_p, (UINT32)(mobj->ceilingrover->target - sectors));
-		WRITEUINT32(save_p, rover ? roverindex : i); // store max index to denote invalid ffloor ref
+		WRITEUINT32(save_p, SaveSector(mobj->ceilingrover->target));
+		WRITEUINT16(save_p, P_GetFFloorID(mobj->ceilingrover));
 	}
 
 	if (diff & MD_SPAWNPOINT)
@@ -2634,34 +2606,16 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 
 	if (diff2 & MD2_FLOORROVER)
 	{
-		size_t floor_sectornum = (size_t)READUINT32(save_p);
-		size_t floor_rovernum = (size_t)READUINT32(save_p);
-		ffloor_t *rover = NULL;
-		size_t rovernum = 0;
-
-		for (rover = sectors[floor_sectornum].ffloors; rover; rover = rover->next)
-		{
-			if (rovernum == floor_rovernum)
-				break;
-			rovernum++;
-		}
-		floorrover = rover;
+		sector_t *sec = LoadSector(READUINT32(save_p));
+		UINT16 id = READUINT16(save_p);
+		floorrover = P_GetFFloorByID(sec, id);
 	}
 
 	if (diff2 & MD2_CEILINGROVER)
 	{
-		size_t ceiling_sectornum = (size_t)READUINT32(save_p);
-		size_t ceiling_rovernum = (size_t)READUINT32(save_p);
-		ffloor_t *rover = NULL;
-		size_t rovernum = 0;
-
-		for (rover = sectors[ceiling_sectornum].ffloors; rover; rover = rover->next)
-		{
-			if (rovernum == ceiling_rovernum)
-				break;
-			rovernum++;
-		}
-		ceilingrover = rover;
+		sector_t *sec = LoadSector(READUINT32(save_p));
+		UINT16 id = READUINT16(save_p);
+		ceilingrover = P_GetFFloorByID(sec, id);
 	}
 
 	if (diff & MD_SPAWNPOINT)
diff --git a/src/p_spec.c b/src/p_spec.c
index 6456cc514..96ae5522b 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -5678,6 +5678,35 @@ void P_UpdateSpecials(void)
 	}
 }
 
+//
+// Floor over floors (FOFs), 3Dfloors, 3Dblocks, fake floors (ffloors), rovers, or whatever you want to call them
+//
+
+/** Gets the ID number for a 3Dfloor in its target sector.
+  *
+  * \param fflr The 3Dfloor we want an ID for.
+  * \return ID of 3Dfloor in target sector. Note that the first FOF's ID is 0. UINT16_MAX is given if invalid.
+  * \sa P_GetFFloorByID
+  */
+UINT16 P_GetFFloorID(ffloor_t *fflr)
+{
+	ffloor_t *rover;
+	sector_t *sec;
+	UINT16 i = 0;
+
+	if (!rover)
+		return UINT16_MAX;
+
+	sec = rover->target;
+
+	if (!sec->ffloors)
+		return UINT16_MAX;
+	for (rover = sec->ffloors; rover; rover = rover->next, i++)
+		if (rover == fflr)
+			return i;
+	return UINT16_MAX;
+}
+
 /** Gets a 3Dfloor by control sector.
   *
   * \param sec  Target sector.
@@ -5702,7 +5731,7 @@ static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2)
   * \param sec Target sector.
   * \param id  ID of 3Dfloor in target sector. Note that the first FOF's ID is 0.
   * \return Pointer to found 3Dfloor, or NULL.
-  * \sa P_GetFFloorBySec
+  * \sa P_GetFFloorBySec, P_GetFFloorID
   */
 ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id)
 {
diff --git a/src/p_spec.h b/src/p_spec.h
index e243e3a61..8e778b9ed 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -74,6 +74,7 @@ void P_RunDeNightserizeExecutors(mobj_t *actor);
 void P_RunNightsLapExecutors(mobj_t *actor);
 void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean enoughspheres);
 
+UINT16 P_GetFFloorID(ffloor_t *fflr);
 ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id);
 
 //

From 49cceda15bce75c0c54301c8747e413ee3f436e0 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Fri, 24 Apr 2020 22:43:23 +0100
Subject: [PATCH 207/251] Do the same with writing ARCH_FFLOOR values in Lua
 archiving code (reading was already dealt with years ago)

---
 src/lua_script.c | 12 ++----------
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/src/lua_script.c b/src/lua_script.c
index 7adf62fcc..6b7b122f0 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -1010,16 +1010,8 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 			if (!rover)
 				WRITEUINT8(save_p, ARCH_NULL);
 			else {
-				ffloor_t *r2;
-				UINT16 i = 0;
-				// search for id
-				for (r2 = rover->target->ffloors; r2; r2 = r2->next)
-				{
-					if (r2 == rover)
-						break;
-					i++;
-				}
-				if (!r2)
+				UINT16 i = P_GetFFloorID(rover);
+				if (i == UINT16_MAX) // invalid ID
 					WRITEUINT8(save_p, ARCH_NULL);
 				else
 				{

From 3cd8f62ae984120989c7b6685550112aa674b397 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 25 Apr 2020 08:18:48 +0200
Subject: [PATCH 208/251] Remove a line I overlooked in the thinker cleanup
 branch

---
 src/p_spec.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index 6456cc514..826260d3a 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6863,7 +6863,6 @@ void P_SpawnSpecials(boolean fromnetsave)
 				break;
 			case 153: // Dynamic Sinking Platform
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
-				lines[i].flags |= ML_BLOCKMONSTERS;
 				P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), false, !!(lines[i].flags & ML_NOCLIMB), true);
 				break;
 

From 049a7db877ce52b08981137ea435f2cb3c3df361 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Sat, 25 Apr 2020 16:52:11 +0100
Subject: [PATCH 209/251] whoops

---
 src/p_spec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index 96ae5522b..f15741479 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -5694,7 +5694,7 @@ UINT16 P_GetFFloorID(ffloor_t *fflr)
 	sector_t *sec;
 	UINT16 i = 0;
 
-	if (!rover)
+	if (!fflr)
 		return UINT16_MAX;
 
 	sec = rover->target;

From 7034e2537a9db7024b26dc85b78a93c8fe1eb728 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Sat, 25 Apr 2020 16:53:52 +0100
Subject: [PATCH 210/251] whoops the sequel

---
 src/p_spec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index f15741479..e84619c7f 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -5697,7 +5697,7 @@ UINT16 P_GetFFloorID(ffloor_t *fflr)
 	if (!fflr)
 		return UINT16_MAX;
 
-	sec = rover->target;
+	sec = fflr->target;
 
 	if (!sec->ffloors)
 		return UINT16_MAX;

From 212358dbba7f2e5e47ac12c3a3d6f705ba027d60 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Sun, 26 Apr 2020 00:39:52 +0200
Subject: [PATCH 211/251] Restore old entry searching functions and add
 alternate versions for long names

---
 src/lua_hudlib.c |   6 +--
 src/w_wad.c      | 120 +++++++++++++++++++++++++++++++++++++++++++++--
 src/w_wad.h      |   4 ++
 3 files changed, 124 insertions(+), 6 deletions(-)

diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 818e760c9..703b924bb 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -412,9 +412,9 @@ static int libd_cachePatch(lua_State *L)
 	HUDONLY
 
 	luapat = patchinfohead;
-	lumpnum = W_CheckNumForName(luaL_checkstring(L, 1));
+	lumpnum = W_CheckNumForLongName(luaL_checkstring(L, 1));
 	if (lumpnum == LUMPERROR)
-		lumpnum = W_GetNumForName("MISSING");
+		lumpnum = W_GetNumForLongName("MISSING");
 
 	for (i = 0; i < numluapatches; i++)
 	{
@@ -454,7 +454,7 @@ static int libd_cachePatch(lua_State *L)
 	numluapatches++;
 #else
 	HUDONLY
-	LUA_PushUserdata(L, W_CachePatchName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH);
+	LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH);
 #endif
 	return 1;
 }
diff --git a/src/w_wad.c b/src/w_wad.c
index f273753c8..a81132354 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -920,6 +920,40 @@ const char *W_CheckNameForNum(lumpnum_t lumpnum)
 // 'startlump' is the lump number to start the search
 //
 UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
+{
+	UINT16 i;
+	static char uname[8 + 1];
+
+	if (!TestValidLump(wad,0))
+		return INT16_MAX;
+
+	strlcpy(uname, name, sizeof uname);
+	strupr(uname);
+
+	//
+	// scan forward
+	// start at 'startlump', useful parameter when there are multiple
+	//                       resources with the same name
+	//
+	if (startlump < wadfiles[wad]->numlumps)
+	{
+		lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
+		for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
+			if (!strncmp(lump_p->name, uname, sizeof(uname) - 1))
+				return i;
+	}
+
+	// not found.
+	return INT16_MAX;
+}
+
+//
+// Like W_CheckNumForNamePwad, but can find entries with long names
+//
+// Should be the only version, but that's not possible until we fix
+// all the instances of non null-terminated strings in the codebase...
+//
+UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump)
 {
 	UINT16 i;
 	static char uname[256 + 1];
@@ -1025,7 +1059,8 @@ lumpnum_t W_CheckNumForName(const char *name)
 	// most recent entries first
 	for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--)
 	{
-		if (strcmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0)
+		if (!lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname[8]
+			&& strncmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name, 8) == 0)
 		{
 			lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1);
 			return lumpnumcache[lumpnumcacheindex].lumpnum;
@@ -1045,13 +1080,63 @@ lumpnum_t W_CheckNumForName(const char *name)
 	{
 		// Update the cache.
 		lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1);
-		strlcpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 32);
+		memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', 32);
+		strncpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 8);
 		lumpnumcache[lumpnumcacheindex].lumpnum = (i<<16)+check;
 
 		return lumpnumcache[lumpnumcacheindex].lumpnum;
 	}
 }
 
+//
+// Like W_CheckNumForName, but can find entries with long names
+//
+// Should be the only version, but that's not possible until we fix
+// all the instances of non null-terminated strings in the codebase...
+//
+lumpnum_t W_CheckNumForLongName(const char *name)
+{
+	INT32 i;
+	lumpnum_t check = INT16_MAX;
+
+	if (!*name) // some doofus gave us an empty string?
+		return LUMPERROR;
+
+	// Check the lumpnumcache first. Loop backwards so that we check
+	// most recent entries first
+	for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--)
+	{
+		if (strcmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0)
+		{
+			lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1);
+			return lumpnumcache[lumpnumcacheindex].lumpnum;
+		}
+	}
+
+	// scan wad files backwards so patch lump files take precedence
+	for (i = numwadfiles - 1; i >= 0; i--)
+	{
+		check = W_CheckNumForLongNamePwad(name,(UINT16)i,0);
+		if (check != INT16_MAX)
+			break; //found it
+	}
+
+	if (check == INT16_MAX) return LUMPERROR;
+	else
+	{
+		if (strlen(name) < 32)
+		{
+			// Update the cache.
+			lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1);
+			memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', 32);
+			strlcpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 32);
+			lumpnumcache[lumpnumcacheindex].lumpnum = (i << 16) + check;
+		}
+
+		return (i << 16) + check;
+	}
+}
+
 // Look for valid map data through all added files in descendant order.
 // Get a map marker for WADs, and a standalone WAD file lump inside PK3s.
 // TODO: Make it search through cache first, maybe...?
@@ -1100,6 +1185,24 @@ lumpnum_t W_GetNumForName(const char *name)
 	return i;
 }
 
+//
+// Like W_GetNumForName, but can find entries with long names
+//
+// Should be the only version, but that's not possible until we fix
+// all the instances of non null-terminated strings in the codebase...
+//
+lumpnum_t W_GetNumForLongName(const char *name)
+{
+	lumpnum_t i;
+
+	i = W_CheckNumForLongName(name);
+
+	if (i == LUMPERROR)
+		I_Error("W_GetNumForLongName: %s not found!\n", name);
+
+	return i;
+}
+
 //
 // W_CheckNumForNameInBlock
 // Checks only in blocks from blockstart lump to blockend lump
@@ -1139,7 +1242,7 @@ UINT8 W_LumpExists(const char *name)
 	{
 		lumpinfo_t *lump_p = wadfiles[i]->lumpinfo;
 		for (j = 0; j < wadfiles[i]->numlumps; ++j, ++lump_p)
-			if (fastcmp(lump_p->name,name))
+			if (fastcmp(lump_p->longname, name))
 				return true;
 	}
 	return false;
@@ -1680,6 +1783,17 @@ void *W_CachePatchName(const char *name, INT32 tag)
 		return W_CachePatchNum(W_GetNumForName("MISSING"), tag);
 	return W_CachePatchNum(num, tag);
 }
+
+void *W_CachePatchLongName(const char *name, INT32 tag)
+{
+	lumpnum_t num;
+
+	num = W_CheckNumForLongName(name);
+
+	if (num == LUMPERROR)
+		return W_CachePatchNum(W_GetNumForLongName("MISSING"), tag);
+	return W_CachePatchNum(num, tag);
+}
 #ifndef NOMD5
 #define MD5_LEN 16
 
diff --git a/src/w_wad.h b/src/w_wad.h
index 3af6148f4..88b542fca 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -156,6 +156,7 @@ const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
 const char *W_CheckNameForNum(lumpnum_t lumpnum);
 
 UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump); // checks only in one pwad
+UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump);
 
 /* Find the first lump after F_START for instance. */
 UINT16 W_CheckNumForMarkerStartPwad(const char *name, UINT16 wad, UINT16 startlump);
@@ -166,7 +167,9 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
 
 lumpnum_t W_CheckNumForMap(const char *name);
 lumpnum_t W_CheckNumForName(const char *name);
+lumpnum_t W_CheckNumForLongName(const char *name);
 lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR
+lumpnum_t W_GetNumForLongName(const char *name);
 lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend);
 UINT8 W_LumpExists(const char *name); // Lua uses this.
 
@@ -194,6 +197,7 @@ boolean W_IsPatchCached(lumpnum_t lump, void *ptr);
 
 void *W_CacheLumpName(const char *name, INT32 tag);
 void *W_CachePatchName(const char *name, INT32 tag);
+void *W_CachePatchLongName(const char *name, INT32 tag);
 
 // Returns either a Software patch, or an OpenGL patch.
 // Performs any necessary conversions from PNG images.

From 2e27f32d3e3c7de727867fa0c25f75f0c9ebe698 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Sun, 26 Apr 2020 00:42:17 +0200
Subject: [PATCH 212/251] Replace a few instance of strncpy with strlcpy

---
 src/dehacked.c |  6 ++----
 src/f_finale.c |  4 ++--
 src/m_menu.c   | 14 +++++++-------
 src/m_menu.h   |  2 +-
 src/p_setup.c  |  4 +---
 src/r_data.c   |  5 ++---
 src/v_video.c  |  2 +-
 src/w_wad.c    |  8 +++-----
 src/y_inter.c  |  5 ++---
 9 files changed, 21 insertions(+), 29 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index e9d029be0..fbd42dee1 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -419,7 +419,7 @@ static void readPlayer(MYFILE *f, INT32 num)
 			if (fastcmp(word, "PICNAME"))
 			{
 				SLOTFOUND
-				strncpy(description[num].picname, word2, 8);
+				strlcpy(description[num].picname, word2, sizeof(description->picname));
 			}
 			// new character select
 			else if (fastcmp(word, "DISPLAYNAME"))
@@ -3889,9 +3889,7 @@ static void readmaincfg(MYFILE *f)
 					lumpnum_t lumpnum;
 					char newname[9];
 
-					strncpy(newname, word2, 8);
-
-					newname[8] = '\0';
+					strlcpy(newname, word2, sizeof(newname));
 
 					lumpnum = W_CheckNumForName(newname);
 
diff --git a/src/f_finale.c b/src/f_finale.c
index 825f646b0..abef1da69 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -2338,7 +2338,7 @@ void F_InitMenuPresValues(void)
 	activeMenuId = MainDef.menuid;
 
 	// Set defaults for presentation values
-	strncpy(curbgname, "TITLESKY", 9);
+	strlcpy(curbgname, "TITLESKY", sizeof(curbgname));
 	curfadevalue = 16;
 	curbgcolor = -1;
 	curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed;
@@ -2348,7 +2348,7 @@ void F_InitMenuPresValues(void)
 	curhidepics = hidetitlepics;
 	curttmode = ttmode;
 	curttscale = ttscale;
-	strncpy(curttname, ttname, 9);
+	strlcpy(curttname, ttname, sizeof(curttname));
 	curttx = ttx;
 	curtty = tty;
 	curttloop = ttloop;
diff --git a/src/m_menu.c b/src/m_menu.c
index 1069f0f30..e510f582a 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -2615,7 +2615,7 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval,
 	}
 	else if (menupres[menutype].bgname[0])
 	{
-		strncpy(curbgname, menupres[menutype].bgname, 8);
+		strlcpy(curbgname, menupres[menutype].bgname, sizeof(curbgname));
 		curbgxspeed = menupres[menutype].titlescrollxspeed != INT32_MAX ? menupres[menutype].titlescrollxspeed : titlescrollxspeed;
 		curbgyspeed = menupres[menutype].titlescrollyspeed != INT32_MAX ? menupres[menutype].titlescrollyspeed : titlescrollyspeed;
 		return true;
@@ -2628,7 +2628,7 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval,
 			curbghide = true;
 		else
 		{
-			strncpy(curbgname, defaultname, 9);
+			strlcpy(curbgname, defaultname, sizeof(curbgname));
 			curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed;
 			curbgyspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollyspeed;
 		}
@@ -2767,7 +2767,7 @@ void M_ChangeMenuMusic(const char *defaultmusname, boolean defaultmuslooping)
 void M_SetMenuCurBackground(const char *defaultname)
 {
 	char name[9];
-	strncpy(name, defaultname, 8);
+	strlcpy(name, defaultname, 9);
 	M_IterateMenuTree(MIT_SetCurBackground, &name);
 }
 
@@ -2820,7 +2820,7 @@ static void M_HandleMenuPresState(menu_t *newMenu)
 	activeMenuId = newMenu ? newMenu->menuid : 0;
 
 	// Set defaults for presentation values
-	strncpy(curbgname, "TITLESKY", 9);
+	strlcpy(curbgname, "TITLESKY", sizeof(curbgname));
 	curfadevalue = 16;
 	curhidepics = hidetitlepics;
 	curbgcolor = -1;
@@ -5785,7 +5785,7 @@ static void M_DrawLevelPlatterMenu(void)
 		{
 			F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
 			// Draw and animate foreground
-			if (!strncmp("RECATKBG", curbgname, 8))
+			if (!strcmp("RECATKBG", curbgname))
 				M_DrawRecordAttackForeground();
 		}
 
@@ -6033,7 +6033,7 @@ static void M_DrawMessageMenu(void)
 			else
 			{
 				F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
-				if (!strncmp("RECATKBG", curbgname, 8))
+				if (!strcmp("RECATKBG", curbgname))
 					M_DrawRecordAttackForeground();
 			}
 		}
@@ -9583,7 +9583,7 @@ void M_DrawTimeAttackMenu(void)
 	{
 		F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
 		// Draw and animate foreground
-		if (!strncmp("RECATKBG", curbgname, 8))
+		if (!strcmp("RECATKBG", curbgname))
 			M_DrawRecordAttackForeground();
 	}
 	if (curfadevalue)
diff --git a/src/m_menu.h b/src/m_menu.h
index eeda9cc58..0658f38da 100644
--- a/src/m_menu.h
+++ b/src/m_menu.h
@@ -340,7 +340,7 @@ typedef struct
 {
 	boolean used;
 	char notes[441];
-	char picname[8];
+	char picname[9];
 	char skinname[SKINNAMESIZE*2+2]; // skin&skin\0
 	patch_t *charpic;
 	UINT8 prev;
diff --git a/src/p_setup.c b/src/p_setup.c
index 8c73b85e6..61a49d958 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -2883,9 +2883,7 @@ static void P_RunLevelScript(const char *scriptname)
 		lumpnum_t lumpnum;
 		char newname[9];
 
-		strncpy(newname, scriptname, 8);
-
-		newname[8] = '\0';
+		strlcpy(newname, scriptname, sizeof(newname));
 
 		lumpnum = W_CheckNumForName(newname);
 
diff --git a/src/r_data.c b/src/r_data.c
index 831e75bef..c542bbd98 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -2603,7 +2603,7 @@ INT32 R_CheckTextureNumForName(const char *name)
 		return 0;
 
 	for (i = 0; i < tidcachelen; i++)
-		if (!strncasecmp(tidcache[i].name, name, 8))
+		if (!strcasecmp(tidcache[i].name, name))
 			return tidcache[i].id;
 
 	// Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier
@@ -2613,8 +2613,7 @@ INT32 R_CheckTextureNumForName(const char *name)
 		{
 			tidcachelen++;
 			Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache);
-			strncpy(tidcache[tidcachelen-1].name, name, 8);
-			tidcache[tidcachelen-1].name[8] = '\0';
+			strlcpy(tidcache[tidcachelen-1].name, name, sizeof(tidcache->name));
 #ifndef ZDEBUG
 			CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name);
 #endif
diff --git a/src/v_video.c b/src/v_video.c
index 2d1014c23..e03d0a60d 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -391,7 +391,7 @@ const char *R_GetPalname(UINT16 num)
 	if (num > 0 && num <= 10000)
 		snprintf(newpal, 8, "PAL%04u", num-1);
 
-	strncpy(palname, newpal, 8);
+	strlcpy(palname, newpal, sizeof(palname));
 	return palname;
 }
 
diff --git a/src/w_wad.c b/src/w_wad.c
index a81132354..267f06198 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -440,17 +440,15 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
 		else
 			lump_p->compression = CM_NOCOMPRESSION;
 		memset(lump_p->name, 0x00, 9);
-		strncpy(lump_p->name, fileinfo->name, 8);
+		strlcpy(lump_p->name, fileinfo->name, 9);
 
 		// Allocate the lump's long name.
 		lump_p->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
-		strncpy(lump_p->longname, fileinfo->name, 8);
-		lump_p->longname[8] = '\0';
+		strlcpy(lump_p->longname, fileinfo->name, 9);
 
 		// Allocate the lump's full name.
 		lump_p->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
-		strncpy(lump_p->fullname, fileinfo->name, 8);
-		lump_p->fullname[8] = '\0';
+		strlcpy(lump_p->fullname, fileinfo->name, 9);
 	}
 	free(fileinfov);
 	*nlmp = numlumps;
diff --git a/src/y_inter.c b/src/y_inter.c
index f1764a816..ce57bef9e 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -1740,9 +1740,8 @@ static void Y_CalculateCompetitionWinners(void)
 		data.competition.monitors[data.competition.numplayers] = monitors[winner];
 		data.competition.scores[data.competition.numplayers] = scores[winner];
 
-		strncpy(tempname, player_names[winner], 8);
-		tempname[8] = '\0';
-		strncpy(data.competition.name[data.competition.numplayers], tempname, 9);
+		strlcpy(tempname, player_names[winner], 9);
+		strlcpy(data.competition.name[data.competition.numplayers], tempname, 9);
 
 		data.competition.color[data.competition.numplayers] = &players[winner].skincolor;
 		data.competition.character[data.competition.numplayers] = &players[winner].skin;

From 295ed303af137464c995efe165d8767d22f89859 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 26 Apr 2020 11:55:10 +0200
Subject: [PATCH 213/251] Make T_StartCrumble use its own thinker data
 structure

---
 src/p_floor.c | 175 +++++++++++++++++++++++++-------------------------
 src/p_map.c   |   4 +-
 src/p_saveg.c |  59 ++++++++++++++++-
 src/p_spec.h  |  20 +++++-
 4 files changed, 164 insertions(+), 94 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 179cf73c7..d0fef319c 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -757,7 +757,7 @@ void T_BounceCheese(bouncecheese_t *bouncer)
 // T_StartCrumble ////////////////////////////////
 //////////////////////////////////////////////////
 // Crumbling platform Tails 03-11-2002
-void T_StartCrumble(elevator_t *elevator)
+void T_StartCrumble(crumble_t *crumble)
 {
 	ffloor_t *rover;
 	sector_t *sector;
@@ -765,42 +765,42 @@ void T_StartCrumble(elevator_t *elevator)
 
 	// Once done, the no-return thinker just sits there,
 	// constantly 'returning'... kind of an oxymoron, isn't it?
-	if (((elevator->floordestheight == 1 && elevator->direction == -1)
-		|| (elevator->floordestheight == 0 && elevator->direction == 1))
-		&& elevator->type == elevateContinuous) // No return crumbler
+	if (((crumble->floordestheight == 1 && crumble->direction == -1)
+		|| (crumble->floordestheight == 0 && crumble->direction == 1))
+		&& crumble->type == elevateContinuous) // No return crumbler
 	{
-		elevator->sector->ceilspeed = 0;
-		elevator->sector->floorspeed = 0;
+		crumble->sector->ceilspeed = 0;
+		crumble->sector->floorspeed = 0;
 		return;
 	}
 
-	if (elevator->distance != 0)
+	if (crumble->distance != 0)
 	{
-		if (elevator->distance > 0) // Count down the timer
+		if (crumble->distance > 0) // Count down the timer
 		{
-			elevator->distance--;
-			if (elevator->distance <= 0)
-				elevator->distance = -15*TICRATE; // Timer until platform returns to original position.
+			crumble->distance--;
+			if (crumble->distance <= 0)
+				crumble->distance = -15*TICRATE; // Timer until platform returns to original position.
 			else
 			{
 				// Timer isn't up yet, so just keep waiting.
-				elevator->sector->ceilspeed = 0;
-				elevator->sector->floorspeed = 0;
+				crumble->sector->ceilspeed = 0;
+				crumble->sector->floorspeed = 0;
 				return;
 			}
 		}
-		else if (++elevator->distance == 0) // Reposition back to original spot
+		else if (++crumble->distance == 0) // Reposition back to original spot
 		{
-			for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+			for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
 			{
 				sector = &sectors[i];
 
 				for (rover = sector->ffloors; rover; rover = rover->next)
 				{
 					if (rover->flags & FF_CRUMBLE && rover->flags & FF_FLOATBOB
-						&& rover->master == elevator->sourceline)
+						&& rover->master == crumble->sourceline)
 					{
-						rover->alpha = elevator->origspeed;
+						rover->alpha = crumble->origspeed;
 
 						if (rover->alpha == 0xff)
 							rover->flags &= ~FF_TRANSLUCENT;
@@ -809,39 +809,39 @@ void T_StartCrumble(elevator_t *elevator)
 			}
 
 			// Up!
-			if (elevator->floordestheight == 1)
-				elevator->direction = -1;
+			if (crumble->floordestheight == 1)
+				crumble->direction = -1;
 			else
-				elevator->direction = 1;
+				crumble->direction = 1;
 
-			elevator->sector->ceilspeed = 0;
-			elevator->sector->floorspeed = 0;
+			crumble->sector->ceilspeed = 0;
+			crumble->sector->floorspeed = 0;
 			return;
 		}
 
 		// Flash to indicate that the platform is about to return.
-		if (elevator->distance > -224 && (leveltime % ((abs(elevator->distance)/8) + 1) == 0))
+		if (crumble->distance > -224 && (leveltime % ((abs(crumble->distance)/8) + 1) == 0))
 		{
-			for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+			for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
 			{
 				sector = &sectors[i];
 
 				for (rover = sector->ffloors; rover; rover = rover->next)
 				{
 					if (!(rover->flags & FF_NORETURN) && rover->flags & FF_CRUMBLE && rover->flags & FF_FLOATBOB
-						&& rover->master == elevator->sourceline)
+						&& rover->master == crumble->sourceline)
 					{
-						if (rover->alpha == elevator->origspeed)
+						if (rover->alpha == crumble->origspeed)
 						{
 							rover->flags |= FF_TRANSLUCENT;
 							rover->alpha = 0x00;
 						}
 						else
 						{
-							if (elevator->origspeed == 0xff)
+							if (crumble->origspeed == 0xff)
 								rover->flags &= ~FF_TRANSLUCENT;
 
-							rover->alpha = elevator->origspeed;
+							rover->alpha = crumble->origspeed;
 						}
 					}
 				}
@@ -851,74 +851,74 @@ void T_StartCrumble(elevator_t *elevator)
 		// We're about to go back to the original position,
 		// so set this to let other thinkers know what is
 		// about to happen.
-		if (elevator->distance < 0 && elevator->distance > -3)
-			elevator->sector->crumblestate = CRUMBLE_RESTORE; // makes T_BounceCheese remove itself
+		if (crumble->distance < 0 && crumble->distance > -3)
+			crumble->sector->crumblestate = CRUMBLE_RESTORE; // makes T_BounceCheese remove itself
 	}
 
-	if ((elevator->floordestheight == 0 && elevator->direction == -1)
-		|| (elevator->floordestheight == 1 && elevator->direction == 1)) // Down
+	if ((crumble->floordestheight == 0 && crumble->direction == -1)
+		|| (crumble->floordestheight == 1 && crumble->direction == 1)) // Down
 	{
-		elevator->sector->crumblestate = CRUMBLE_FALL; // Allow floating now.
+		crumble->sector->crumblestate = CRUMBLE_FALL; // Allow floating now.
 
 		// Only fall like this if it isn't meant to float on water
-		if (elevator->high != 42)
+		if (crumble->high != 42)
 		{
-			elevator->speed += gravity; // Gain more and more speed
+			crumble->speed += gravity; // Gain more and more speed
 
-			if ((elevator->floordestheight == 0 && !(elevator->sector->ceilingheight < -16384*FRACUNIT))
-				|| (elevator->floordestheight == 1 && !(elevator->sector->ceilingheight > 16384*FRACUNIT)))
+			if ((crumble->floordestheight == 0 && !(crumble->sector->ceilingheight < -16384*FRACUNIT))
+				|| (crumble->floordestheight == 1 && !(crumble->sector->ceilingheight > 16384*FRACUNIT)))
 			{
 				fixed_t dest;
 
-				if (elevator->floordestheight == 1)
-					dest = elevator->sector->ceilingheight + (elevator->speed*2);
+				if (crumble->floordestheight == 1)
+					dest = crumble->sector->ceilingheight + (crumble->speed*2);
 				else
-					dest = elevator->sector->ceilingheight - (elevator->speed*2);
+					dest = crumble->sector->ceilingheight - (crumble->speed*2);
 
 				T_MovePlane             //jff 4/7/98 reverse order of ceiling/floor
 				(
-				  elevator->sector,
-				  elevator->speed,
+				  crumble->sector,
+				  crumble->speed,
 				  dest,
 				  false,
 				  true, // move ceiling
-				  elevator->direction
+				  crumble->direction
 				);
 
-				if (elevator->floordestheight == 1)
-					dest = elevator->sector->floorheight + (elevator->speed*2);
+				if (crumble->floordestheight == 1)
+					dest = crumble->sector->floorheight + (crumble->speed*2);
 				else
-					dest = elevator->sector->floorheight - (elevator->speed*2);
+					dest = crumble->sector->floorheight - (crumble->speed*2);
 
 				  T_MovePlane
 				  (
-					elevator->sector,
-					elevator->speed,
+					crumble->sector,
+					crumble->speed,
 					dest,
 					false,
 					false, // move floor
-					elevator->direction
+					crumble->direction
 				);
 
-				elevator->sector->ceilspeed = 42;
-				elevator->sector->floorspeed = elevator->speed*elevator->direction;
+				crumble->sector->ceilspeed = 42;
+				crumble->sector->floorspeed = crumble->speed*crumble->direction;
 			}
 		}
 	}
 	else // Up (restore to original position)
 	{
-		elevator->sector->crumblestate = CRUMBLE_WAIT;
-		elevator->sector->ceilingheight = elevator->ceilingwasheight;
-		elevator->sector->floorheight = elevator->floorwasheight;
-		elevator->sector->floordata = NULL;
-		elevator->sector->ceilingdata = NULL;
-		elevator->sector->ceilspeed = 0;
-		elevator->sector->floorspeed = 0;
-		elevator->sector->moved = true;
-		P_RemoveThinker(&elevator->thinker);
+		crumble->sector->crumblestate = CRUMBLE_WAIT;
+		crumble->sector->ceilingheight = crumble->ceilingwasheight;
+		crumble->sector->floorheight = crumble->floorwasheight;
+		crumble->sector->floordata = NULL;
+		crumble->sector->ceilingdata = NULL;
+		crumble->sector->ceilspeed = 0;
+		crumble->sector->floorspeed = 0;
+		crumble->sector->moved = true;
+		P_RemoveThinker(&crumble->thinker);
 	}
 
-	for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+	for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
 	{
 		sector = &sectors[i];
 		sector->moved = true;
@@ -2309,7 +2309,7 @@ void EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boole
 INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
 	player_t *player, fixed_t origalpha, boolean crumblereturn)
 {
-	elevator_t *elevator;
+	crumble_t *crumble;
 	sector_t *foundsec;
 	INT32 i;
 
@@ -2320,55 +2320,54 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
 	if (sec->crumblestate >= CRUMBLE_ACTIVATED)
 		return 0;
 
-	// create and initialize new elevator thinker
-	elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
-	P_AddThinker(THINK_MAIN, &elevator->thinker);
-	elevator->thinker.function.acp1 = (actionf_p1)T_StartCrumble;
+	// create and initialize new crumble thinker
+	crumble = Z_Calloc(sizeof (*crumble), PU_LEVSPEC, NULL);
+	P_AddThinker(THINK_MAIN, &crumble->thinker);
+	crumble->thinker.function.acp1 = (actionf_p1)T_StartCrumble;
 
 	// Does this crumbler return?
 	if (crumblereturn)
-		elevator->type = elevateBounce;
+		crumble->type = elevateBounce;
 	else
-		elevator->type = elevateContinuous;
+		crumble->type = elevateContinuous;
 
-	// set up the fields according to the type of elevator action
-	elevator->sector = sec;
-	elevator->speed = 0;
+	// set up the fields
+	crumble->sector = sec;
+	crumble->speed = 0;
 
 	if (player && player->mo && (player->mo->eflags & MFE_VERTICALFLIP))
 	{
-		elevator->direction = 1; // Up
-		elevator->floordestheight = 1;
+		crumble->direction = 1; // Up
+		crumble->floordestheight = 1;
 	}
 	else
 	{
-		elevator->direction = -1; // Down
-		elevator->floordestheight = 0;
+		crumble->direction = -1; // Down
+		crumble->floordestheight = 0;
 	}
 
-	elevator->floorwasheight = elevator->sector->floorheight;
-	elevator->ceilingwasheight = elevator->sector->ceilingheight;
-	elevator->distance = TICRATE; // Used for delay time
-	elevator->low = 0;
-	elevator->player = player;
-	elevator->origspeed = origalpha;
+	crumble->floorwasheight = crumble->sector->floorheight;
+	crumble->ceilingwasheight = crumble->sector->ceilingheight;
+	crumble->distance = TICRATE; // Used for delay time
+	crumble->player = player;
+	crumble->origspeed = origalpha;
 
-	elevator->sourceline = rover->master;
+	crumble->sourceline = rover->master;
 
-	sec->floordata = elevator;
+	sec->floordata = crumble;
 
 	if (floating)
-		elevator->high = 42;
+		crumble->high = 42;
 	else
-		elevator->high = 0;
+		crumble->high = 0;
 
-	elevator->sector->crumblestate = CRUMBLE_ACTIVATED;
+	crumble->sector->crumblestate = CRUMBLE_ACTIVATED;
 
-	for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;)
+	for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
 	{
 		foundsec = &sectors[i];
 
-		P_SpawnMobj(foundsec->soundorg.x, foundsec->soundorg.y, elevator->direction == 1 ? elevator->sector->floorheight : elevator->sector->ceilingheight, MT_CRUMBLEOBJ);
+		P_SpawnMobj(foundsec->soundorg.x, foundsec->soundorg.y, crumble->direction == 1 ? crumble->sector->floorheight : crumble->sector->ceilingheight, MT_CRUMBLEOBJ);
 	}
 
 	return 1;
diff --git a/src/p_map.c b/src/p_map.c
index accc52836..2b6623f71 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -4223,14 +4223,14 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
 					{
 						//If the thing was crushed by a crumbling FOF, reward the player who made it crumble!
 						thinker_t *think;
-						elevator_t *crumbler;
+						crumble_t *crumbler;
 
 						for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
 						{
 							if (think->function.acp1 != (actionf_p1)T_StartCrumble)
 								continue;
 
-							crumbler = (elevator_t *)think;
+							crumbler = (crumble_t *)think;
 
 							if (crumbler->player && crumbler->player->mo
 								&& crumbler->player->mo != thing
diff --git a/src/p_saveg.c b/src/p_saveg.c
index f6e31fc3a..5032cfc75 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1930,6 +1930,30 @@ static void SaveElevatorThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveLine(ht->sourceline));
 }
 
+//
+// SaveCrumbleThinker
+//
+// Saves a crumble_t thinker
+//
+static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type)
+{
+	const crumble_t *ht = (const void *)th;
+	WRITEUINT8(save_p, type);
+	WRITEUINT8(save_p, ht->type);
+	WRITEUINT32(save_p, SaveSector(ht->sector));
+	WRITEUINT32(save_p, SaveSector(ht->actionsector));
+	WRITEINT32(save_p, ht->direction);
+	WRITEFIXED(save_p, ht->floordestheight);
+	WRITEFIXED(save_p, ht->speed);
+	WRITEFIXED(save_p, ht->origspeed);
+	WRITEFIXED(save_p, ht->high);
+	WRITEFIXED(save_p, ht->distance);
+	WRITEFIXED(save_p, ht->floorwasheight);
+	WRITEFIXED(save_p, ht->ceilingwasheight);
+	WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy
+	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+}
+
 //
 // SaveScrollThinker
 //
@@ -2377,7 +2401,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_CameraScanner)
 			{
-				SaveElevatorThinker(th, tc_camerascanner);
+				SaveCrumbleThinker(th, tc_camerascanner);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_Scroll)
@@ -3142,7 +3166,7 @@ static thinker_t* LoadFireflickerThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 //
-// LoadElevatorThinker
+// +vatorThinker
 //
 // Loads a elevator_t from a save game
 //
@@ -3179,6 +3203,35 @@ static thinker_t* LoadElevatorThinker(actionf_p1 thinker, UINT8 floorOrCeiling)
 	return &ht->thinker;
 }
 
+//
+// LoadCrumbleThinker
+//
+// Loads a crumble_t from a save game
+//
+static thinker_t* LoadCrumbleThinker(actionf_p1 thinker)
+{
+	crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ht->thinker.function.acp1 = thinker;
+	ht->type = READUINT8(save_p);
+	ht->sector = LoadSector(READUINT32(save_p));
+	ht->actionsector = LoadSector(READUINT32(save_p));
+	ht->direction = READINT32(save_p);
+	ht->floordestheight = READFIXED(save_p);
+	ht->speed = READFIXED(save_p);
+	ht->origspeed = READFIXED(save_p);
+	ht->high = READFIXED(save_p);
+	ht->distance = READFIXED(save_p);
+	ht->floorwasheight = READFIXED(save_p);
+	ht->ceilingwasheight = READFIXED(save_p);
+	ht->player = LoadPlayer(READUINT32(save_p)); // was dummy
+	ht->sourceline = LoadLine(READUINT32(save_p));
+
+	if (ht->sector)
+		ht->sector->floordata = ht;
+
+	return &ht->thinker;
+}
+
 //
 // LoadScrollThinker
 //
@@ -3707,7 +3760,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_startcrumble:
-					th = LoadElevatorThinker((actionf_p1)T_StartCrumble, 1);
+					th = LoadCrumbleThinker((actionf_p1)T_StartCrumble);
 					break;
 
 				case tc_marioblock:
diff --git a/src/p_spec.h b/src/p_spec.h
index e243e3a61..7e2a97ce9 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -311,6 +311,24 @@ typedef struct
 	line_t *sourceline;
 } elevator_t;
 
+typedef struct
+{
+	thinker_t thinker;
+	elevator_e type;
+	sector_t *sector;
+	sector_t *actionsector; // The sector the rover action is taking place in.
+	INT32 direction;
+	fixed_t floordestheight;
+	fixed_t speed;
+	fixed_t origspeed;
+	fixed_t high;
+	fixed_t distance;
+	fixed_t floorwasheight; // Height the floor WAS at
+	fixed_t ceilingwasheight; // Height the ceiling WAS at
+	player_t *player; // Player who initiated the thinker (used for airbob)
+	line_t *sourceline;
+} crumble_t;
+
 typedef struct
 {
 	thinker_t thinker;
@@ -440,7 +458,7 @@ void T_MoveFloor(floormove_t *movefloor);
 void T_MoveElevator(elevator_t *elevator);
 void T_ContinuousFalling(continuousfall_t *faller);
 void T_BounceCheese(bouncecheese_t *bouncer);
-void T_StartCrumble(elevator_t *elevator);
+void T_StartCrumble(crumble_t *crumble);
 void T_MarioBlock(mariothink_t *block);
 void T_FloatSector(floatthink_t *floater);
 void T_MarioBlockChecker(mariocheck_t *block);

From 554de0e0f52730a66ec5e05613aaba5c80b68688 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 26 Apr 2020 16:51:14 +0200
Subject: [PATCH 214/251] T_StartCrumble refactoring, part 1

---
 src/p_floor.c | 139 +++++++++++++++++++++++---------------------------
 src/p_map.c   |   4 +-
 src/p_saveg.c |  24 ++++-----
 src/p_spec.h  |  19 ++++---
 4 files changed, 88 insertions(+), 98 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index d0fef319c..220202d07 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -765,22 +765,21 @@ void T_StartCrumble(crumble_t *crumble)
 
 	// Once done, the no-return thinker just sits there,
 	// constantly 'returning'... kind of an oxymoron, isn't it?
-	if (((crumble->floordestheight == 1 && crumble->direction == -1)
-		|| (crumble->floordestheight == 0 && crumble->direction == 1))
-		&& crumble->type == elevateContinuous) // No return crumbler
+	if ((((crumble->flags & CF_REVERSE) && crumble->direction == -1)
+		|| (!(crumble->flags & CF_REVERSE) && crumble->direction == 1))
+		&& !(crumble->flags & CF_RETURN))
 	{
 		crumble->sector->ceilspeed = 0;
 		crumble->sector->floorspeed = 0;
 		return;
 	}
 
-	if (crumble->distance != 0)
+	if (crumble->timer != 0)
 	{
-		if (crumble->distance > 0) // Count down the timer
+		if (crumble->timer > 0) // Count down the timer
 		{
-			crumble->distance--;
-			if (crumble->distance <= 0)
-				crumble->distance = -15*TICRATE; // Timer until platform returns to original position.
+			if (--crumble->timer <= 0)
+				crumble->timer = -15*TICRATE; // Timer until platform returns to original position.
 			else
 			{
 				// Timer isn't up yet, so just keep waiting.
@@ -789,7 +788,7 @@ void T_StartCrumble(crumble_t *crumble)
 				return;
 			}
 		}
-		else if (++crumble->distance == 0) // Reposition back to original spot
+		else if (++crumble->timer == 0) // Reposition back to original spot
 		{
 			for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
 			{
@@ -797,19 +796,24 @@ void T_StartCrumble(crumble_t *crumble)
 
 				for (rover = sector->ffloors; rover; rover = rover->next)
 				{
-					if (rover->flags & FF_CRUMBLE && rover->flags & FF_FLOATBOB
-						&& rover->master == crumble->sourceline)
-					{
-						rover->alpha = crumble->origspeed;
+					if (!(rover->flags & FF_CRUMBLE))
+						continue;
 
-						if (rover->alpha == 0xff)
-							rover->flags &= ~FF_TRANSLUCENT;
-					}
+					if (!(rover->flags & FF_FLOATBOB))
+						continue;
+
+					if (rover->master != crumble->sourceline)
+						continue;
+
+					rover->alpha = crumble->origalpha;
+
+					if (rover->alpha == 0xff)
+						rover->flags &= ~FF_TRANSLUCENT;
 				}
 			}
 
 			// Up!
-			if (crumble->floordestheight == 1)
+			if (crumble->flags & CF_REVERSE)
 				crumble->direction = -1;
 			else
 				crumble->direction = 1;
@@ -820,7 +824,7 @@ void T_StartCrumble(crumble_t *crumble)
 		}
 
 		// Flash to indicate that the platform is about to return.
-		if (crumble->distance > -224 && (leveltime % ((abs(crumble->distance)/8) + 1) == 0))
+		if (crumble->timer > -224 && (leveltime % ((abs(crumble->timer)/8) + 1) == 0))
 		{
 			for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;)
 			{
@@ -828,21 +832,29 @@ void T_StartCrumble(crumble_t *crumble)
 
 				for (rover = sector->ffloors; rover; rover = rover->next)
 				{
-					if (!(rover->flags & FF_NORETURN) && rover->flags & FF_CRUMBLE && rover->flags & FF_FLOATBOB
-						&& rover->master == crumble->sourceline)
-					{
-						if (rover->alpha == crumble->origspeed)
-						{
-							rover->flags |= FF_TRANSLUCENT;
-							rover->alpha = 0x00;
-						}
-						else
-						{
-							if (crumble->origspeed == 0xff)
-								rover->flags &= ~FF_TRANSLUCENT;
+					if (rover->flags & FF_NORETURN)
+						continue;
 
-							rover->alpha = crumble->origspeed;
-						}
+					if (!(rover->flags & FF_CRUMBLE))
+						continue;
+
+					if (!(rover->flags & FF_FLOATBOB))
+						continue;
+
+					if (rover->master != crumble->sourceline)
+						continue;
+
+					if (rover->alpha == crumble->origalpha)
+					{
+						rover->flags |= FF_TRANSLUCENT;
+						rover->alpha = 0x00;
+					}
+					else
+					{
+						rover->alpha = crumble->origalpha;
+
+						if (rover->alpha == 0xff)
+							rover->flags &= ~FF_TRANSLUCENT;
 					}
 				}
 			}
@@ -851,53 +863,41 @@ void T_StartCrumble(crumble_t *crumble)
 		// We're about to go back to the original position,
 		// so set this to let other thinkers know what is
 		// about to happen.
-		if (crumble->distance < 0 && crumble->distance > -3)
+		if (crumble->timer < 0 && crumble->timer > -3)
 			crumble->sector->crumblestate = CRUMBLE_RESTORE; // makes T_BounceCheese remove itself
 	}
 
-	if ((crumble->floordestheight == 0 && crumble->direction == -1)
-		|| (crumble->floordestheight == 1 && crumble->direction == 1)) // Down
+	if ((!(crumble->flags & CF_REVERSE) && crumble->direction == -1)
+		|| ((crumble->flags & CF_REVERSE) && crumble->direction == 1)) // Down
 	{
 		crumble->sector->crumblestate = CRUMBLE_FALL; // Allow floating now.
 
 		// Only fall like this if it isn't meant to float on water
-		if (crumble->high != 42)
+		if (!(crumble->flags & CF_FLOATBOB))
 		{
 			crumble->speed += gravity; // Gain more and more speed
 
-			if ((crumble->floordestheight == 0 && !(crumble->sector->ceilingheight < -16384*FRACUNIT))
-				|| (crumble->floordestheight == 1 && !(crumble->sector->ceilingheight > 16384*FRACUNIT)))
+			if ((!(crumble->flags & CF_REVERSE) && crumble->sector->ceilingheight >= -16384*FRACUNIT)
+				|| ((crumble->flags & CF_REVERSE) && crumble->sector->ceilingheight <= 16384*FRACUNIT))
 			{
-				fixed_t dest;
-
-				if (crumble->floordestheight == 1)
-					dest = crumble->sector->ceilingheight + (crumble->speed*2);
-				else
-					dest = crumble->sector->ceilingheight - (crumble->speed*2);
-
 				T_MovePlane             //jff 4/7/98 reverse order of ceiling/floor
 				(
 				  crumble->sector,
 				  crumble->speed,
-				  dest,
+				  crumble->sector->ceilingheight + crumble->direction*crumble->speed*2,
 				  false,
 				  true, // move ceiling
 				  crumble->direction
 				);
 
-				if (crumble->floordestheight == 1)
-					dest = crumble->sector->floorheight + (crumble->speed*2);
-				else
-					dest = crumble->sector->floorheight - (crumble->speed*2);
-
-				  T_MovePlane
-				  (
-					crumble->sector,
-					crumble->speed,
-					dest,
-					false,
-					false, // move floor
-					crumble->direction
+				T_MovePlane
+				(
+				  crumble->sector,
+				  crumble->speed,
+				  crumble->sector->floorheight + crumble->direction*crumble->speed*2,
+				  false,
+				  false, // move floor
+				  crumble->direction
 				);
 
 				crumble->sector->ceilspeed = 42;
@@ -2325,12 +2325,6 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
 	P_AddThinker(THINK_MAIN, &crumble->thinker);
 	crumble->thinker.function.acp1 = (actionf_p1)T_StartCrumble;
 
-	// Does this crumbler return?
-	if (crumblereturn)
-		crumble->type = elevateBounce;
-	else
-		crumble->type = elevateContinuous;
-
 	// set up the fields
 	crumble->sector = sec;
 	crumble->speed = 0;
@@ -2338,28 +2332,25 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
 	if (player && player->mo && (player->mo->eflags & MFE_VERTICALFLIP))
 	{
 		crumble->direction = 1; // Up
-		crumble->floordestheight = 1;
+		crumble->flags |= CF_REVERSE;
 	}
 	else
-	{
 		crumble->direction = -1; // Down
-		crumble->floordestheight = 0;
-	}
 
 	crumble->floorwasheight = crumble->sector->floorheight;
 	crumble->ceilingwasheight = crumble->sector->ceilingheight;
-	crumble->distance = TICRATE; // Used for delay time
+	crumble->timer = TICRATE;
 	crumble->player = player;
-	crumble->origspeed = origalpha;
+	crumble->origalpha = origalpha;
 
 	crumble->sourceline = rover->master;
 
 	sec->floordata = crumble;
 
+	if (crumblereturn)
+		crumble->flags |= CF_RETURN;
 	if (floating)
-		crumble->high = 42;
-	else
-		crumble->high = 0;
+		crumble->flags |= CF_FLOATBOB;
 
 	crumble->sector->crumblestate = CRUMBLE_ACTIVATED;
 
diff --git a/src/p_map.c b/src/p_map.c
index 2b6623f71..0c21e3e69 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -4235,9 +4235,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
 							if (crumbler->player && crumbler->player->mo
 								&& crumbler->player->mo != thing
 								&& crumbler->actionsector == thing->subsector->sector
-								&& crumbler->sector == rover->master->frontsector
-								&& (crumbler->type == elevateBounce
-								|| crumbler->type == elevateContinuous))
+								&& crumbler->sector == rover->master->frontsector)
 							{
 								killer = crumbler->player->mo;
 							}
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 5032cfc75..c4830b995 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1939,19 +1939,17 @@ static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type)
 {
 	const crumble_t *ht = (const void *)th;
 	WRITEUINT8(save_p, type);
-	WRITEUINT8(save_p, ht->type);
+	WRITEUINT32(save_p, SaveLine(ht->sourceline));
 	WRITEUINT32(save_p, SaveSector(ht->sector));
 	WRITEUINT32(save_p, SaveSector(ht->actionsector));
+	WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy
 	WRITEINT32(save_p, ht->direction);
-	WRITEFIXED(save_p, ht->floordestheight);
+	WRITEINT32(save_p, ht->origalpha);
+	WRITEINT32(save_p, ht->timer);
 	WRITEFIXED(save_p, ht->speed);
-	WRITEFIXED(save_p, ht->origspeed);
-	WRITEFIXED(save_p, ht->high);
-	WRITEFIXED(save_p, ht->distance);
 	WRITEFIXED(save_p, ht->floorwasheight);
 	WRITEFIXED(save_p, ht->ceilingwasheight);
-	WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+	WRITEUINT8(save_p, ht->flags);
 }
 
 //
@@ -3212,19 +3210,17 @@ static thinker_t* LoadCrumbleThinker(actionf_p1 thinker)
 {
 	crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->type = READUINT8(save_p);
+	ht->sourceline = LoadLine(READUINT32(save_p));
 	ht->sector = LoadSector(READUINT32(save_p));
 	ht->actionsector = LoadSector(READUINT32(save_p));
+	ht->player = LoadPlayer(READUINT32(save_p));
 	ht->direction = READINT32(save_p);
-	ht->floordestheight = READFIXED(save_p);
+	ht->origalpha = READINT32(save_p);
+	ht->timer = READINT32(save_p);
 	ht->speed = READFIXED(save_p);
-	ht->origspeed = READFIXED(save_p);
-	ht->high = READFIXED(save_p);
-	ht->distance = READFIXED(save_p);
 	ht->floorwasheight = READFIXED(save_p);
 	ht->ceilingwasheight = READFIXED(save_p);
-	ht->player = LoadPlayer(READUINT32(save_p)); // was dummy
-	ht->sourceline = LoadLine(READUINT32(save_p));
+	ht->flags = READUINT8(save_p);
 
 	if (ht->sector)
 		ht->sector->floordata = ht;
diff --git a/src/p_spec.h b/src/p_spec.h
index 7e2a97ce9..c26cb4523 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -311,22 +311,27 @@ typedef struct
 	line_t *sourceline;
 } elevator_t;
 
+typedef enum
+{
+	CF_RETURN   = 1,    // Return after crumbling
+	CF_FLOATBOB = 1<<1, // Float on water
+	CF_REVERSE  = 1<<2, // Reverse gravity
+} crumbleflag_t;
+
 typedef struct
 {
 	thinker_t thinker;
-	elevator_e type;
+	line_t *sourceline;
 	sector_t *sector;
 	sector_t *actionsector; // The sector the rover action is taking place in.
+	player_t *player; // Player who initiated the thinker (used for airbob)
 	INT32 direction;
-	fixed_t floordestheight;
+	INT32 origalpha;
+	INT32 timer;
 	fixed_t speed;
-	fixed_t origspeed;
-	fixed_t high;
-	fixed_t distance;
 	fixed_t floorwasheight; // Height the floor WAS at
 	fixed_t ceilingwasheight; // Height the ceiling WAS at
-	player_t *player; // Player who initiated the thinker (used for airbob)
-	line_t *sourceline;
+	UINT8 flags;
 } crumble_t;
 
 typedef struct

From f4282718dc3a22f5e2f7c1d0356ce3e2289bc232 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 26 Apr 2020 18:31:39 +0200
Subject: [PATCH 215/251] Accidentally changed the wrong SaveElevatorThinker
 call to SaveCrumbleThinker

---
 src/p_saveg.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index c4830b995..74f94590c 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -2399,7 +2399,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_CameraScanner)
 			{
-				SaveCrumbleThinker(th, tc_camerascanner);
+				SaveElevatorThinker(th, tc_camerascanner);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_Scroll)
@@ -2424,7 +2424,7 @@ static void P_NetArchiveThinkers(void)
 			}
 			else if (th->function.acp1 == (actionf_p1)T_StartCrumble)
 			{
-				SaveElevatorThinker(th, tc_startcrumble);
+				SaveCrumbleThinker(th, tc_startcrumble);
 				continue;
 			}
 			else if (th->function.acp1 == (actionf_p1)T_MarioBlock)

From 82bf72f5e1dba7997d4e7be49d190b14b0098950 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 26 Apr 2020 18:38:45 +0200
Subject: [PATCH 216/251] Remove obsolete stuff from elevator_t

---
 src/p_saveg.c | 18 ++++++------------
 src/p_spec.h  |  1 -
 2 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 74f94590c..c04a9ee2d 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1926,7 +1926,6 @@ static void SaveElevatorThinker(const thinker_t *th, const UINT8 type)
 	WRITEFIXED(save_p, ht->delaytimer);
 	WRITEFIXED(save_p, ht->floorwasheight);
 	WRITEFIXED(save_p, ht->ceilingwasheight);
-	WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy
 	WRITEUINT32(save_p, SaveLine(ht->sourceline));
 }
 
@@ -3168,7 +3167,7 @@ static thinker_t* LoadFireflickerThinker(actionf_p1 thinker)
 //
 // Loads a elevator_t from a save game
 //
-static thinker_t* LoadElevatorThinker(actionf_p1 thinker, UINT8 floorOrCeiling)
+static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata)
 {
 	elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
@@ -3187,15 +3186,12 @@ static thinker_t* LoadElevatorThinker(actionf_p1 thinker, UINT8 floorOrCeiling)
 	ht->delaytimer = READFIXED(save_p);
 	ht->floorwasheight = READFIXED(save_p);
 	ht->ceilingwasheight = READFIXED(save_p);
-	ht->player = LoadPlayer(READUINT32(save_p)); // was dummy
 	ht->sourceline = LoadLine(READUINT32(save_p));
 
-	if (ht->sector)
+	if (ht->sector && setplanedata)
 	{
-		if (floorOrCeiling & 2)
-			ht->sector->ceilingdata = ht;
-		if (floorOrCeiling & 1)
-			ht->sector->floordata = ht;
+		ht->sector->ceilingdata = ht;
+		ht->sector->floordata = ht;
 	}
 
 	return &ht->thinker;
@@ -3722,7 +3718,7 @@ static void P_NetUnArchiveThinkers(void)
 					break;
 
 				case tc_elevator:
-					th = LoadElevatorThinker((actionf_p1)T_MoveElevator, 3);
+					th = LoadElevatorThinker((actionf_p1)T_MoveElevator, true);
 					break;
 
 				case tc_continuousfalling:
@@ -3745,10 +3741,8 @@ static void P_NetUnArchiveThinkers(void)
 					th = LoadRaiseThinker((actionf_p1)T_RaiseSector);
 					break;
 
-				/// \todo rewrite all the code that uses an elevator_t but isn't an elevator
-				/// \note working on it!
 				case tc_camerascanner:
-					th = LoadElevatorThinker((actionf_p1)T_CameraScanner, 0);
+					th = LoadElevatorThinker((actionf_p1)T_CameraScanner, false);
 					break;
 
 				case tc_bouncecheese:
diff --git a/src/p_spec.h b/src/p_spec.h
index c26cb4523..f7785125a 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -307,7 +307,6 @@ typedef struct
 	fixed_t delaytimer;
 	fixed_t floorwasheight; // Height the floor WAS at
 	fixed_t ceilingwasheight; // Height the ceiling WAS at
-	player_t *player; // Player who initiated the thinker (used for airbob)
 	line_t *sourceline;
 } elevator_t;
 

From fb1746e95b2a2a2647d8ca2997b655a2d0278f88 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 26 Apr 2020 18:42:31 +0200
Subject: [PATCH 217/251] Deprecate the camera scanner effect and print a
 warning when it's used

---
 src/p_spec.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/p_spec.c b/src/p_spec.c
index 826260d3a..57795f2bf 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6156,6 +6156,8 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto
 {
 	elevator_t *elevator; // Why not? LOL
 
+	CONS_Alert(CONS_WARNING, M_GetText("Detected a camera scanner effect (linedef type 5). This effect is deprecated and will be removed in the future!\n"));
+
 	// create and initialize new elevator thinker
 	elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
 	P_AddThinker(THINK_MAIN, &elevator->thinker);

From c026b707cea12bb1c46ca3ea8af2b888dae6fe57 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 26 Apr 2020 18:54:03 +0200
Subject: [PATCH 218/251] Make new thinker loading functions set
 floordata/ceilingdata where necessary

---
 src/p_saveg.c | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index f6e31fc3a..c5724c15c 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -2892,6 +2892,10 @@ static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker)
 	ht->floorwasheight = READFIXED(save_p);
 	ht->ceilingwasheight = READFIXED(save_p);
 	ht->low = READCHAR(save_p);
+
+	if (ht->sector)
+		ht->sector->ceilingdata = ht;
+
 	return &ht->thinker;
 }
 
@@ -2909,6 +2913,13 @@ static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker)
 	ht->floorstartheight = READFIXED(save_p);
 	ht->ceilingstartheight = READFIXED(save_p);
 	ht->destheight = READFIXED(save_p);
+
+	if (ht->sector)
+	{
+		ht->sector->ceilingdata = ht;
+		ht->sector->floordata = ht;
+	}
+
 	return &ht->thinker;
 }
 
@@ -2926,6 +2937,13 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker)
 	ht->floorstartheight = READFIXED(save_p);
 	ht->ceilingstartheight = READFIXED(save_p);
 	ht->tag = READINT16(save_p);
+
+	if (ht->sector)
+	{
+		ht->sector->ceilingdata = ht;
+		ht->sector->floordata = ht;
+	}
+
 	return &ht->thinker;
 }
 
@@ -2960,6 +2978,13 @@ static thinker_t* LoadThwompThinker(actionf_p1 thinker)
 	ht->delay = READINT32(save_p);
 	ht->tag = READINT16(save_p);
 	ht->sound = READUINT16(save_p);
+
+	if (ht->sector)
+	{
+		ht->sector->ceilingdata = ht;
+		ht->sector->floordata = ht;
+	}
+
 	return &ht->thinker;
 }
 

From 2f9cccf2870a7cab7588c02ba96d78bfc477591a Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 27 Apr 2020 11:19:07 +0200
Subject: [PATCH 219/251] Make P_AddRaiseThinker more configurable via function
 parameters (needed for UDMF)

---
 src/p_spec.c | 56 +++++++++++++++++++++-------------------------------
 1 file changed, 22 insertions(+), 34 deletions(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index 826260d3a..c2fe59ee3 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6013,7 +6013,7 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline)
   * \sa P_SpawnSpecials, T_RaiseSector
   * \author SSNTails <http://www.ssntails.org>
   */
-static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, boolean lower, boolean spindash)
+static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, fixed_t speed, fixed_t ceilingtop, fixed_t ceilingbottom, boolean lower, boolean spindash)
 {
 	raise_t *raise;
 
@@ -6025,10 +6025,10 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, boolean lower,
 	raise->sourceline = sourceline;
 	raise->sector = sec;
 
-	raise->ceilingtop = P_FindHighestCeilingSurrounding(sec);
-	raise->ceilingbottom = P_FindLowestCeilingSurrounding(sec);
+	raise->ceilingtop = ceilingtop;
+	raise->ceilingbottom = ceilingbottom;
 
-	raise->basespeed =  FixedDiv(P_AproxDistance(sourceline->dx, sourceline->dy), 4*FRACUNIT);
+	raise->basespeed =  speed;
 
 	if (lower)
 		raise->flags |= RF_REVERSE;
@@ -6936,44 +6936,32 @@ void P_SpawnSpecials(boolean fromnetsave)
 				break;
 
 			case 190: // Rising Platform FOF (solid, opaque, shadows)
-				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
-				break;
-
 			case 191: // Rising Platform FOF (solid, opaque, no shadows)
-				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_CUTLEVEL, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
-				break;
-
 			case 192: // Rising Platform TL block: FOF (solid, translucent)
-				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
-				break;
-
 			case 193: // Rising Platform FOF (solid, invisible)
-				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_NOSHADE, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
-				break;
-
 			case 194: // Rising Platform 'Platform' - You can jump up through it
-				// If line has no-climb set, don't give it shadows, otherwise do
-				ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_BOTHPLANES|FF_ALLSIDES;
-				if (lines[i].flags & ML_NOCLIMB)
-					ffloorflags |= FF_NOSHADE;
-
-				P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
-				break;
-
 			case 195: // Rising Platform Translucent "platform"
-				// If line has no-climb set, don't give it shadows, otherwise do
-				ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_TRANSLUCENT|FF_BOTHPLANES|FF_ALLSIDES|FF_EXTRA|FF_CUTEXTRA;
-				if (lines[i].flags & ML_NOCLIMB)
-					ffloorflags |= FF_NOSHADE;
+			{
+				fixed_t speed = FixedDiv(P_AproxDistance(lines[i].dx, lines[i].dy), 4*FRACUNIT);
+				fixed_t ceilingtop = P_FindHighestCeilingSurrounding(lines[i].frontsector);
+				fixed_t ceilingbottom = P_FindLowestCeilingSurrounding(lines[i].frontsector);
 
+				ffloorflags = FF_EXISTS|FF_SOLID;
+				if (lines[i].special != 193)
+					ffloorflags |= FF_RENDERALL;
+				if (lines[i].special <= 191)
+					ffloorflags |= FF_CUTLEVEL;
+				if (lines[i].special == 192 || lines[i].special == 195)
+					ffloorflags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA;
+				if (lines[i].special >= 194)
+					ffloorflags |= FF_PLATFORM|FF_BOTHPLANES|FF_ALLSIDES;
+				if (lines[i].special != 190 && (lines[i].special <= 193 || lines[i].flags & ML_NOCLIMB))
+					ffloorflags |= FF_NOSHADE;
 				P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i], !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
+
+				P_AddRaiseThinker(lines[i].frontsector, &lines[i], speed, ceilingtop, ceilingbottom, !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
 				break;
+			}
 
 			case 200: // Double light effect
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_CUTSPRITES|FF_DOUBLESHADOW, secthinkers);

From 556c2a8c185c269b7eab56182b9f28311df9e710 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 27 Apr 2020 12:54:08 +0200
Subject: [PATCH 220/251] Store tag instead of sourceline in raise thinker

---
 src/p_floor.c |  4 ++--
 src/p_saveg.c |  4 ++--
 src/p_spec.c  | 24 +++++++++++-------------
 src/p_spec.h  |  2 +-
 4 files changed, 16 insertions(+), 18 deletions(-)

diff --git a/src/p_floor.c b/src/p_floor.c
index 179cf73c7..97b3af4cc 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1556,7 +1556,7 @@ void T_RaiseSector(raise_t *raise)
 	if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata)
 		return;
 
-	for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->tag, i)) >= 0 ;)
+	for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;)
 	{
 		sector = &sectors[i];
 
@@ -1683,7 +1683,7 @@ void T_RaiseSector(raise_t *raise)
 	raise->sector->ceilspeed = 42;
 	raise->sector->floorspeed = speed*direction;
 
-	for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->tag, i)) >= 0 ;)
+	for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;)
 		P_RecalcPrecipInSector(&sectors[i]);
 }
 
diff --git a/src/p_saveg.c b/src/p_saveg.c
index f6e31fc3a..27f60684a 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1784,7 +1784,7 @@ static void SaveRaiseThinker(const thinker_t *th, const UINT8 type)
 {
 	const raise_t *ht  = (const void *)th;
 	WRITEUINT8(save_p, type);
-	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+	WRITEINT16(save_p, ht->tag);
 	WRITEUINT32(save_p, SaveSector(ht->sector));
 	WRITEFIXED(save_p, ht->ceilingbottom);
 	WRITEFIXED(save_p, ht->ceilingtop);
@@ -3004,7 +3004,7 @@ static thinker_t* LoadRaiseThinker(actionf_p1 thinker)
 {
 	raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
 	ht->thinker.function.acp1 = thinker;
-	ht->sourceline = LoadLine(READUINT32(save_p));
+	ht->tag = READINT16(save_p);
 	ht->sector = LoadSector(READUINT32(save_p));
 	ht->ceilingbottom = READFIXED(save_p);
 	ht->ceilingtop = READFIXED(save_p);
diff --git a/src/p_spec.c b/src/p_spec.c
index c2fe59ee3..a870bf681 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6008,12 +6008,10 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline)
   * there already.
   *
   * \param sec          Control sector.
-  * \param actionsector Target sector.
-  * \param sourceline   Control linedef.
   * \sa P_SpawnSpecials, T_RaiseSector
   * \author SSNTails <http://www.ssntails.org>
   */
-static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, fixed_t speed, fixed_t ceilingtop, fixed_t ceilingbottom, boolean lower, boolean spindash)
+static void P_AddRaiseThinker(sector_t *sec, INT16 tag, fixed_t speed, fixed_t ceilingtop, fixed_t ceilingbottom, boolean lower, boolean spindash)
 {
 	raise_t *raise;
 
@@ -6022,7 +6020,7 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, fixed_t speed,
 
 	raise->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
 
-	raise->sourceline = sourceline;
+	raise->tag = tag;
 	raise->sector = sec;
 
 	raise->ceilingtop = ceilingtop;
@@ -6036,7 +6034,7 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline, fixed_t speed,
 		raise->flags |= RF_SPINDASH;
 }
 
-static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean raise, boolean spindash, boolean dynamic)
+static void P_AddAirbob(sector_t *sec, INT16 tag, fixed_t dist, boolean raise, boolean spindash, boolean dynamic)
 {
 	raise_t *airbob;
 
@@ -6045,7 +6043,7 @@ static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean
 
 	airbob->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
 
-	airbob->sourceline = sourceline;
+	airbob->tag = tag;
 	airbob->sector = sec;
 
 	airbob->ceilingtop = sec->ceilingheight;
@@ -6854,16 +6852,16 @@ void P_SpawnSpecials(boolean fromnetsave)
 			{
 				fixed_t dist = (lines[i].special == 150) ? 16*FRACUNIT : P_AproxDistance(lines[i].dx, lines[i].dy);
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
-				P_AddAirbob(lines[i].frontsector, lines + i, dist, false, !!(lines[i].flags & ML_NOCLIMB), false);
+				P_AddAirbob(lines[i].frontsector, lines[i].tag, dist, false, !!(lines[i].flags & ML_NOCLIMB), false);
 				break;
 			}
 			case 152: // Adjustable air bobbing platform in reverse
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
-				P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), true, !!(lines[i].flags & ML_NOCLIMB), false);
+				P_AddAirbob(lines[i].frontsector, lines[i].tag, P_AproxDistance(lines[i].dx, lines[i].dy), true, !!(lines[i].flags & ML_NOCLIMB), false);
 				break;
 			case 153: // Dynamic Sinking Platform
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
-				P_AddAirbob(lines[i].frontsector, lines + i, P_AproxDistance(lines[i].dx, lines[i].dy), false, !!(lines[i].flags & ML_NOCLIMB), true);
+				P_AddAirbob(lines[i].frontsector, lines[i].tag, P_AproxDistance(lines[i].dx, lines[i].dy), false, !!(lines[i].flags & ML_NOCLIMB), true);
 				break;
 
 			case 160: // Float/bob platform
@@ -6913,13 +6911,13 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 176: // Air bobbing platform that will crumble and bob on the water when it falls and hits
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB|FF_CRUMBLE, secthinkers);
-				P_AddAirbob(lines[i].frontsector, lines + i, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false);
+				P_AddAirbob(lines[i].frontsector, lines[i].tag, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false);
 				break;
 
 			case 177: // Air bobbing platform that will crumble and bob on
 				// the water when it falls and hits, then never return
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB|FF_CRUMBLE|FF_NORETURN, secthinkers);
-				P_AddAirbob(lines[i].frontsector, lines + i, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false);
+				P_AddAirbob(lines[i].frontsector, lines[i].tag, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false);
 				break;
 
 			case 178: // Crumbling platform that will float when it hits water
@@ -6932,7 +6930,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 180: // Air bobbing platform that will crumble
 				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE, secthinkers);
-				P_AddAirbob(lines[i].frontsector, lines + i, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false);
+				P_AddAirbob(lines[i].frontsector, lines[i].tag, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false);
 				break;
 
 			case 190: // Rising Platform FOF (solid, opaque, shadows)
@@ -6959,7 +6957,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 					ffloorflags |= FF_NOSHADE;
 				P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
 
-				P_AddRaiseThinker(lines[i].frontsector, &lines[i], speed, ceilingtop, ceilingbottom, !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
+				P_AddRaiseThinker(lines[i].frontsector, lines[i].tag, speed, ceilingtop, ceilingbottom, !!(lines[i].flags & ML_BLOCKMONSTERS), !!(lines[i].flags & ML_NOCLIMB));
 				break;
 			}
 
diff --git a/src/p_spec.h b/src/p_spec.h
index e243e3a61..d81726b14 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -400,7 +400,7 @@ typedef enum
 typedef struct
 {
 	thinker_t thinker;
-	line_t *sourceline;
+	INT16 tag;
 	sector_t *sector;
 	fixed_t ceilingbottom;
 	fixed_t ceilingtop;

From 630af5d225f796a61ac77224e7822e138a091164 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 27 Apr 2020 13:01:31 +0200
Subject: [PATCH 221/251] Pass thwomp settings to P_AddThwompThinker

---
 src/p_spec.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index a870bf681..19bbdf57e 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6063,12 +6063,10 @@ static void P_AddAirbob(sector_t *sec, INT16 tag, fixed_t dist, boolean raise, b
   * Even thwomps need to think!
   *
   * \param sec          Control sector.
-  * \param actionsector Target sector.
-  * \param sourceline   Control linedef.
   * \sa P_SpawnSpecials, T_ThwompSector
   * \author SSNTails <http://www.ssntails.org>
   */
-static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, line_t *sourceline)
+static inline void P_AddThwompThinker(sector_t *sec, INT16 tag, line_t *sourceline, fixed_t crushspeed, fixed_t retractspeed, UINT16 sound)
 {
 	thwomp_t *thwomp;
 
@@ -6086,14 +6084,14 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin
 	// set up the fields according to the type of elevator action
 	thwomp->sourceline = sourceline;
 	thwomp->sector = sec;
-	thwomp->crushspeed = (sourceline->flags & ML_EFFECT5) ? sourceline->dy >> 3 : 10*FRACUNIT;
-	thwomp->retractspeed = (sourceline->flags & ML_EFFECT5) ? sourceline->dx >> 3 : 2*FRACUNIT;
+	thwomp->crushspeed = crushspeed;
+	thwomp->retractspeed = retractspeed;
 	thwomp->direction = 0;
 	thwomp->floorstartheight = sec->floorheight;
 	thwomp->ceilingstartheight = sec->ceilingheight;
 	thwomp->delay = 1;
-	thwomp->tag = actionsector->tag;
-	thwomp->sound = (sourceline->flags & ML_EFFECT4) ? sides[sourceline->sidenum[0]].textureoffset >> FRACBITS : sfx_thwomp;
+	thwomp->tag = tag;
+	thwomp->sound = sound;
 
 	sec->floordata = thwomp;
 	sec->ceilingdata = thwomp;
@@ -7015,14 +7013,20 @@ void P_SpawnSpecials(boolean fromnetsave)
 				break;
 
 			case 251: // A THWOMP!
+			{
+				fixed_t crushspeed = (lines[i].flags & ML_EFFECT5) ? lines[i].dy >> 3 : 10*FRACUNIT;
+				fixed_t retractspeed = (lines[i].flags & ML_EFFECT5) ? lines[i].dx >> 3 : 2*FRACUNIT;
+				UINT16 sound = (lines[i].flags & ML_EFFECT4) ? sides[lines[i].sidenum[0]].textureoffset >> FRACBITS : sfx_thwomp;
+
 				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 				{
-					P_AddThwompThinker(&sectors[sec], &sectors[s], &lines[i]);
+					P_AddThwompThinker(&sectors[sec], lines[i].tag, &lines[i], crushspeed, retractspeed, sound);
 					P_AddFakeFloor(&sectors[s], &sectors[sec], lines + i,
 						FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers);
 				}
 				break;
+			}
 
 			case 252: // Shatter block (breaks when touched)
 				ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER;

From 4f3d8378355b4b2fefc37fe67362cebff152dfef Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 27 Apr 2020 13:09:57 +0200
Subject: [PATCH 222/251] Store "no bosses" setting for lasers in thinker
 instead of checking sourceline.

---
 src/p_saveg.c |  2 ++
 src/p_spec.c  | 10 +++++-----
 src/p_spec.h  |  1 +
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 27f60684a..6f96cbf0c 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -2003,6 +2003,7 @@ static void SaveLaserThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveSector(ht->sector));
 	WRITEUINT32(save_p, SaveSector(ht->sec));
 	WRITEUINT32(save_p, SaveLine(ht->sourceline));
+	WRITEUINT8(save_p, ht->nobosses);
 }
 
 //
@@ -3257,6 +3258,7 @@ static inline thinker_t* LoadLaserThinker(actionf_p1 thinker)
 	ht->sector = LoadSector(READUINT32(save_p));
 	ht->sec = LoadSector(READUINT32(save_p));
 	ht->sourceline = LoadLine(READUINT32(save_p));
+	ht->nobosses = READUINT8(save_p);
 	for (rover = ht->sector->ffloors; rover; rover = rover->next)
 		if (rover->secnum == (size_t)(ht->sec - sectors)
 		&& rover->master == ht->sourceline)
diff --git a/src/p_spec.c b/src/p_spec.c
index 19bbdf57e..17b4d047e 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6206,8 +6206,7 @@ void T_LaserFlash(laserthink_t *flash)
 	{
 		thing = node->m_thing;
 
-		if ((fflr->master->flags & ML_EFFECT1)
-			&& thing->flags & MF_BOSS)
+		if (flash->nobosses && thing->flags & MF_BOSS)
 			continue; // Don't hurt bosses
 
 		// Don't endlessly kill egg guard shields (or anything else for that matter)
@@ -6236,7 +6235,7 @@ void T_LaserFlash(laserthink_t *flash)
   * \sa T_LaserFlash
   * \author SSNTails <http://www.ssntails.org>
   */
-static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *line, thinkerlist_t *secthinkers)
+static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *line, thinkerlist_t *secthinkers, boolean nobosses)
 {
 	laserthink_t *flash;
 	ffloor_t *fflr = P_AddFakeFloor(sec, sec2, line, laserflags, secthinkers);
@@ -6253,6 +6252,7 @@ static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *lin
 	flash->sector = sec; // For finding mobjs
 	flash->sec = sec2;
 	flash->sourceline = line;
+	flash->nobosses = nobosses;
 }
 
 //
@@ -7068,8 +7068,8 @@ void P_SpawnSpecials(boolean fromnetsave)
 				sec = sides[*lines[i].sidenum].sector - sectors;
 
 				// No longer totally disrupts netgames
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-					EV_AddLaserThinker(&sectors[s], &sectors[sec], lines + i, secthinkers);
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
+					EV_AddLaserThinker(&sectors[s], &sectors[sec], lines + i, secthinkers, !!(lines[i].flags & ML_EFFECT1));
 				break;
 
 			case 259: // Custom FOF
diff --git a/src/p_spec.h b/src/p_spec.h
index d81726b14..53e0076ef 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -108,6 +108,7 @@ typedef struct
 	sector_t *sector;  ///< Sector in which the effect takes place.
 	sector_t *sec;
 	line_t *sourceline;
+	UINT8 nobosses;
 } laserthink_t;
 
 /** Strobe light action structure..

From 0a0812bc57c3dedaa48c0cdb2749f78cd04eb1e9 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 27 Apr 2020 14:31:37 +0200
Subject: [PATCH 223/251] Remove P_FindSectorFromLineTag

---
 src/p_ceilng.c |   4 +-
 src/p_floor.c  |  12 ++---
 src/p_slopes.c |   2 +-
 src/p_spec.c   | 128 +++++++++++++++++++------------------------------
 src/p_spec.h   |   1 -
 5 files changed, 58 insertions(+), 89 deletions(-)

diff --git a/src/p_ceilng.c b/src/p_ceilng.c
index 31a4895ba..3c3c507cd 100644
--- a/src/p_ceilng.c
+++ b/src/p_ceilng.c
@@ -395,7 +395,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
 	sector_t *sec;
 	ceiling_t *ceiling;
 
-	while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
+	while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
 	{
 		sec = &sectors[secnum];
 
@@ -615,7 +615,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
 	sector_t *sec;
 	ceiling_t *ceiling;
 
-	while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
+	while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
 	{
 		sec = &sectors[secnum];
 
diff --git a/src/p_floor.c b/src/p_floor.c
index 97b3af4cc..a4b71d78d 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1284,7 +1284,7 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
 	INT32 secnum = -1;
 	boolean FOFsector = false;
 
-	while ((secnum = P_FindSectorFromLineTag(nobaddies->sourceline, secnum)) >= 0)
+	while ((secnum = P_FindSectorFromTag(nobaddies->sourceline->tag, secnum)) >= 0)
 	{
 		sec = &sectors[secnum];
 
@@ -1300,7 +1300,7 @@ void T_NoEnemiesSector(noenemies_t *nobaddies)
 
 			FOFsector = true;
 
-			while ((targetsecnum = P_FindSectorFromLineTag(sec->lines[i], targetsecnum)) >= 0)
+			while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0)
 			{
 				if (T_SectorHasEnemies(&sectors[targetsecnum]))
 					return;
@@ -1395,7 +1395,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
 		eachtime->playersOnArea[i] = false;
 	}
 
-	while ((secnum = P_FindSectorFromLineTag(eachtime->sourceline, secnum)) >= 0)
+	while ((secnum = P_FindSectorFromTag(eachtime->sourceline->tag, secnum)) >= 0)
 	{
 		sec = &sectors[secnum];
 
@@ -1418,7 +1418,7 @@ void T_EachTimeThinker(eachtime_t *eachtime)
 
 			FOFsector = true;
 
-			while ((targetsecnum = P_FindSectorFromLineTag(sec->lines[i], targetsecnum)) >= 0)
+			while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0)
 			{
 				targetsec = &sectors[targetsecnum];
 
@@ -1801,7 +1801,7 @@ void EV_DoFloor(line_t *line, floor_e floortype)
 	sector_t *sec;
 	floormove_t *dofloor;
 
-	while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
+	while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
 	{
 		sec = &sectors[secnum];
 
@@ -2017,7 +2017,7 @@ void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
 	elevator_t *elevator;
 
 	// act on all sectors with the same tag as the triggering linedef
-	while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
+	while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0)
 	{
 		sec = &sectors[secnum];
 
diff --git a/src/p_slopes.c b/src/p_slopes.c
index 4b5838077..92b40f70f 100644
--- a/src/p_slopes.c
+++ b/src/p_slopes.c
@@ -566,7 +566,7 @@ void P_CopySectorSlope(line_t *line)
 	int i, special = line->special;
 
 	// Check for copy linedefs
-	for (i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;)
+	for (i = -1; (i = P_FindSectorFromTag(line->tag, i)) >= 0;)
 	{
 		sector_t *srcsec = sectors + i;
 
diff --git a/src/p_spec.c b/src/p_spec.c
index 17b4d047e..7074ca4a6 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -987,42 +987,12 @@ static sector_t *P_FindModelCeilingSector(fixed_t ceildestheight, INT32 secnum)
 }
 #endif
 
-/** Searches the tag lists for the next sector tagged to a line.
-  *
-  * \param line  Tagged line used as a reference.
-  * \param start -1 to start at the beginning, or the result of a previous call
-  *              to keep searching.
-  * \return Number of the next tagged sector found.
-  * \sa P_FindSectorFromTag, P_FindLineFromLineTag
-  */
-INT32 P_FindSectorFromLineTag(line_t *line, INT32 start)
-{
-	if (line->tag == -1)
-	{
-		start++;
-
-		if (start >= (INT32)numsectors)
-			return -1;
-
-		return start;
-	}
-	else
-	{
-		start = start >= 0 ? sectors[start].nexttag :
-			sectors[(unsigned)line->tag % numsectors].firsttag;
-		while (start >= 0 && sectors[start].tag != line->tag)
-			start = sectors[start].nexttag;
-		return start;
-	}
-}
-
 /** Searches the tag lists for the next sector with a given tag.
   *
   * \param tag   Tag number to look for.
   * \param start -1 to start anew, or the result of a previous call to keep
   *              searching.
   * \return Number of the next tagged sector found.
-  * \sa P_FindSectorFromLineTag
   */
 INT32 P_FindSectorFromTag(INT16 tag, INT32 start)
 {
@@ -1051,7 +1021,7 @@ INT32 P_FindSectorFromTag(INT16 tag, INT32 start)
   * \param start -1 to start anew, or the result of a previous call to keep
   *              searching.
   * \return Number of the next tagged line found.
-  * \sa P_FindSectorFromLineTag
+  * \sa P_FindSectorFromTag
   */
 static INT32 P_FindLineFromLineTag(const line_t *line, INT32 start)
 {
@@ -2500,7 +2470,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				newceilinglightsec = line->frontsector->ceilinglightsec;
 
 				// act on all sectors with the same tag as the triggering linedef
-				while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
+				while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
 				{
 					if (sectors[secnum].lightingdata)
 					{
@@ -2555,7 +2525,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 		case 409: // Change tagged sectors' tag
 		// (formerly "Change calling sectors' tag", but behavior was changed)
 		{
-			while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
+			while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
 				P_ChangeSectorTag(secnum,(INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS));
 			break;
 		}
@@ -2565,7 +2535,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			break;
 
 		case 411: // Stop floor/ceiling movement in tagged sector(s)
-			while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
+			while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
 			{
 				if (sectors[secnum].floordata)
 				{
@@ -2635,7 +2605,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				}
 				else
 				{
-					if ((secnum = P_FindSectorFromLineTag(line, -1)) < 0)
+					if ((secnum = P_FindSectorFromTag(line->tag, -1)) < 0)
 						return;
 
 					dest = P_GetObjectTypeInSectorNum(MT_TELEPORTMAN, secnum);
@@ -2750,7 +2720,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 						// Additionally play the sound from tagged sectors' soundorgs
 						sector_t *sec;
 
-						while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
+						while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
 						{
 							sec = &sectors[secnum];
 							S_StartSound(&sec->soundorg, sfxnum);
@@ -2865,7 +2835,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			break;
 
 		case 416: // Spawn adjustable fire flicker
-			while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
+			while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
 			{
 				if (line->flags & ML_NOCLIMB && line->backsector)
 				{
@@ -2899,7 +2869,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			break;
 
 		case 417: // Spawn adjustable glowing light
-			while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
+			while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
 			{
 				if (line->flags & ML_NOCLIMB && line->backsector)
 				{
@@ -2933,7 +2903,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			break;
 
 		case 418: // Spawn adjustable strobe flash (unsynchronized)
-			while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
+			while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
 			{
 				if (line->flags & ML_NOCLIMB && line->backsector)
 				{
@@ -2967,7 +2937,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			break;
 
 		case 419: // Spawn adjustable strobe flash (synchronized)
-			while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
+			while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
 			{
 				if (line->flags & ML_NOCLIMB && line->backsector)
 				{
@@ -3015,7 +2985,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			break;
 
 		case 421: // Stop lighting effect in tagged sectors
-			while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
+			while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
 				if (sectors[secnum].lightingdata)
 				{
 					P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker);
@@ -3030,7 +3000,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				if ((!mo || !mo->player) && !titlemapinaction) // only players have views, and title screens
 					return;
 
-				if ((secnum = P_FindSectorFromLineTag(line, -1)) < 0)
+				if ((secnum = P_FindSectorFromTag(line->tag, -1)) < 0)
 					return;
 
 				altview = P_GetObjectTypeInSectorNum(MT_ALTVIEWMAN, secnum);
@@ -3349,7 +3319,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			if (line->sidenum[1] != 0xffff)
 				state = (statenum_t)sides[line->sidenum[1]].toptexture;
 
-			while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
+			while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0)
 			{
 				boolean tryagain;
 				sec = sectors + secnum;
@@ -3504,7 +3474,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			// Except it is activated by linedef executor, not level load
 			// This could even override existing colormaps I believe
 			// -- Monster Iestyn 14/06/18
-			for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;)
+			for (secnum = -1; (secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0 ;)
 			{
 				P_ResetColormapFader(&sectors[secnum]);
 
@@ -3832,7 +3802,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 		}
 
 		case 455: // Fade colormap
-			for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;)
+			for (secnum = -1; (secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0 ;)
 			{
 				extracolormap_t *source_exc, *dest_exc, *exc;
 				INT32 speed = (INT32)((line->flags & ML_DONTPEGBOTTOM) || !sides[line->sidenum[0]].rowoffset) && line->sidenum[1] != 0xFFFF ?
@@ -3921,7 +3891,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			break;
 
 		case 456: // Stop fade colormap
-			for (secnum = -1; (secnum = P_FindSectorFromLineTag(line, secnum)) >= 0 ;)
+			for (secnum = -1; (secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0 ;)
 				P_ResetColormapFader(&sectors[secnum]);
 			break;
 
@@ -3935,7 +3905,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				boolean persist = (line->flags & ML_EFFECT2);
 				mobj_t *anchormo;
 
-				if ((secnum = P_FindSectorFromLineTag(line, -1)) < 0)
+				if ((secnum = P_FindSectorFromTag(line->tag, -1)) < 0)
 					return;
 
 				anchormo = P_GetObjectTypeInSectorNum(MT_ANGLEMAN, secnum);
@@ -6473,7 +6443,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 1: // Definable gravity per sector
 				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 				{
 					sectors[s].gravity = &sectors[sec].floorheight; // This allows it to change in realtime!
 
@@ -6497,7 +6467,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 5: // Change camera info
 				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					P_AddCameraScanner(&sectors[sec], &sectors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y));
 				break;
 
@@ -6524,7 +6494,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 						P_ApplyFlatAlignment(lines + i, lines[i].frontsector, flatangle, xoffs, yoffs);
 					else
 					{
-						for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0;)
+						for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0;)
 							P_ApplyFlatAlignment(lines + i, sectors + s, flatangle, xoffs, yoffs);
 					}
 				}
@@ -6535,7 +6505,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 				break;
 
 			case 8: // Sector Parameters
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 				{
 					if (lines[i].flags & ML_NOCLIMB)
 					{
@@ -6563,7 +6533,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 10: // Vertical culling plane for sprites and FOFs
 				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					sectors[s].cullheight = &lines[i]; // This allows it to change in realtime!
 				break;
 
@@ -6624,13 +6594,13 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 63: // support for drawn heights coming from different sector
 				sec = sides[*lines[i].sidenum].sector-sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					sectors[s].heightsec = (INT32)sec;
 				break;
 
 			case 64: // Appearing/Disappearing FOF option
 				if (lines[i].flags & ML_BLOCKMONSTERS) { // Find FOFs by control sector tag
-					for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+					for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 						for (j = 0; (unsigned)j < sectors[s].linecount; j++)
 							if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300)
 								Add_MasterDisappearer(abs(lines[i].dx>>FRACBITS), abs(lines[i].dy>>FRACBITS), abs(sides[lines[i].sidenum[0]].sector->floorheight>>FRACBITS), (INT32)(sectors[s].lines[j]-lines), (INT32)i);
@@ -6645,15 +6615,15 @@ void P_SpawnSpecials(boolean fromnetsave)
 				break;
 
 			case 66: // Displace floor by front sector
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					P_AddPlaneDisplaceThinker(pd_floor, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB));
 				break;
 			case 67: // Displace ceiling by front sector
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					P_AddPlaneDisplaceThinker(pd_ceiling, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB));
 				break;
 			case 68: // Displace both floor AND ceiling by front sector
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					P_AddPlaneDisplaceThinker(pd_both, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB));
 				break;
 
@@ -7255,46 +7225,46 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 			case 600: // floor lighting independently (e.g. lava)
 				sec = sides[*lines[i].sidenum].sector-sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					sectors[s].floorlightsec = (INT32)sec;
 				break;
 
 			case 601: // ceiling lighting independently
 				sec = sides[*lines[i].sidenum].sector-sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					sectors[s].ceilinglightsec = (INT32)sec;
 				break;
 
 			case 602: // Adjustable pulsating light
 				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					P_SpawnAdjustableGlowingLight(&sectors[sec], &sectors[s],
 						P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS);
 				break;
 
 			case 603: // Adjustable flickering light
 				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					P_SpawnAdjustableFireFlicker(&sectors[sec], &sectors[s],
 						P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS);
 				break;
 
 			case 604: // Adjustable Blinking Light (unsynchronized)
 				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					P_SpawnAdjustableStrobeFlash(&sectors[sec], &sectors[s],
 						abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, false);
 				break;
 
 			case 605: // Adjustable Blinking Light (synchronized)
 				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					P_SpawnAdjustableStrobeFlash(&sectors[sec], &sectors[s],
 						abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, true);
 				break;
 
 			case 606: // HACK! Copy colormaps. Just plain colormaps.
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;)
 					sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = sides[lines[i].sidenum[0]].colormap_data;
 				break;
 
@@ -7349,7 +7319,7 @@ static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinker
 	INT32 s;
 	size_t sec = sides[*lines[line].sidenum].sector-sectors;
 
-	for (s = -1; (s = P_FindSectorFromLineTag(lines+line, s)) >= 0 ;)
+	for (s = -1; (s = P_FindSectorFromTag(lines[line].tag, s)) >= 0 ;)
 		P_AddFakeFloor(&sectors[s], &sectors[sec], lines+line, ffloorflags, secthinkers);
 }
 
@@ -7711,7 +7681,7 @@ static void P_SpawnScrollers(void)
 
 			case 513: // scroll effect ceiling
 			case 533: // scroll and carry objects on ceiling
-				for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 					Add_Scroller(sc_ceiling, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB);
 				if (special != 533)
 					break;
@@ -7720,13 +7690,13 @@ static void P_SpawnScrollers(void)
 			case 523:	// carry objects on ceiling
 				dx = FixedMul(dx, CARRYFACTOR);
 				dy = FixedMul(dy, CARRYFACTOR);
-				for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 					Add_Scroller(sc_carry_ceiling, dx, dy, control, s, accel, l->flags & ML_NOCLIMB);
 				break;
 
 			case 510: // scroll effect floor
 			case 530: // scroll and carry objects on floor
-				for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 					Add_Scroller(sc_floor, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB);
 				if (special != 530)
 					break;
@@ -7735,14 +7705,14 @@ static void P_SpawnScrollers(void)
 			case 520:	// carry objects on floor
 				dx = FixedMul(dx, CARRYFACTOR);
 				dy = FixedMul(dy, CARRYFACTOR);
-				for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 					Add_Scroller(sc_carry, dx, dy, control, s, accel, l->flags & ML_NOCLIMB);
 				break;
 
 			// scroll wall according to linedef
 			// (same direction and speed as scrolling floors)
 			case 502:
-				for (s = -1; (s = P_FindLineFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 					if (s != (INT32)i)
 						Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[0], accel, 0);
 				break;
@@ -7812,7 +7782,7 @@ void T_Disappear(disappear_t *d)
 		ffloor_t *rover;
 		register INT32 s;
 
-		for (s = -1; (s = P_FindSectorFromLineTag(&lines[d->affectee], s)) >= 0 ;)
+		for (s = -1; (s = P_FindSectorFromTag(lines[d->affectee].tag, s)) >= 0 ;)
 		{
 			for (rover = sectors[s].ffloors; rover; rover = rover->next)
 			{
@@ -8569,7 +8539,7 @@ static void P_SpawnFriction(void)
 			else
 				movefactor = FRACUNIT;
 
-			for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+			for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 				Add_Friction(friction, movefactor, s, -1);
 		}
 }
@@ -9104,15 +9074,15 @@ static void P_SpawnPushers(void)
 		switch (l->special)
 		{
 			case 541: // wind
-				for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 					Add_Pusher(p_wind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4);
 				break;
 			case 544: // current
-				for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 					Add_Pusher(p_current, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4);
 				break;
 			case 547: // push/pull
-				for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 				{
 					thing = P_GetPushThing(s);
 					if (thing) // No MT_P* means no effect
@@ -9120,19 +9090,19 @@ static void P_SpawnPushers(void)
 				}
 				break;
 			case 545: // current up
-				for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 					Add_Pusher(p_upcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4);
 				break;
 			case 546: // current down
-				for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 					Add_Pusher(p_downcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4);
 				break;
 			case 542: // wind up
-				for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 					Add_Pusher(p_upwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4);
 				break;
 			case 543: // wind down
-				for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;)
+				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
 					Add_Pusher(p_downwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4);
 				break;
 		}
diff --git a/src/p_spec.h b/src/p_spec.h
index 53e0076ef..98541d3e5 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -55,7 +55,6 @@ fixed_t P_FindNextLowestFloor(sector_t *sec, fixed_t currentheight);
 fixed_t P_FindLowestCeilingSurrounding(sector_t *sec);
 fixed_t P_FindHighestCeilingSurrounding(sector_t *sec);
 
-INT32 P_FindSectorFromLineTag(line_t *line, INT32 start);
 INT32 P_FindSectorFromTag(INT16 tag, INT32 start);
 INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start);
 

From 4cec927bbb35d4d006c4fa1cc9954985a1ab5370 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 27 Apr 2020 14:34:42 +0200
Subject: [PATCH 224/251] Replace P_FindLineFromLineTag with P_FindLineFromTag

---
 src/p_spec.c | 36 +++---------------------------------
 1 file changed, 3 insertions(+), 33 deletions(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index 7074ca4a6..f9e0a4040 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -1015,42 +1015,12 @@ INT32 P_FindSectorFromTag(INT16 tag, INT32 start)
 	}
 }
 
-/** Searches the tag lists for the next line tagged to a line.
-  *
-  * \param line  Tagged line used as a reference.
-  * \param start -1 to start anew, or the result of a previous call to keep
-  *              searching.
-  * \return Number of the next tagged line found.
-  * \sa P_FindSectorFromTag
-  */
-static INT32 P_FindLineFromLineTag(const line_t *line, INT32 start)
-{
-	if (line->tag == -1)
-	{
-		start++;
-
-		if (start >= (INT32)numlines)
-			return -1;
-
-		return start;
-	}
-	else
-	{
-		start = start >= 0 ? lines[start].nexttag :
-			lines[(unsigned)line->tag % numlines].firsttag;
-		while (start >= 0 && lines[start].tag != line->tag)
-			start = lines[start].nexttag;
-		return start;
-	}
-}
-#if 0
 /** Searches the tag lists for the next line with a given tag and special.
   *
   * \param tag     Tag number.
   * \param start   -1 to start anew, or the result of a previous call to keep
   *                searching.
   * \return Number of next suitable line found.
-  * \sa P_FindLineFromLineTag
   * \author Graue <graue@oceanbase.org>
   */
 static INT32 P_FindLineFromTag(INT32 tag, INT32 start)
@@ -1059,7 +1029,7 @@ static INT32 P_FindLineFromTag(INT32 tag, INT32 start)
 	{
 		start++;
 
-		if (start >= numlines)
+		if (start >= (INT32)numlines)
 			return -1;
 
 		return start;
@@ -1073,7 +1043,7 @@ static INT32 P_FindLineFromTag(INT32 tag, INT32 start)
 		return start;
 	}
 }
-#endif
+
 //
 // P_FindSpecialLineFromTag
 //
@@ -6605,7 +6575,7 @@ void P_SpawnSpecials(boolean fromnetsave)
 							if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300)
 								Add_MasterDisappearer(abs(lines[i].dx>>FRACBITS), abs(lines[i].dy>>FRACBITS), abs(sides[lines[i].sidenum[0]].sector->floorheight>>FRACBITS), (INT32)(sectors[s].lines[j]-lines), (INT32)i);
 				} else // Find FOFs by effect sector tag
-					for (s = -1; (s = P_FindLineFromLineTag(lines + i, s)) >= 0 ;)
+					for (s = -1; (s = P_FindLineFromTag(lines[i].tag, s)) >= 0 ;)
 					{
 						if ((size_t)s == i)
 							continue;

From 9b3917cd729895c0f0e2db8792d3b721222afef4 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Wed, 29 Apr 2020 10:55:49 +0200
Subject: [PATCH 225/251] Revert "Replace a few instance of strncpy with
 strlcpy"

This reverts commit 2e27f32d3e3c7de727867fa0c25f75f0c9ebe698.
---
 src/dehacked.c |  6 ++++--
 src/f_finale.c |  4 ++--
 src/m_menu.c   | 14 +++++++-------
 src/m_menu.h   |  2 +-
 src/p_setup.c  |  4 +++-
 src/r_data.c   |  5 +++--
 src/v_video.c  |  2 +-
 src/w_wad.c    |  8 +++++---
 src/y_inter.c  |  5 +++--
 9 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index fbd42dee1..e9d029be0 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -419,7 +419,7 @@ static void readPlayer(MYFILE *f, INT32 num)
 			if (fastcmp(word, "PICNAME"))
 			{
 				SLOTFOUND
-				strlcpy(description[num].picname, word2, sizeof(description->picname));
+				strncpy(description[num].picname, word2, 8);
 			}
 			// new character select
 			else if (fastcmp(word, "DISPLAYNAME"))
@@ -3889,7 +3889,9 @@ static void readmaincfg(MYFILE *f)
 					lumpnum_t lumpnum;
 					char newname[9];
 
-					strlcpy(newname, word2, sizeof(newname));
+					strncpy(newname, word2, 8);
+
+					newname[8] = '\0';
 
 					lumpnum = W_CheckNumForName(newname);
 
diff --git a/src/f_finale.c b/src/f_finale.c
index abef1da69..825f646b0 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -2338,7 +2338,7 @@ void F_InitMenuPresValues(void)
 	activeMenuId = MainDef.menuid;
 
 	// Set defaults for presentation values
-	strlcpy(curbgname, "TITLESKY", sizeof(curbgname));
+	strncpy(curbgname, "TITLESKY", 9);
 	curfadevalue = 16;
 	curbgcolor = -1;
 	curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed;
@@ -2348,7 +2348,7 @@ void F_InitMenuPresValues(void)
 	curhidepics = hidetitlepics;
 	curttmode = ttmode;
 	curttscale = ttscale;
-	strlcpy(curttname, ttname, sizeof(curttname));
+	strncpy(curttname, ttname, 9);
 	curttx = ttx;
 	curtty = tty;
 	curttloop = ttloop;
diff --git a/src/m_menu.c b/src/m_menu.c
index e510f582a..1069f0f30 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -2615,7 +2615,7 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval,
 	}
 	else if (menupres[menutype].bgname[0])
 	{
-		strlcpy(curbgname, menupres[menutype].bgname, sizeof(curbgname));
+		strncpy(curbgname, menupres[menutype].bgname, 8);
 		curbgxspeed = menupres[menutype].titlescrollxspeed != INT32_MAX ? menupres[menutype].titlescrollxspeed : titlescrollxspeed;
 		curbgyspeed = menupres[menutype].titlescrollyspeed != INT32_MAX ? menupres[menutype].titlescrollyspeed : titlescrollyspeed;
 		return true;
@@ -2628,7 +2628,7 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval,
 			curbghide = true;
 		else
 		{
-			strlcpy(curbgname, defaultname, sizeof(curbgname));
+			strncpy(curbgname, defaultname, 9);
 			curbgxspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollxspeed;
 			curbgyspeed = (gamestate == GS_TIMEATTACK) ? 0 : titlescrollyspeed;
 		}
@@ -2767,7 +2767,7 @@ void M_ChangeMenuMusic(const char *defaultmusname, boolean defaultmuslooping)
 void M_SetMenuCurBackground(const char *defaultname)
 {
 	char name[9];
-	strlcpy(name, defaultname, 9);
+	strncpy(name, defaultname, 8);
 	M_IterateMenuTree(MIT_SetCurBackground, &name);
 }
 
@@ -2820,7 +2820,7 @@ static void M_HandleMenuPresState(menu_t *newMenu)
 	activeMenuId = newMenu ? newMenu->menuid : 0;
 
 	// Set defaults for presentation values
-	strlcpy(curbgname, "TITLESKY", sizeof(curbgname));
+	strncpy(curbgname, "TITLESKY", 9);
 	curfadevalue = 16;
 	curhidepics = hidetitlepics;
 	curbgcolor = -1;
@@ -5785,7 +5785,7 @@ static void M_DrawLevelPlatterMenu(void)
 		{
 			F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
 			// Draw and animate foreground
-			if (!strcmp("RECATKBG", curbgname))
+			if (!strncmp("RECATKBG", curbgname, 8))
 				M_DrawRecordAttackForeground();
 		}
 
@@ -6033,7 +6033,7 @@ static void M_DrawMessageMenu(void)
 			else
 			{
 				F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
-				if (!strcmp("RECATKBG", curbgname))
+				if (!strncmp("RECATKBG", curbgname, 8))
 					M_DrawRecordAttackForeground();
 			}
 		}
@@ -9583,7 +9583,7 @@ void M_DrawTimeAttackMenu(void)
 	{
 		F_SkyScroll(curbgxspeed, curbgyspeed, curbgname);
 		// Draw and animate foreground
-		if (!strcmp("RECATKBG", curbgname))
+		if (!strncmp("RECATKBG", curbgname, 8))
 			M_DrawRecordAttackForeground();
 	}
 	if (curfadevalue)
diff --git a/src/m_menu.h b/src/m_menu.h
index 0658f38da..eeda9cc58 100644
--- a/src/m_menu.h
+++ b/src/m_menu.h
@@ -340,7 +340,7 @@ typedef struct
 {
 	boolean used;
 	char notes[441];
-	char picname[9];
+	char picname[8];
 	char skinname[SKINNAMESIZE*2+2]; // skin&skin\0
 	patch_t *charpic;
 	UINT8 prev;
diff --git a/src/p_setup.c b/src/p_setup.c
index 61a49d958..8c73b85e6 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -2883,7 +2883,9 @@ static void P_RunLevelScript(const char *scriptname)
 		lumpnum_t lumpnum;
 		char newname[9];
 
-		strlcpy(newname, scriptname, sizeof(newname));
+		strncpy(newname, scriptname, 8);
+
+		newname[8] = '\0';
 
 		lumpnum = W_CheckNumForName(newname);
 
diff --git a/src/r_data.c b/src/r_data.c
index c542bbd98..831e75bef 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -2603,7 +2603,7 @@ INT32 R_CheckTextureNumForName(const char *name)
 		return 0;
 
 	for (i = 0; i < tidcachelen; i++)
-		if (!strcasecmp(tidcache[i].name, name))
+		if (!strncasecmp(tidcache[i].name, name, 8))
 			return tidcache[i].id;
 
 	// Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier
@@ -2613,7 +2613,8 @@ INT32 R_CheckTextureNumForName(const char *name)
 		{
 			tidcachelen++;
 			Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache);
-			strlcpy(tidcache[tidcachelen-1].name, name, sizeof(tidcache->name));
+			strncpy(tidcache[tidcachelen-1].name, name, 8);
+			tidcache[tidcachelen-1].name[8] = '\0';
 #ifndef ZDEBUG
 			CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name);
 #endif
diff --git a/src/v_video.c b/src/v_video.c
index e03d0a60d..2d1014c23 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -391,7 +391,7 @@ const char *R_GetPalname(UINT16 num)
 	if (num > 0 && num <= 10000)
 		snprintf(newpal, 8, "PAL%04u", num-1);
 
-	strlcpy(palname, newpal, sizeof(palname));
+	strncpy(palname, newpal, 8);
 	return palname;
 }
 
diff --git a/src/w_wad.c b/src/w_wad.c
index 267f06198..a81132354 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -440,15 +440,17 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
 		else
 			lump_p->compression = CM_NOCOMPRESSION;
 		memset(lump_p->name, 0x00, 9);
-		strlcpy(lump_p->name, fileinfo->name, 9);
+		strncpy(lump_p->name, fileinfo->name, 8);
 
 		// Allocate the lump's long name.
 		lump_p->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
-		strlcpy(lump_p->longname, fileinfo->name, 9);
+		strncpy(lump_p->longname, fileinfo->name, 8);
+		lump_p->longname[8] = '\0';
 
 		// Allocate the lump's full name.
 		lump_p->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
-		strlcpy(lump_p->fullname, fileinfo->name, 9);
+		strncpy(lump_p->fullname, fileinfo->name, 8);
+		lump_p->fullname[8] = '\0';
 	}
 	free(fileinfov);
 	*nlmp = numlumps;
diff --git a/src/y_inter.c b/src/y_inter.c
index ce57bef9e..f1764a816 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -1740,8 +1740,9 @@ static void Y_CalculateCompetitionWinners(void)
 		data.competition.monitors[data.competition.numplayers] = monitors[winner];
 		data.competition.scores[data.competition.numplayers] = scores[winner];
 
-		strlcpy(tempname, player_names[winner], 9);
-		strlcpy(data.competition.name[data.competition.numplayers], tempname, 9);
+		strncpy(tempname, player_names[winner], 8);
+		tempname[8] = '\0';
+		strncpy(data.competition.name[data.competition.numplayers], tempname, 9);
 
 		data.competition.color[data.competition.numplayers] = &players[winner].skincolor;
 		data.competition.character[data.competition.numplayers] = &players[winner].skin;

From d89d2505bb64c82c5e5192149aed0e5066006a3e Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Wed, 29 Apr 2020 14:45:52 +0100
Subject: [PATCH 226/251] Whoops the third

---
 src/p_saveg.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index e63409386..239fa47df 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -966,7 +966,7 @@ static void ArchiveSectors(void)
 			if (diff3 & SD_CRUMBLESTATE)
 				WRITEINT32(save_p, ss->crumblestate);
 			if (diff & SD_FFLOORS)
-				ArchiveFFloors(save_p, ss);
+				ArchiveFFloors(ss);
 		}
 	}
 
@@ -1042,7 +1042,7 @@ static void UnArchiveSectors(void)
 			sectors[i].crumblestate = READINT32(save_p);
 
 		if (diff & SD_FFLOORS)
-			UnArchiveFFloors(save_p, sectors[i]);
+			UnArchiveFFloors(sectors[i]);
 	}
 }
 

From 2f0bf3860f1ba456c9b2f5ef3d975fd19c2289d5 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Wed, 29 Apr 2020 15:24:28 +0100
Subject: [PATCH 227/251] Don't discard const, added missing &

---
 src/p_saveg.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index 239fa47df..aee160859 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -776,7 +776,7 @@ static void P_NetUnArchiveColormaps(void)
 #define FD_ALPHA 0x02
 
 // Check if any of the sector's FOFs differ from how they spawned
-static boolean CheckFFloorDiff(sector_t *ss)
+static boolean CheckFFloorDiff(const sector_t *ss)
 {
 	ffloor_t *rover;
 
@@ -794,7 +794,7 @@ static boolean CheckFFloorDiff(sector_t *ss)
 
 // Special case: save the stats of all modified ffloors along with their ffloor "number"s
 // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
-static void ArchiveFFloors(sector_t *ss)
+static void ArchiveFFloors(const sector_t *ss)
 {
 	size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc
 	ffloor_t *rover;
@@ -821,7 +821,7 @@ static void ArchiveFFloors(sector_t *ss)
 	WRITEUINT16(save_p, 0xffff);
 }
 
-static void UnArchiveFFloors(sector_t *ss)
+static void UnArchiveFFloors(const sector_t *ss)
 {
 	UINT16 j = 0; // number of current ffloor in loop
 	UINT16 fflr_i; // saved ffloor "number" of next modified ffloor
@@ -1042,7 +1042,7 @@ static void UnArchiveSectors(void)
 			sectors[i].crumblestate = READINT32(save_p);
 
 		if (diff & SD_FFLOORS)
-			UnArchiveFFloors(sectors[i]);
+			UnArchiveFFloors(&sectors[i]);
 	}
 }
 

From f9b831c00b25b02873d2fef7964267c1f89287e5 Mon Sep 17 00:00:00 2001
From: lachwright <lachlanwright17@gmail.com>
Date: Fri, 1 May 2020 06:34:30 +0800
Subject: [PATCH 228/251] Restore jump-related pflags properly during twinspin

---
 src/p_user.c | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/src/p_user.c b/src/p_user.c
index b2f40fe70..2b8744e64 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -5006,6 +5006,15 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range)
 	player->pflags |= PF_THOKKED;
 }
 
+static inline void P_DoTwinSpin(player_t *player)
+{
+	player->pflags &= ~PF_NOJUMPDAMAGE;
+	player->pflags |= P_GetJumpFlags(player) | PF_THOKKED;
+	S_StartSound(player->mo, sfx_s3k42);
+	player->mo->frame = 0;
+	P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN);
+}
+
 //
 // P_DoJumpStuff
 //
@@ -5176,12 +5185,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 						break;
 					case CA_TWINSPIN:
 						if ((player->charability2 == CA2_MELEE) && (!(player->pflags & (PF_THOKKED|PF_USEDOWN)) || player->charflags & SF_MULTIABILITY))
-						{
-							player->pflags |= PF_THOKKED;
-							S_StartSound(player->mo, sfx_s3k42);
-							player->mo->frame = 0;
-							P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN);
-						}
+							P_DoTwinSpin(player);
 						break;
 					default:
 						break;
@@ -5438,12 +5442,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 					break;
 				case CA_TWINSPIN:
 					if (!(player->pflags & PF_THOKKED) || player->charflags & SF_MULTIABILITY)
-					{
-						player->pflags |= PF_THOKKED;
-						S_StartSound(player->mo, sfx_s3k42);
-						player->mo->frame = 0;
-						P_SetPlayerMobjState(player->mo, S_PLAY_TWINSPIN);
-					}
+						P_DoTwinSpin(player);
 					break;
 				default:
 					break;

From be0959fa904889ae65532d2afec21b58f73eb1b8 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Fri, 1 May 2020 11:25:32 +0200
Subject: [PATCH 229/251] Remove bogus comments from p_saveg.c

---
 src/p_saveg.c | 397 +-------------------------------------------------
 1 file changed, 5 insertions(+), 392 deletions(-)

diff --git a/src/p_saveg.c b/src/p_saveg.c
index c04a9ee2d..2f84e97ef 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -59,9 +59,6 @@ typedef enum
 	DRONE      = 0x80,
 } player_saveflags;
 
-//
-// P_ArchivePlayer
-//
 static inline void P_ArchivePlayer(void)
 {
 	const player_t *player = &players[consoleplayer];
@@ -77,9 +74,6 @@ static inline void P_ArchivePlayer(void)
 	WRITEINT32(save_p, player->continues);
 }
 
-//
-// P_UnArchivePlayer
-//
 static inline void P_UnArchivePlayer(void)
 {
 	INT16 skininfo = READUINT16(save_p);
@@ -92,9 +86,6 @@ static inline void P_UnArchivePlayer(void)
 	savedata.continues = READINT32(save_p);
 }
 
-//
-// P_NetArchivePlayers
-//
 static void P_NetArchivePlayers(void)
 {
 	INT32 i, j;
@@ -300,9 +291,6 @@ static void P_NetArchivePlayers(void)
 	}
 }
 
-//
-// P_NetUnArchivePlayers
-//
 static void P_NetUnArchivePlayers(void)
 {
 	INT32 i, j;
@@ -772,9 +760,6 @@ static void P_NetUnArchiveColormaps(void)
 #define LD_S2BOTTEX 0x04
 #define LD_S2MIDTEX 0x08
 
-//
-// P_NetArchiveWorld
-//
 static void P_NetArchiveWorld(void)
 {
 	size_t i;
@@ -1022,9 +1007,6 @@ static void P_NetArchiveWorld(void)
 	save_p = put;
 }
 
-//
-// P_NetUnArchiveWorld
-//
 static void P_NetUnArchiveWorld(void)
 {
 	UINT16 i;
@@ -1341,11 +1323,6 @@ static UINT32 SaveSlope(const pslope_t *slope)
 	return 0xFFFFFFFF;
 }
 
-//
-// SaveMobjThinker
-//
-// Saves a mobj_t thinker
-//
 static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 {
 	const mobj_t *mobj = (const mobj_t *)th;
@@ -1646,11 +1623,6 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, mobj->mobjnum);
 }
 
-//
-// SaveNoEnemiesThinker
-//
-// Saves a noenemies_t thinker
-//
 static void SaveNoEnemiesThinker(const thinker_t *th, const UINT8 type)
 {
 	const noenemies_t *ht  = (const void *)th;
@@ -1658,11 +1630,6 @@ static void SaveNoEnemiesThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveLine(ht->sourceline));
 }
 
-//
-// SaveBounceCheeseThinker
-//
-// Saves a bouncecheese_t thinker
-//
 static void SaveBounceCheeseThinker(const thinker_t *th, const UINT8 type)
 {
 	const bouncecheese_t *ht  = (const void *)th;
@@ -1676,11 +1643,6 @@ static void SaveBounceCheeseThinker(const thinker_t *th, const UINT8 type)
 	WRITECHAR(save_p, ht->low);
 }
 
-//
-// SaveContinuousFallThinker
-//
-// Saves a continuousfall_t thinker
-//
 static void SaveContinuousFallThinker(const thinker_t *th, const UINT8 type)
 {
 	const continuousfall_t *ht  = (const void *)th;
@@ -1693,11 +1655,6 @@ static void SaveContinuousFallThinker(const thinker_t *th, const UINT8 type)
 	WRITEFIXED(save_p, ht->destheight);
 }
 
-//
-// SaveMarioBlockThinker
-//
-// Saves a mariothink_t thinker
-//
 static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type)
 {
 	const mariothink_t *ht  = (const void *)th;
@@ -1710,11 +1667,6 @@ static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT16(save_p, ht->tag);
 }
 
-//
-// SaveMarioCheckThinker
-//
-// Saves a mariocheck_t thinker
-//
 static void SaveMarioCheckThinker(const thinker_t *th, const UINT8 type)
 {
 	const mariocheck_t *ht  = (const void *)th;
@@ -1723,11 +1675,6 @@ static void SaveMarioCheckThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveSector(ht->sector));
 }
 
-//
-// SaveThwompThinker
-//
-// Saves a thwomp_t thinker
-//
 static void SaveThwompThinker(const thinker_t *th, const UINT8 type)
 {
 	const thwomp_t *ht  = (const void *)th;
@@ -1744,11 +1691,6 @@ static void SaveThwompThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT16(save_p, ht->sound);
 }
 
-//
-// SaveFloatThinker
-//
-// Saves a floatthink_t thinker
-//
 static void SaveFloatThinker(const thinker_t *th, const UINT8 type)
 {
 	const floatthink_t *ht  = (const void *)th;
@@ -1758,10 +1700,6 @@ static void SaveFloatThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT16(save_p, ht->tag);
 }
 
-// SaveEachTimeThinker
-//
-// Loads a eachtime_t from a save game
-//
 static void SaveEachTimeThinker(const thinker_t *th, const UINT8 type)
 {
 	const eachtime_t *ht  = (const void *)th;
@@ -1776,10 +1714,6 @@ static void SaveEachTimeThinker(const thinker_t *th, const UINT8 type)
 	WRITECHAR(save_p, ht->triggerOnExit);
 }
 
-// SaveRaiseThinker
-//
-// Saves a raise_t thinker
-//
 static void SaveRaiseThinker(const thinker_t *th, const UINT8 type)
 {
 	const raise_t *ht  = (const void *)th;
@@ -1794,11 +1728,6 @@ static void SaveRaiseThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT8(save_p, ht->flags);
 }
 
-//
-// SaveCeilingThinker
-//
-// Saves a ceiling_t thinker
-//
 static void SaveCeilingThinker(const thinker_t *th, const UINT8 type)
 {
 	const ceiling_t *ht = (const void *)th;
@@ -1820,11 +1749,6 @@ static void SaveCeilingThinker(const thinker_t *th, const UINT8 type)
 	WRITEFIXED(save_p, ht->sourceline);
 }
 
-//
-// SaveFloormoveThinker
-//
-// Saves a floormove_t thinker
-//
 static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type)
 {
 	const floormove_t *ht = (const void *)th;
@@ -1841,11 +1765,6 @@ static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type)
 	WRITEFIXED(save_p, ht->delaytimer);
 }
 
-//
-// SaveLightflashThinker
-//
-// Saves a lightflash_t thinker
-//
 static void SaveLightflashThinker(const thinker_t *th, const UINT8 type)
 {
 	const lightflash_t *ht = (const void *)th;
@@ -1855,11 +1774,6 @@ static void SaveLightflashThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->minlight);
 }
 
-//
-// SaveStrobeThinker
-//
-// Saves a strobe_t thinker
-//
 static void SaveStrobeThinker(const thinker_t *th, const UINT8 type)
 {
 	const strobe_t *ht = (const void *)th;
@@ -1872,11 +1786,6 @@ static void SaveStrobeThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->brighttime);
 }
 
-//
-// SaveGlowThinker
-//
-// Saves a glow_t thinker
-//
 static void SaveGlowThinker(const thinker_t *th, const UINT8 type)
 {
 	const glow_t *ht = (const void *)th;
@@ -1887,11 +1796,7 @@ static void SaveGlowThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->direction);
 	WRITEINT32(save_p, ht->speed);
 }
-//
-// SaveFireflickerThinker
-//
-// Saves a fireflicker_t thinker
-//
+
 static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type)
 {
 	const fireflicker_t *ht = (const void *)th;
@@ -1902,11 +1807,7 @@ static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->maxlight);
 	WRITEINT32(save_p, ht->minlight);
 }
-//
-// SaveElevatorThinker
-//
-// Saves a elevator_t thinker
-//
+
 static void SaveElevatorThinker(const thinker_t *th, const UINT8 type)
 {
 	const elevator_t *ht = (const void *)th;
@@ -1929,11 +1830,6 @@ static void SaveElevatorThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveLine(ht->sourceline));
 }
 
-//
-// SaveCrumbleThinker
-//
-// Saves a crumble_t thinker
-//
 static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type)
 {
 	const crumble_t *ht = (const void *)th;
@@ -1951,11 +1847,6 @@ static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT8(save_p, ht->flags);
 }
 
-//
-// SaveScrollThinker
-//
-// Saves a scroll_t thinker
-//
 static inline void SaveScrollThinker(const thinker_t *th, const UINT8 type)
 {
 	const scroll_t *ht = (const void *)th;
@@ -1972,11 +1863,6 @@ static inline void SaveScrollThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT8(save_p, ht->type);
 }
 
-//
-// SaveFrictionThinker
-//
-// Saves a friction_t thinker
-//
 static inline void SaveFrictionThinker(const thinker_t *th, const UINT8 type)
 {
 	const friction_t *ht = (const void *)th;
@@ -1988,11 +1874,6 @@ static inline void SaveFrictionThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT8(save_p, ht->roverfriction);
 }
 
-//
-// SavePusherThinker
-//
-// Saves a pusher_t thinker
-//
 static inline void SavePusherThinker(const thinker_t *th, const UINT8 type)
 {
 	const pusher_t *ht = (const void *)th;
@@ -2012,11 +1893,6 @@ static inline void SavePusherThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->slider);
 }
 
-//
-// SaveLaserThinker
-//
-// Saves a laserthink_t thinker
-//
 static void SaveLaserThinker(const thinker_t *th, const UINT8 type)
 {
 	const laserthink_t *ht = (const void *)th;
@@ -2026,11 +1902,6 @@ static void SaveLaserThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT32(save_p, SaveLine(ht->sourceline));
 }
 
-//
-// SaveLightlevelThinker
-//
-// Saves a lightlevel_t thinker
-//
 static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type)
 {
 	const lightlevel_t *ht = (const void *)th;
@@ -2043,11 +1914,6 @@ static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->timer);
 }
 
-//
-// SaveExecutorThinker
-//
-// Saves a executor_t thinker
-//
 static void SaveExecutorThinker(const thinker_t *th, const UINT8 type)
 {
 	const executor_t *ht = (const void *)th;
@@ -2058,11 +1924,6 @@ static void SaveExecutorThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->timer);
 }
 
-//
-// SaveDisappearThinker
-//
-// Saves a disappear_t thinker
-//
 static void SaveDisappearThinker(const thinker_t *th, const UINT8 type)
 {
 	const disappear_t *ht = (const void *)th;
@@ -2076,11 +1937,6 @@ static void SaveDisappearThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->exists);
 }
 
-//
-// SaveFadeThinker
-//
-// Saves a fade_t thinker
-//
 static void SaveFadeThinker(const thinker_t *th, const UINT8 type)
 {
 	const fade_t *ht = (const void *)th;
@@ -2104,11 +1960,6 @@ static void SaveFadeThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT8(save_p, ht->exactalpha);
 }
 
-//
-// SaveFadeColormapThinker
-//
-// Saves a fadecolormap_t thinker
-//
 static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type)
 {
 	const fadecolormap_t *ht = (const void *)th;
@@ -2121,11 +1972,6 @@ static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->timer);
 }
 
-//
-// SavePlaneDisplaceThinker
-//
-// Saves a planedisplace_t thinker
-//
 static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type)
 {
 	const planedisplace_t *ht = (const void *)th;
@@ -2137,7 +1983,6 @@ static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT8(save_p, ht->type);
 }
 
-/// Save a dynamic slope thinker.
 static inline void SaveDynamicSlopeThinker(const thinker_t *th, const UINT8 type)
 {
 	const dynplanethink_t* ht = (const void*)th;
@@ -2153,12 +1998,6 @@ static inline void SaveDynamicSlopeThinker(const thinker_t *th, const UINT8 type
 }
 
 #ifdef POLYOBJECTS
-
-//
-// SavePolyrotateThinker
-//
-// Saves a polyrotate_t thinker
-//
 static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type)
 {
 	const polyrotate_t *ht = (const void *)th;
@@ -2168,11 +2007,6 @@ static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->distance);
 }
 
-//
-// SavePolymoveThinker
-//
-// Saves a polymovet_t thinker
-//
 static void SavePolymoveThinker(const thinker_t *th, const UINT8 type)
 {
 	const polymove_t *ht = (const void *)th;
@@ -2185,11 +2019,6 @@ static void SavePolymoveThinker(const thinker_t *th, const UINT8 type)
 	WRITEANGLE(save_p, ht->angle);
 }
 
-//
-// SavePolywaypointThinker
-//
-// Saves a polywaypoint_t thinker
-//
 static void SavePolywaypointThinker(const thinker_t *th, UINT8 type)
 {
 	const polywaypoint_t *ht = (const void *)th;
@@ -2209,11 +2038,6 @@ static void SavePolywaypointThinker(const thinker_t *th, UINT8 type)
 	WRITEUINT32(save_p, SaveMobjnum(ht->target));
 }
 
-//
-// SavePolyslidedoorThinker
-//
-// Saves a polyslidedoor_t thinker
-//
 static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type)
 {
 	const polyslidedoor_t *ht = (const void *)th;
@@ -2233,11 +2057,6 @@ static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type)
 	WRITEUINT8(save_p, ht->closing);
 }
 
-//
-// SavePolyswingdoorThinker
-//
-// Saves a polyswingdoor_t thinker
-//
 static void SavePolyswingdoorThinker(const thinker_t *th, const UINT8 type)
 {
 	const polyswingdoor_t *ht = (const void *)th;
@@ -2287,25 +2106,8 @@ static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->duration);
 	WRITEINT32(save_p, ht->timer);
 }
-
 #endif
-/*
-//
-// SaveWhatThinker
-//
-// Saves a what_t thinker
-//
-static inline void SaveWhatThinker(const thinker_t *th, const UINT8 type)
-{
-	const what_t *ht = (const void *)th;
-	WRITEUINT8(save_p, type);
-}
-*/
 
-//
-// P_NetArchiveThinkers
-//
-//
 static void P_NetArchiveThinkers(void)
 {
 	const thinker_t *th;
@@ -2605,11 +2407,6 @@ static inline pslope_t *LoadSlope(UINT32 slopeid)
 	return NULL;
 }
 
-//
-// LoadMobjThinker
-//
-// Loads a mobj_t from a save game
-//
 static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 {
 	thinker_t *next;
@@ -2886,10 +2683,6 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
 	return &mobj->thinker;
 }
 
-// LoadNoEnemiesThinker
-//
-// Loads a noenemies_t from a save game
-//
 static thinker_t* LoadNoEnemiesThinker(actionf_p1 thinker)
 {
 	noenemies_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -2898,10 +2691,6 @@ static thinker_t* LoadNoEnemiesThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-// LoadBounceCheeseThinker
-//
-// Loads a bouncecheese_t from a save game
-//
 static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker)
 {
 	bouncecheese_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -2916,10 +2705,6 @@ static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-// LoadContinuousFallThinker
-//
-// Loads a continuousfall_t from a save game
-//
 static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker)
 {
 	continuousfall_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -2933,10 +2718,6 @@ static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-// LoadMarioBlockThinker
-//
-// Loads a mariothink_t from a save game
-//
 static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker)
 {
 	mariothink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -2950,10 +2731,6 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-// LoadMarioCheckThinker
-//
-// Loads a mariocheck_t from a save game
-//
 static thinker_t* LoadMarioCheckThinker(actionf_p1 thinker)
 {
 	mariocheck_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -2963,10 +2740,6 @@ static thinker_t* LoadMarioCheckThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-// LoadThwompThinker
-//
-// Loads a thwomp_t from a save game
-//
 static thinker_t* LoadThwompThinker(actionf_p1 thinker)
 {
 	thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -2984,10 +2757,6 @@ static thinker_t* LoadThwompThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-// LoadFloatThinker
-//
-// Loads a floatthink_t from a save game
-//
 static thinker_t* LoadFloatThinker(actionf_p1 thinker)
 {
 	floatthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -2998,10 +2767,6 @@ static thinker_t* LoadFloatThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-// LoadEachTimeThinker
-//
-// Loads a eachtime_t from a save game
-//
 static thinker_t* LoadEachTimeThinker(actionf_p1 thinker)
 {
 	size_t i;
@@ -3017,10 +2782,6 @@ static thinker_t* LoadEachTimeThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-// LoadRaiseThinker
-//
-// Loads a raise_t from a save game
-//
 static thinker_t* LoadRaiseThinker(actionf_p1 thinker)
 {
 	raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3036,11 +2797,6 @@ static thinker_t* LoadRaiseThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadCeilingThinker
-//
-// Loads a ceiling_t from a save game
-//
 static thinker_t* LoadCeilingThinker(actionf_p1 thinker)
 {
 	ceiling_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3065,11 +2821,6 @@ static thinker_t* LoadCeilingThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadFloormoveThinker
-//
-// Loads a floormove_t from a save game
-//
 static thinker_t* LoadFloormoveThinker(actionf_p1 thinker)
 {
 	floormove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3089,11 +2840,6 @@ static thinker_t* LoadFloormoveThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadLightflashThinker
-//
-// Loads a lightflash_t from a save game
-//
 static thinker_t* LoadLightflashThinker(actionf_p1 thinker)
 {
 	lightflash_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3106,11 +2852,6 @@ static thinker_t* LoadLightflashThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadStrobeThinker
-//
-// Loads a strobe_t from a save game
-//
 static thinker_t* LoadStrobeThinker(actionf_p1 thinker)
 {
 	strobe_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3126,11 +2867,6 @@ static thinker_t* LoadStrobeThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadGlowThinker
-//
-// Loads a glow_t from a save game
-//
 static thinker_t* LoadGlowThinker(actionf_p1 thinker)
 {
 	glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3144,11 +2880,7 @@ static thinker_t* LoadGlowThinker(actionf_p1 thinker)
 		ht->sector->lightingdata = ht;
 	return &ht->thinker;
 }
-//
-// LoadFireflickerThinker
-//
-// Loads a fireflicker_t from a save game
-//
+
 static thinker_t* LoadFireflickerThinker(actionf_p1 thinker)
 {
 	fireflicker_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3162,11 +2894,7 @@ static thinker_t* LoadFireflickerThinker(actionf_p1 thinker)
 		ht->sector->lightingdata = ht;
 	return &ht->thinker;
 }
-//
-// +vatorThinker
-//
-// Loads a elevator_t from a save game
-//
+
 static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata)
 {
 	elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3197,11 +2925,6 @@ static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata)
 	return &ht->thinker;
 }
 
-//
-// LoadCrumbleThinker
-//
-// Loads a crumble_t from a save game
-//
 static thinker_t* LoadCrumbleThinker(actionf_p1 thinker)
 {
 	crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3224,11 +2947,6 @@ static thinker_t* LoadCrumbleThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadScrollThinker
-//
-// Loads a scroll_t from a save game
-//
 static thinker_t* LoadScrollThinker(actionf_p1 thinker)
 {
 	scroll_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3246,11 +2964,6 @@ static thinker_t* LoadScrollThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadFrictionThinker
-//
-// Loads a friction_t from a save game
-//
 static inline thinker_t* LoadFrictionThinker(actionf_p1 thinker)
 {
 	friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3263,11 +2976,6 @@ static inline thinker_t* LoadFrictionThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadPusherThinker
-//
-// Loads a pusher_t from a save game
-//
 static thinker_t* LoadPusherThinker(actionf_p1 thinker)
 {
 	pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3289,11 +2997,6 @@ static thinker_t* LoadPusherThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadLaserThinker
-//
-// Loads a laserthink_t from a save game
-//
 static inline thinker_t* LoadLaserThinker(actionf_p1 thinker)
 {
 	laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3309,11 +3012,6 @@ static inline thinker_t* LoadLaserThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadLightlevelThinker
-//
-// Loads a lightlevel_t from a save game
-//
 static inline thinker_t* LoadLightlevelThinker(actionf_p1 thinker)
 {
 	lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3329,11 +3027,6 @@ static inline thinker_t* LoadLightlevelThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadExecutorThinker
-//
-// Loads a executor_t from a save game
-//
 static inline thinker_t* LoadExecutorThinker(actionf_p1 thinker)
 {
 	executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3345,11 +3038,6 @@ static inline thinker_t* LoadExecutorThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadDisappearThinker
-//
-// Loads a disappear_t thinker
-//
 static inline thinker_t* LoadDisappearThinker(actionf_p1 thinker)
 {
 	disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3364,11 +3052,6 @@ static inline thinker_t* LoadDisappearThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadFadeThinker
-//
-// Loads a fade_t thinker
-//
 static inline thinker_t* LoadFadeThinker(actionf_p1 thinker)
 {
 	sector_t *ss;
@@ -3411,10 +3094,6 @@ static inline thinker_t* LoadFadeThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-// LoadFadeColormapThinker
-//
-// Loads a fadecolormap_t from a save game
-//
 static inline thinker_t* LoadFadeColormapThinker(actionf_p1 thinker)
 {
 	fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3430,11 +3109,6 @@ static inline thinker_t* LoadFadeColormapThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadPlaneDisplaceThinker
-//
-// Loads a planedisplace_t thinker
-//
 static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker)
 {
 	planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3448,7 +3122,6 @@ static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-/// Save a dynamic slope thinker.
 static inline thinker_t* LoadDynamicSlopeThinker(actionf_p1 thinker)
 {
 	dynplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL);
@@ -3464,12 +3137,6 @@ static inline thinker_t* LoadDynamicSlopeThinker(actionf_p1 thinker)
 }
 
 #ifdef POLYOBJECTS
-
-//
-// LoadPolyrotateThinker
-//
-// Loads a polyrotate_t thinker
-//
 static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker)
 {
 	polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3480,11 +3147,6 @@ static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadPolymoveThinker
-//
-// Loads a polymovet_t thinker
-//
 static thinker_t* LoadPolymoveThinker(actionf_p1 thinker)
 {
 	polymove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3498,11 +3160,6 @@ static thinker_t* LoadPolymoveThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadPolywaypointThinker
-//
-// Loads a polywaypoint_t thinker
-//
 static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker)
 {
 	polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3523,11 +3180,6 @@ static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadPolyslidedoorThinker
-//
-// loads a polyslidedoor_t thinker
-//
 static inline thinker_t* LoadPolyslidedoorThinker(actionf_p1 thinker)
 {
 	polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3548,11 +3200,6 @@ static inline thinker_t* LoadPolyslidedoorThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadPolyswingdoorThinker
-//
-// Loads a polyswingdoor_t thinker
-//
 static inline thinker_t* LoadPolyswingdoorThinker(actionf_p1 thinker)
 {
 	polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3568,11 +3215,6 @@ static inline thinker_t* LoadPolyswingdoorThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadPolydisplaceThinker
-//
-// Loads a polydisplace_t thinker
-//
 static inline thinker_t* LoadPolydisplaceThinker(actionf_p1 thinker)
 {
 	polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3597,11 +3239,6 @@ static inline thinker_t* LoadPolyrotdisplaceThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-//
-// LoadPolyfadeThinker
-//
-// Loads a polyfadet_t thinker
-//
 static thinker_t* LoadPolyfadeThinker(actionf_p1 thinker)
 {
 	polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3618,22 +3255,6 @@ static thinker_t* LoadPolyfadeThinker(actionf_p1 thinker)
 }
 #endif
 
-/*
-//
-// LoadWhatThinker
-//
-// load a what_t thinker
-//
-static inline void LoadWhatThinker(actionf_p1 thinker)
-{
-	what_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
-	ht->thinker.function.acp1 = thinker;
-}
-*/
-
-//
-// P_NetUnArchiveThinkers
-//
 static void P_NetUnArchiveThinkers(void)
 {
 	thinker_t *currentthinker;
@@ -3982,9 +3603,7 @@ static inline void P_UnArchivePolyObjects(void)
 		P_UnArchivePolyObj(&PolyObjects[i]);
 }
 #endif
-//
-// P_FinishMobjs
-//
+
 static inline void P_FinishMobjs(void)
 {
 	thinker_t *currentthinker;
@@ -4093,9 +3712,6 @@ static void P_RelinkPointers(void)
 	}
 }
 
-//
-// P_NetArchiveSpecials
-//
 static inline void P_NetArchiveSpecials(void)
 {
 	size_t i, z;
@@ -4136,9 +3752,6 @@ static inline void P_NetArchiveSpecials(void)
 		WRITEUINT8(save_p, 0x00);
 }
 
-//
-// P_NetUnArchiveSpecials
-//
 static void P_NetUnArchiveSpecials(void)
 {
 	size_t i;

From 485a4e50356d81ce6a72af60ac83da0135b01fb4 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sat, 2 May 2020 12:08:31 +0200
Subject: [PATCH 230/251] Remove POLYOBJECTS and POLYOBJECTS_PLANES defines

---
 src/doomdef.h          |   3 -
 src/hardware/hw_bsp.c  |   2 -
 src/hardware/hw_main.c |  47 +++--------
 src/lua_blockmaplib.c  |   4 -
 src/p_map.c            |   4 -
 src/p_maputl.c         | 164 ++++++++++++++++++-------------------
 src/p_mobj.c           |   3 -
 src/p_polyobj.c        |   8 --
 src/p_polyobj.h        |   4 -
 src/p_saveg.c          |  16 ----
 src/p_setup.c          |   8 --
 src/p_sight.c          |  11 ---
 src/p_spec.c           |   9 ---
 src/p_user.c           |  26 +-----
 src/r_bsp.c            |  52 +++---------
 src/r_bsp.h            |   2 -
 src/r_defs.h           |  10 ---
 src/r_plane.c          | 178 +++++++++++++++++++----------------------
 src/r_plane.h          |  10 +--
 src/r_segs.c           |  92 ++++++++++-----------
 src/r_things.c         |   5 --
 21 files changed, 230 insertions(+), 428 deletions(-)

diff --git a/src/doomdef.h b/src/doomdef.h
index f9828a442..a91142e9d 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -578,9 +578,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
 ///	Dumps the contents of a network save game upon consistency failure for debugging.
 //#define DUMPCONSISTENCY
 
-///	Polyobject fake flat code
-#define POLYOBJECTS_PLANES
-
 ///	See name of player in your crosshair
 #define SEENAMES
 
diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c
index 6f3dd9fbd..ebb74f653 100644
--- a/src/hardware/hw_bsp.c
+++ b/src/hardware/hw_bsp.c
@@ -887,12 +887,10 @@ static void AdjustSegs(void)
 			float distv1,distv2,tmp;
 			nearv1 = nearv2 = MYMAX;
 
-#ifdef POLYOBJECTS
 			// Don't touch polyobject segs. We'll compensate
 			// for this when we go about drawing them.
 			if (lseg->polyseg)
 				continue;
-#endif
 
 			if (p) {
 				for (j = 0; j < p->numpts; j++)
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 7fca7cd91..50c76fb5a 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -1602,7 +1602,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			// heights of the polygon, and h & l, are the final (clipped)
 			// poly coords.
 
-#ifdef POLYOBJECTS
 			// NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to,
 			// you must use the linedef's backsector to be correct
 			// From CB
@@ -1612,7 +1611,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				popenbottom = back->floorheight;
 			}
 			else
-#endif
             {
 				popentop = min(worldtop, worldhigh);
 				popenbottom = max(worldbottom, worldlow);
@@ -1642,7 +1640,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				polybottom = polytop - textureheight[gr_midtexture]*repeats;
 			}
 			// CB
-#ifdef POLYOBJECTS
 			// NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to,
 			// you must use the linedef's backsector to be correct
 			if (gr_curline->polyseg)
@@ -1650,7 +1647,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				lowcut = polybottom;
 				highcut = polytop;
 			}
-#endif
 			else
 			{
 				// The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector
@@ -1780,7 +1776,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 					break;
 			}
 
-#ifdef POLYOBJECTS
 			if (gr_curline->polyseg && gr_curline->polyseg->translucency > 0)
 			{
 				if (gr_curline->polyseg->translucency >= NUMTRANSMAPS) // wall not drawn
@@ -1791,7 +1786,6 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				else
 					blendmode = HWR_TranstableToAlpha(gr_curline->polyseg->translucency, &Surf);
 			}
-#endif
 
 			if (gr_frontsector->numlights)
 			{
@@ -2587,10 +2581,8 @@ static void HWR_AddLine(seg_t * line)
 	static sector_t tempsec;
 
 	fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t
-#ifdef POLYOBJECTS
 	if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES))
 		return;
-#endif
 
 	gr_curline = line;
 
@@ -2717,13 +2709,10 @@ static void HWR_AddLine(seg_t * line)
 
 		if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then
 		{
-			if (
-#ifdef POLYOBJECTS
-			!line->polyseg &&
-#endif
-			!line->sidedef->midtexture
-			&& ((!gr_frontsector->ffloors && !gr_backsector->ffloors)
-			|| (gr_frontsector->tag == gr_backsector->tag)))
+			if (!line->polyseg &&
+				!line->sidedef->midtexture
+				&& ((!gr_frontsector->ffloors && !gr_backsector->ffloors)
+					|| (gr_frontsector->tag == gr_backsector->tag)))
 				return; // line is empty, don't even bother
 			// treat like wide open window instead
 			HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
@@ -2759,13 +2748,10 @@ static void HWR_AddLine(seg_t * line)
 
 	if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then
 	{
-		if (
-#ifdef POLYOBJECTS
-		!line->polyseg &&
-#endif
-		!line->sidedef->midtexture
-		&& ((!gr_frontsector->ffloors && !gr_backsector->ffloors)
-		|| (gr_frontsector->tag == gr_backsector->tag)))
+		if (!line->polyseg &&
+			!line->sidedef->midtexture
+			&& ((!gr_frontsector->ffloors && !gr_backsector->ffloors)
+				|| (gr_frontsector->tag == gr_backsector->tag)))
 			return; // line is empty, don't even bother
 
 		goto clippass; // treat like wide open window instead
@@ -2957,8 +2943,6 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord)
 #endif
 }
 
-#ifdef POLYOBJECTS
-
 //
 // HWR_AddPolyObjectSegs
 //
@@ -3001,7 +2985,6 @@ static inline void HWR_AddPolyObjectSegs(void)
 	Z_Free(gr_fakeline);
 }
 
-#ifdef POLYOBJECTS_PLANES
 static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight,
 									FBITFIELD blendmode, UINT8 lightlevel, levelflat_t *levelflat, sector_t *FOFsector,
 									UINT8 alpha, extracolormap_t *planecolormap)
@@ -3256,8 +3239,6 @@ static void HWR_AddPolyObjectPlanes(void)
 		}
 	}
 }
-#endif
-#endif
 
 // -----------------+
 // HWR_Subsector    : Determine floor/ceiling planes.
@@ -3585,7 +3566,6 @@ static void HWR_Subsector(size_t num)
 #endif
 #endif //doplanes
 
-#ifdef POLYOBJECTS
 	// Draw all the polyobjects in this subsector
 	if (sub->polyList)
 	{
@@ -3606,15 +3586,12 @@ static void HWR_Subsector(size_t num)
 		// Draw polyobject lines.
 		HWR_AddPolyObjectSegs();
 
-#ifdef POLYOBJECTS_PLANES
 		if (sub->validcount != validcount) // This validcount situation seems to let us know that the floors have already been drawn.
 		{
 			// Draw polyobject planes
 			HWR_AddPolyObjectPlanes();
 		}
-#endif
 	}
-#endif
 
 // Hurder ici se passe les choses INT32�essantes!
 // on vient de tracer le sol et le plafond
@@ -3637,14 +3614,8 @@ static void HWR_Subsector(size_t num)
 		while (count--)
 		{
 
-			if (!line->glseg
-#ifdef POLYOBJECTS
-			    && !line->polyseg // ignore segs that belong to polyobjects
-#endif
-			)
-			{
+			if (!line->glseg && !line->polyseg) // ignore segs that belong to polyobjects
 				HWR_AddLine(line);
-			}
 			line++;
 		}
 	}
diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c
index bc8d20e8e..5aae73284 100644
--- a/src/lua_blockmaplib.c
+++ b/src/lua_blockmaplib.c
@@ -80,9 +80,7 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th
 {
 	INT32 offset;
 	const INT32 *list; // Big blockmap
-#ifdef POLYOBJECTS
 	polymaplink_t *plink; // haleyjd 02/22/06
-#endif
 	line_t *ld;
 
 	if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
@@ -90,7 +88,6 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th
 
 	offset = y*bmapwidth + x;
 
-#ifdef POLYOBJECTS
 	// haleyjd 02/22/06: consider polyobject lines
 	plink = polyblocklinks[offset];
 
@@ -133,7 +130,6 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th
 		}
 		plink = (polymaplink_t *)(plink->link.next);
 	}
-#endif
 
 	offset = *(blockmap + offset); // offset = blockmap[y*bmapwidth+x];
 
diff --git a/src/p_map.c b/src/p_map.c
index 0c21e3e69..0fade4847 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -2157,7 +2157,6 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 
 	BMBOUNDFIX(xl, xh, yl, yh);
 
-#ifdef POLYOBJECTS
 	// Check polyobjects and see if tmfloorz/tmceilingz need to be altered
 	{
 		validcount++;
@@ -2229,7 +2228,6 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 				}
 			}
 	}
-#endif
 
 	// tmfloorthing is set when tmfloorz comes from a thing's top
 	tmfloorthing = NULL;
@@ -2387,7 +2385,6 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
 
 	BMBOUNDFIX(xl, xh, yl, yh);
 
-#ifdef POLYOBJECTS
 	// Check polyobjects and see if tmfloorz/tmceilingz need to be altered
 	{
 		validcount++;
@@ -2458,7 +2455,6 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
 				}
 			}
 	}
-#endif
 
 	// check lines
 	for (bx = xl; bx <= xh; bx++)
diff --git a/src/p_maputl.c b/src/p_maputl.c
index bfca72eda..b0289db36 100644
--- a/src/p_maputl.c
+++ b/src/p_maputl.c
@@ -451,7 +451,6 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 	I_Assert(back != NULL);
 
 	openfloorrover = openceilingrover = NULL;
-#ifdef POLYOBJECTS
 	if (linedef->polyobj)
 	{
 		// set these defaults so that polyobjects don't interfere with collision above or below them
@@ -462,7 +461,6 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 		opentopslope = openbottomslope = NULL;
 	}
 	else
-#endif
 	{ // Set open and high/low values here
 		fixed_t frontheight, backheight;
 
@@ -517,7 +515,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 				texheight = textures[texnum]->height << FRACBITS;
 
 				// Set texbottom and textop to the Z coordinates of the texture's boundaries
-#if 0 // #ifdef POLYOBJECTS
+#if 0
 				// don't remove this code unless solid midtextures
 				// on non-solid polyobjects should NEVER happen in the future
 				if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) {
@@ -560,7 +558,6 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 				}
 			}
 		}
-#ifdef POLYOBJECTS
 		if (linedef->polyobj)
 		{
 			// Treat polyobj's backsector like a 3D Floor
@@ -597,94 +594,95 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 			// otherwise don't do anything special, pretend there's nothing else there
 		}
 		else
-#endif
-		// Check for fake floors in the sector.
-		if (front->ffloors || back->ffloors)
 		{
-			ffloor_t *rover;
-			fixed_t delta1, delta2;
-
-			// Check for frontsector's fake floors
-			for (rover = front->ffloors; rover; rover = rover->next)
+			// Check for fake floors in the sector.
+			if (front->ffloors || back->ffloors)
 			{
-				fixed_t topheight, bottomheight;
-				if (!(rover->flags & FF_EXISTS))
-					continue;
+				ffloor_t *rover;
+				fixed_t delta1, delta2;
 
-				if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover)))
-					;
-				else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
-					|| (rover->flags & FF_BLOCKOTHERS && !mobj->player)))
-					continue;
-
-				topheight = P_GetFOFTopZ(mobj, front, rover, tmx, tmy, linedef);
-				bottomheight = P_GetFOFBottomZ(mobj, front, rover, tmx, tmy, linedef);
-
-				delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
-				delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
-
-				if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF
+				// Check for frontsector's fake floors
+				for (rover = front->ffloors; rover; rover = rover->next)
 				{
-					if (bottomheight < opentop) {
-						opentop = bottomheight;
-						opentopslope = *rover->b_slope;
-						openceilingrover = rover;
+					fixed_t topheight, bottomheight;
+					if (!(rover->flags & FF_EXISTS))
+						continue;
+
+					if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover)))
+						;
+					else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
+						|| (rover->flags & FF_BLOCKOTHERS && !mobj->player)))
+						continue;
+
+					topheight = P_GetFOFTopZ(mobj, front, rover, tmx, tmy, linedef);
+					bottomheight = P_GetFOFBottomZ(mobj, front, rover, tmx, tmy, linedef);
+
+					delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
+					delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
+
+					if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF
+					{
+						if (bottomheight < opentop) {
+							opentop = bottomheight;
+							opentopslope = *rover->b_slope;
+							openceilingrover = rover;
+						}
+						else if (bottomheight < highceiling)
+							highceiling = bottomheight;
+					}
+
+					if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
+					{
+						if (topheight > openbottom) {
+							openbottom = topheight;
+							openbottomslope = *rover->t_slope;
+							openfloorrover = rover;
+						}
+						else if (topheight > lowfloor)
+							lowfloor = topheight;
 					}
-					else if (bottomheight < highceiling)
-						highceiling = bottomheight;
 				}
 
-				if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
+				// Check for backsectors fake floors
+				for (rover = back->ffloors; rover; rover = rover->next)
 				{
-					if (topheight > openbottom) {
-						openbottom = topheight;
-						openbottomslope = *rover->t_slope;
-						openfloorrover = rover;
+					fixed_t topheight, bottomheight;
+					if (!(rover->flags & FF_EXISTS))
+						continue;
+
+					if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover)))
+						;
+					else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
+						|| (rover->flags & FF_BLOCKOTHERS && !mobj->player)))
+						continue;
+
+					topheight = P_GetFOFTopZ(mobj, back, rover, tmx, tmy, linedef);
+					bottomheight = P_GetFOFBottomZ(mobj, back, rover, tmx, tmy, linedef);
+
+					delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
+					delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
+
+					if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF
+					{
+						if (bottomheight < opentop) {
+							opentop = bottomheight;
+							opentopslope = *rover->b_slope;
+							openceilingrover = rover;
+						}
+						else if (bottomheight < highceiling)
+							highceiling = bottomheight;
 					}
-					else if (topheight > lowfloor)
-						lowfloor = topheight;
-				}
-			}
 
-			// Check for backsectors fake floors
-			for (rover = back->ffloors; rover; rover = rover->next)
-			{
-				fixed_t topheight, bottomheight;
-				if (!(rover->flags & FF_EXISTS))
-					continue;
-
-				if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover)))
-					;
-				else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
-					|| (rover->flags & FF_BLOCKOTHERS && !mobj->player)))
-					continue;
-
-				topheight = P_GetFOFTopZ(mobj, back, rover, tmx, tmy, linedef);
-				bottomheight = P_GetFOFBottomZ(mobj, back, rover, tmx, tmy, linedef);
-
-				delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2)));
-				delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
-
-				if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF
-				{
-					if (bottomheight < opentop) {
-						opentop = bottomheight;
-						opentopslope = *rover->b_slope;
-						openceilingrover = rover;
+					if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
+					{
+						if (topheight > openbottom) {
+							openbottom = topheight;
+							openbottomslope = *rover->t_slope;
+							openfloorrover = rover;
+						}
+						else if (topheight > lowfloor)
+							lowfloor = topheight;
 					}
-					else if (bottomheight < highceiling)
-						highceiling = bottomheight;
-				}
-
-				if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF
-				{
-					if (topheight > openbottom) {
-						openbottom = topheight;
-						openbottomslope = *rover->t_slope;
-						openfloorrover = rover;
-					}
-					else if (topheight > lowfloor)
-						lowfloor = topheight;
 				}
 			}
 		}
@@ -934,9 +932,7 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
 {
 	INT32 offset;
 	const INT32 *list; // Big blockmap
-#ifdef POLYOBJECTS
 	polymaplink_t *plink; // haleyjd 02/22/06
-#endif
 	line_t *ld;
 
 	if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
@@ -944,7 +940,6 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
 
 	offset = y*bmapwidth + x;
 
-#ifdef POLYOBJECTS
 	// haleyjd 02/22/06: consider polyobject lines
 	plink = polyblocklinks[offset];
 
@@ -968,7 +963,6 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
 		}
 		plink = (polymaplink_t *)(plink->link.next);
 	}
-#endif
 
 	offset = *(blockmap + offset); // offset = blockmap[y*bmapwidth+x];
 
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 29fe1a57c..c78ec4a53 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -2895,7 +2895,6 @@ static void P_PlayerZMovement(mobj_t *mo)
 			mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack
 
 			{
-#ifdef POLYOBJECTS
 				// Check if we're on a polyobject
 				// that triggers a linedef executor.
 				msecnode_t *node;
@@ -2955,8 +2954,6 @@ static void P_PlayerZMovement(mobj_t *mo)
 				}
 
 			if (!stopmovecut)
-#endif
-
 				// Cut momentum in half when you hit the ground and
 				// aren't pressing any controls.
 				if (!(mo->player->cmd.forwardmove || mo->player->cmd.sidemove) && !mo->player->cmomx && !mo->player->cmomy && !(mo->player->pflags & PF_SPINNING))
diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 7e1ff1f49..0431707ac 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -28,12 +28,6 @@
 #include "r_state.h"
 #include "r_defs.h"
 
-
-#define POLYOBJECTS
-
-
-#ifdef POLYOBJECTS
-
 /*
    Theory behind Polyobjects:
 
@@ -3152,6 +3146,4 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata)
 	return 1;
 }
 
-#endif // ifdef POLYOBJECTS
-
 // EOF
diff --git a/src/p_polyobj.h b/src/p_polyobj.h
index d56701d2d..7dfc90ce9 100644
--- a/src/p_polyobj.h
+++ b/src/p_polyobj.h
@@ -18,8 +18,6 @@
 #include "p_mobj.h"
 #include "r_defs.h"
 
-// haleyjd: temporary define
-#ifdef POLYOBJECTS
 //
 // Defines
 //
@@ -353,8 +351,6 @@ extern polyobj_t *PolyObjects;
 extern INT32 numPolyObjects;
 extern polymaplink_t **polyblocklinks; // polyobject blockmap
 
-#endif // ifdef POLYOBJECTS
-
 #endif
 
 // EOF
diff --git a/src/p_saveg.c b/src/p_saveg.c
index e8c6593fa..34bd3724b 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1300,7 +1300,6 @@ typedef enum
 	tc_planedisplace,
 	tc_dynslopeline,
 	tc_dynslopevert,
-#ifdef POLYOBJECTS
 	tc_polyrotate, // haleyjd 03/26/06: polyobjects
 	tc_polymove,
 	tc_polywaypoint,
@@ -1310,7 +1309,6 @@ typedef enum
 	tc_polydisplace,
 	tc_polyrotdisplace,
 	tc_polyfade,
-#endif
 	tc_end
 } specials_e;
 
@@ -1991,7 +1989,6 @@ static inline void SaveDynamicSlopeThinker(const thinker_t *th, const UINT8 type
     WRITEMEM(save_p, ht->vex, sizeof(ht->vex));
 }
 
-#ifdef POLYOBJECTS
 static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type)
 {
 	const polyrotate_t *ht = (const void *)th;
@@ -2100,7 +2097,6 @@ static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type)
 	WRITEINT32(save_p, ht->duration);
 	WRITEINT32(save_p, ht->timer);
 }
-#endif
 
 static void P_NetArchiveThinkers(void)
 {
@@ -2272,7 +2268,6 @@ static void P_NetArchiveThinkers(void)
 				SavePlaneDisplaceThinker(th, tc_planedisplace);
 				continue;
 			}
-#ifdef POLYOBJECTS
 			else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate)
 			{
 				SavePolyrotatetThinker(th, tc_polyrotate);
@@ -2318,7 +2313,6 @@ static void P_NetArchiveThinkers(void)
 				SavePolyfadeThinker(th, tc_polyfade);
 				continue;
 			}
-#endif
 			else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine)
 			{
 				SaveDynamicSlopeThinker(th, tc_dynslopeline);
@@ -3138,7 +3132,6 @@ static inline thinker_t* LoadDynamicSlopeThinker(actionf_p1 thinker)
 	return &ht->thinker;
 }
 
-#ifdef POLYOBJECTS
 static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker)
 {
 	polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
@@ -3255,7 +3248,6 @@ static thinker_t* LoadPolyfadeThinker(actionf_p1 thinker)
 	ht->timer = READINT32(save_p);
 	return &ht->thinker;
 }
-#endif
 
 static void P_NetUnArchiveThinkers(void)
 {
@@ -3416,7 +3408,6 @@ static void P_NetUnArchiveThinkers(void)
 				case tc_planedisplace:
 					th = LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace);
 					break;
-#ifdef POLYOBJECTS
 				case tc_polyrotate:
 					th = LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate);
 					break;
@@ -3453,7 +3444,6 @@ static void P_NetUnArchiveThinkers(void)
 				case tc_polyfade:
 					th = LoadPolyfadeThinker((actionf_p1)T_PolyObjFade);
 					break;
-#endif
 
 				case tc_dynslopeline:
 					th = LoadDynamicSlopeThinker((actionf_p1)T_DynamicSlopeLine);
@@ -3515,7 +3505,6 @@ static void P_NetUnArchiveThinkers(void)
 //
 // haleyjd 03/26/06: PolyObject saving code
 //
-#ifdef POLYOBJECTS
 #define PD_FLAGS  0x01
 #define PD_TRANS   0x02
 
@@ -3604,7 +3593,6 @@ static inline void P_UnArchivePolyObjects(void)
 	for (i = 0; i < numSavedPolys; ++i)
 		P_UnArchivePolyObj(&PolyObjects[i]);
 }
-#endif
 
 static inline void P_FinishMobjs(void)
 {
@@ -4078,9 +4066,7 @@ void P_SaveNetGame(void)
 	if (gamestate == GS_LEVEL)
 	{
 		P_NetArchiveWorld();
-#ifdef POLYOBJECTS
 		P_ArchivePolyObjects();
-#endif
 		P_NetArchiveThinkers();
 		P_NetArchiveSpecials();
 		P_NetArchiveColormaps();
@@ -4118,9 +4104,7 @@ boolean P_LoadNetGame(void)
 	if (gamestate == GS_LEVEL)
 	{
 		P_NetUnArchiveWorld();
-#ifdef POLYOBJECTS
 		P_UnArchivePolyObjects();
-#endif
 		P_NetUnArchiveThinkers();
 		P_NetUnArchiveSpecials();
 		P_NetUnArchiveColormaps();
diff --git a/src/p_setup.c b/src/p_setup.c
index 8c73b85e6..b3b618e51 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -953,9 +953,7 @@ static void P_InitializeLinedef(line_t *ld)
 	ld->splats = NULL;
 #endif
 	ld->firsttag = ld->nexttag = -1;
-#ifdef POLYOBJECTS
 	ld->polyobj = NULL;
-#endif
 
 	ld->text = NULL;
 	ld->callcount = 0;
@@ -1869,10 +1867,8 @@ static void P_InitializeSeg(seg_t *seg)
 
 	seg->numlights = 0;
 	seg->rlights = NULL;
-#ifdef POLYOBJECTS
 	seg->polyseg = NULL;
 	seg->dontrenderme = false;
-#endif
 }
 
 static void P_LoadSegs(UINT8 *data)
@@ -2235,11 +2231,9 @@ static boolean P_LoadBlockMap(UINT8 *data, size_t count)
 	blocklinks = Z_Calloc(count, PU_LEVEL, NULL);
 	blockmap = blockmaplump+4;
 
-#ifdef POLYOBJECTS
 	// haleyjd 2/22/06: setup polyobject blockmap
 	count = sizeof(*polyblocklinks) * bmapwidth * bmapheight;
 	polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL);
-#endif
 	return true;
 }
 
@@ -2490,11 +2484,9 @@ static void P_CreateBlockMap(void)
 		blocklinks = Z_Calloc(count, PU_LEVEL, NULL);
 		blockmap = blockmaplump + 4;
 
-#ifdef POLYOBJECTS
 		// haleyjd 2/22/06: setup polyobject blockmap
 		count = sizeof(*polyblocklinks) * bmapwidth * bmapheight;
 		polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL);
-#endif
 	}
 }
 
diff --git a/src/p_sight.c b/src/p_sight.c
index 3d1ee9e60..3e44281d0 100644
--- a/src/p_sight.c
+++ b/src/p_sight.c
@@ -100,7 +100,6 @@ static fixed_t P_InterceptVector2(divline_t *v2, divline_t *v1)
 	return frac;
 }
 
-#ifdef POLYOBJECTS
 static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los)
 {
 	size_t i;
@@ -169,7 +168,6 @@ static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los)
 
 	return true;
 }
-#endif
 
 //
 // P_CrossSubsector
@@ -180,9 +178,7 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
 {
 	seg_t *seg;
 	INT32 count;
-#ifdef POLYOBJECTS
 	polyobj_t *po; // haleyjd 02/23/06
-#endif
 
 #ifdef RANGECHECK
 	if (num >= numsubsectors)
@@ -192,7 +188,6 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
 	// haleyjd 02/23/06: this assignment should be after the above check
 	seg = segs + subsectors[num].firstline;
 
-#ifdef POLYOBJECTS
 	// haleyjd 02/23/06: check polyobject lines
 	if ((po = subsectors[num].polyList))
 	{
@@ -207,7 +202,6 @@ static boolean P_CrossSubsector(size_t num, register los_t *los)
 			po = (polyobj_t *)(po->link.next);
 		}
 	}
-#endif
 
 	for (count = subsectors[num].numlines; --count >= 0; seg++)  // check lines
 	{
@@ -413,15 +407,10 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2)
 
 	// killough 11/98: shortcut for melee situations
 	// same subsector? obviously visible
-#ifndef POLYOBJECTS
-	if (t1->subsector == t2->subsector)
-		return true;
-#else
 	// haleyjd 02/23/06: can't do this if there are polyobjects in the subsec
 	if (!t1->subsector->polyList &&
 		t1->subsector == t2->subsector)
 		return true;
-#endif
 
 	// An unobstructed LOS is possible.
 	// Now look from eyes of t1 to any part of t2.
diff --git a/src/p_spec.c b/src/p_spec.c
index cebab0902..c93846438 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -1076,9 +1076,6 @@ INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start)
 	}
 }
 
-// haleyjd: temporary define
-#ifdef POLYOBJECTS
-
 //
 // PolyDoor
 //
@@ -1401,8 +1398,6 @@ static boolean PolyRotDisplace(line_t *line)
 	return EV_DoPolyObjRotDisplace(&pdd);
 }
 
-#endif // ifdef POLYOBJECTS
-
 /** Changes a sector's tag.
   * Used by the linedef executor tag changer and by crumblers.
   *
@@ -4010,7 +4005,6 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			}
 			break;
 
-#ifdef POLYOBJECTS
 		case 480: // Polyobj_DoorSlide
 		case 481: // Polyobj_DoorSwing
 			PolyDoor(line);
@@ -4040,7 +4034,6 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 		case 492:
 			PolyFade(line);
 			break;
-#endif
 
 		default:
 			break;
@@ -7281,7 +7274,6 @@ void P_SpawnSpecials(boolean fromnetsave)
 
 	Z_Free(secthinkers);
 
-#ifdef POLYOBJECTS
 	// haleyjd 02/20/06: spawn polyobjects
 	Polyobj_InitLevel();
 
@@ -7302,7 +7294,6 @@ void P_SpawnSpecials(boolean fromnetsave)
 				break;
 		}
 	}
-#endif
 
 	P_RunLevelLoadExecutors();
 }
diff --git a/src/p_user.c b/src/p_user.c
index b2f40fe70..36a1054c6 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -3847,7 +3847,6 @@ static void P_DoTeeter(player_t *player)
 		BMBOUNDFIX(xl, xh, yl, yh);
 
 	// Polyobjects
-#ifdef POLYOBJECTS
 		validcount++;
 
 		for (by = yl; by <= yh; by++)
@@ -3941,7 +3940,6 @@ static void P_DoTeeter(player_t *player)
 					plink = (polymaplink_t *)(plink->link.next);
 				}
 			}
-#endif
 		if (teeter) // only bother with objects as a last resort if you were already teetering
 		{
 			mobj_t *oldtmthing = tmthing;
@@ -5702,11 +5700,7 @@ static void P_2dMovement(player_t *player)
 	}
 	else if (player->onconveyor == 4 && !P_IsObjectOnGround(player->mo)) // Actual conveyor belt
 		player->cmomx = player->cmomy = 0;
-	else if (player->onconveyor != 2 && player->onconveyor != 4
-#ifdef POLYOBJECTS
-				&& player->onconveyor != 1
-#endif
-	)
+	else if (player->onconveyor != 2 && player->onconveyor != 4 && player->onconveyor != 1)
 		player->cmomx = player->cmomy = 0;
 
 	player->rmomx = player->mo->momx - player->cmomx;
@@ -5901,11 +5895,7 @@ static void P_3dMovement(player_t *player)
 	}
 	else if (player->onconveyor == 4 && !P_IsObjectOnGround(player->mo)) // Actual conveyor belt
 		player->cmomx = player->cmomy = 0;
-	else if (player->onconveyor != 2 && player->onconveyor != 4
-#ifdef POLYOBJECTS
-				&& player->onconveyor != 1
-#endif
-	)
+	else if (player->onconveyor != 2 && player->onconveyor != 4 && player->onconveyor != 1)
 		player->cmomx = player->cmomy = 0;
 
 	player->rmomx = player->mo->momx - player->cmomx;
@@ -10235,7 +10225,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
 			}
 		}
 
-#ifdef POLYOBJECTS
 	// Check polyobjects and see if floorz/ceilingz need to be altered
 	{
 		INT32 xl, xh, yl, yh, bx, by;
@@ -10314,7 +10303,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
 				}
 			}
 	}
-#endif
 
 		// crushed camera
 		if (myceilingz <= myfloorz + thiscam->height && !resetcalled && !cameranoclip)
@@ -11725,10 +11713,8 @@ void P_PlayerThink(player_t *player)
 	P_MobjCheckWater(player->mo);
 
 #ifndef SECTORSPECIALSAFTERTHINK
-#ifdef POLYOBJECTS
 	if (player->onconveyor != 1 || !P_IsObjectOnGround(player->mo))
-#endif
-	player->onconveyor = 0;
+		player->onconveyor = 0;
 	// check special sectors : damage & secrets
 
 	if (!player->spectator)
@@ -12086,12 +12072,10 @@ void P_PlayerThink(player_t *player)
 	// it lasts for one tic.
 	player->pflags &= ~PF_FULLSTASIS;
 
-#ifdef POLYOBJECTS
 	if (player->onconveyor == 1)
 		player->onconveyor = 3;
 	else if (player->onconveyor == 3)
 		player->cmomy = player->cmomx = 0;
-#endif
 
 	P_DoSuperStuff(player);
 	P_CheckSneakerAndLivesTimer(player);
@@ -12424,10 +12408,8 @@ void P_PlayerAfterThink(player_t *player)
 	cmd = &player->cmd;
 
 #ifdef SECTORSPECIALSAFTERTHINK
-#ifdef POLYOBJECTS
 	if (player->onconveyor != 1 || !P_IsObjectOnGround(player->mo))
-#endif
-	player->onconveyor = 0;
+		player->onconveyor = 0;
 	// check special sectors : damage & secrets
 
 	if (!player->spectator)
diff --git a/src/r_bsp.c b/src/r_bsp.c
index 77ab2a82f..3bd023dbf 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -354,9 +354,7 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
 boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back)
 {
 	return (
-#ifdef POLYOBJECTS
 		!line->polyseg &&
-#endif
 		back->ceilingpic == front->ceilingpic
 		&& back->floorpic == front->floorpic
 		&& back->f_slope == front->f_slope
@@ -482,13 +480,10 @@ static void R_AddLine(seg_t *line)
 
 	if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then
 	{
-		if (
-#ifdef POLYOBJECTS
-		!line->polyseg &&
-#endif
-		!line->sidedef->midtexture
-		&& ((!frontsector->ffloors && !backsector->ffloors)
-		|| (frontsector->tag == backsector->tag)))
+		if (!line->polyseg &&
+			!line->sidedef->midtexture
+			&& ((!frontsector->ffloors && !backsector->ffloors)
+				|| (frontsector->tag == backsector->tag)))
 			return; // line is empty, don't even bother
 
 		goto clippass; // treat like wide open window instead
@@ -654,8 +649,6 @@ static boolean R_CheckBBox(const fixed_t *bspcoord)
 	return true;
 }
 
-#ifdef POLYOBJECTS
-
 size_t numpolys;        // number of polyobjects in current subsector
 size_t num_po_ptrs;     // number of polyobject pointers allocated
 polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
@@ -819,7 +812,6 @@ static void R_AddPolyObjects(subsector_t *sub)
 			R_AddLine(po_ptrs[i]->segs[j]);
 	}
 }
-#endif
 
 //
 // R_Subsector
@@ -896,11 +888,7 @@ static void R_Subsector(size_t num)
 		|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum))
 	{
 		floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel,
-			frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL
-#ifdef POLYOBJECTS_PLANES
-			, NULL
-#endif
-			, frontsector->f_slope);
+			frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL, NULL, frontsector->f_slope);
 	}
 	else
 		floorplane = NULL;
@@ -911,11 +899,7 @@ static void R_Subsector(size_t num)
 	{
 		ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic,
 			ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle,
-			ceilingcolormap, NULL
-#ifdef POLYOBJECTS_PLANES
-			, NULL
-#endif
-			, frontsector->c_slope);
+			ceilingcolormap, NULL, NULL, frontsector->c_slope);
 	}
 	else
 		ceilingplane = NULL;
@@ -963,11 +947,7 @@ static void R_Subsector(size_t num)
 
 				ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic,
 					*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs,
-					*rover->bottomyoffs, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover
-#ifdef POLYOBJECTS_PLANES
-					, NULL
-#endif
-					, *rover->b_slope);
+					*rover->bottomyoffs, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope);
 
 				ffloor[numffloors].slope = *rover->b_slope;
 
@@ -1000,11 +980,7 @@ static void R_Subsector(size_t num)
 
 				ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic,
 					*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle,
-					*frontsector->lightlist[light].extra_colormap, rover
-#ifdef POLYOBJECTS_PLANES
-					, NULL
-#endif
-					, *rover->t_slope);
+					*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope);
 
 				ffloor[numffloors].slope = *rover->t_slope;
 
@@ -1019,7 +995,6 @@ static void R_Subsector(size_t num)
 		}
 	}
 
-#ifdef POLYOBJECTS_PLANES
 	// Polyobjects have planes, too!
 	if (sub->polyList)
 	{
@@ -1085,7 +1060,6 @@ static void R_Subsector(size_t num)
 			po = (polyobj_t *)(po->link.next);
 		}
 	}
-#endif
 
 #ifdef FLOORSPLATS
 	if (sub->splats)
@@ -1108,21 +1082,15 @@ static void R_Subsector(size_t num)
 
 	firstseg = NULL;
 
-#ifdef POLYOBJECTS
 	// haleyjd 02/19/06: draw polyobjects before static lines
 	if (sub->polyList)
 		R_AddPolyObjects(sub);
-#endif
 
 	while (count--)
 	{
 //		CONS_Debug(DBG_GAMELOGIC, "Adding normal line %d...(%d)\n", line->linedef-lines, leveltime);
-		if (!line->glseg
-#ifdef POLYOBJECTS
-		&& !line->polyseg // ignore segs that belong to polyobjects
-#endif
-		)
-		R_AddLine(line);
+		if (!line->glseg && !line->polyseg) // ignore segs that belong to polyobjects
+			R_AddLine(line);
 		line++;
 		curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so stuff doesn't try using it for other things */
 	}
diff --git a/src/r_bsp.h b/src/r_bsp.h
index 1562b79f6..e2da8ebaf 100644
--- a/src/r_bsp.h
+++ b/src/r_bsp.h
@@ -40,13 +40,11 @@ void R_PortalClearClipSegs(INT32 start, INT32 end);
 void R_ClearDrawSegs(void);
 void R_RenderBSPNode(INT32 bspnum);
 
-#ifdef POLYOBJECTS
 void R_SortPolyObjects(subsector_t *sub);
 
 extern size_t numpolys;        // number of polyobjects in current subsector
 extern size_t num_po_ptrs;     // number of polyobject pointers allocated
 extern polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers
-#endif
 
 sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel,
 	INT32 *ceilinglightlevel, boolean back);
diff --git a/src/r_defs.h b/src/r_defs.h
index 4a8f5be34..a36568192 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -28,8 +28,6 @@
 #include "m_aatree.h"
 #endif
 
-#define POLYOBJECTS
-
 //
 // ClipWallSegment
 // Clips the given range of columns
@@ -107,9 +105,7 @@ typedef struct
 	fixed_t z;         ///< Z coordinate.
 } degenmobj_t;
 
-#ifdef POLYOBJECTS
 #include "p_polyobj.h"
-#endif
 
 // Store fake planes in a resizable array insted of just by
 // heightsec. Allows for multiple fake planes.
@@ -434,9 +430,7 @@ typedef struct line_s
 	void *splats; // wallsplat_t list
 #endif
 	INT32 firsttag, nexttag; // improves searches for tags.
-#ifdef POLYOBJECTS
 	polyobj_t *polyobj; // Belongs to a polyobject?
-#endif
 
 	char *text; // a concatenation of all front and back texture names, for linedef specials that require a string.
 	INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0
@@ -479,9 +473,7 @@ typedef struct subsector_s
 	sector_t *sector;
 	INT16 numlines;
 	UINT16 firstline;
-#ifdef POLYOBJECTS
 	struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects
-#endif
 #if 1//#ifdef FLOORSPLATS
 	void *splats; // floorsplat_t list
 #endif
@@ -584,10 +576,8 @@ typedef struct seg_s
 	// Why slow things down by calculating lightlists for every thick side?
 	size_t numlights;
 	r_lightlist_t *rlights;
-#ifdef POLYOBJECTS
 	polyobj_t *polyseg;
 	boolean dontrenderme;
-#endif
 	boolean glseg;
 } seg_t;
 
diff --git a/src/r_plane.c b/src/r_plane.c
index ca5aa758e..9b5a94340 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -337,11 +337,7 @@ static visplane_t *new_visplane(unsigned hash)
 //
 visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 	fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap,
-	ffloor_t *pfloor
-#ifdef POLYOBJECTS_PLANES
-			, polyobj_t *polyobj
-#endif
-			, pslope_t *slope)
+	ffloor_t *pfloor, polyobj_t *polyobj, pslope_t *slope)
 {
 	visplane_t *check;
 	unsigned hash;
@@ -361,7 +357,6 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 		}
 	}
 
-#ifdef POLYOBJECTS_PLANES
 	if (polyobj)
 	{
 		if (polyobj->angle != 0)
@@ -376,7 +371,6 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 			yoff += polyobj->centerPt.y;
 		}
 	}
-#endif
 
 	// This appears to fix the Nimbus Ruins sky bug.
 	if (picnum == skyflatnum && pfloor)
@@ -390,12 +384,10 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 
 	for (check = visplanes[hash]; check; check = check->next)
 	{
-#ifdef POLYOBJECTS_PLANES
 		if (check->polyobj && pfloor)
 			continue;
 		if (polyobj != check->polyobj)
 			continue;
-#endif
 		if (height == check->height && picnum == check->picnum
 			&& lightlevel == check->lightlevel
 			&& xoff == check->xoffs && yoff == check->yoffs
@@ -426,9 +418,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 	check->viewz = viewz;
 	check->viewangle = viewangle;
 	check->plangle = plangle;
-#ifdef POLYOBJECTS_PLANES
 	check->polyobj = polyobj;
-#endif
 	check->slope = slope;
 
 	memset(check->top, 0xff, sizeof (check->top));
@@ -496,9 +486,7 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop)
 		new_pl->viewz = pl->viewz;
 		new_pl->viewangle = pl->viewangle;
 		new_pl->plangle = pl->plangle;
-#ifdef POLYOBJECTS_PLANES
 		new_pl->polyobj = pl->polyobj;
-#endif
 		new_pl->slope = pl->slope;
 		pl = new_pl;
 		pl->minx = start;
@@ -523,11 +511,9 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop)
 //	INT32 unionl, unionh;
 //	INT32 x;
 
-#ifdef POLYOBJECTS_PLANES
 	// Don't expand polyobject planes here - we do that on our own.
 	if (pl->polyobj)
 		return;
-#endif
 
 	if (pl->minx > start) pl->minx = start;
 	if (pl->maxx < stop)  pl->maxx = stop;
@@ -603,11 +589,7 @@ void R_DrawPlanes(void)
 	{
 		for (pl = visplanes[i]; pl; pl = pl->next)
 		{
-			if (pl->ffloor != NULL
-#ifdef POLYOBJECTS_PLANES
-			|| pl->polyobj != NULL
-#endif
-			)
+			if (pl->ffloor != NULL || pl->polyobj != NULL)
 				continue;
 
 			R_DrawSinglePlane(pl);
@@ -961,7 +943,6 @@ void R_DrawSinglePlane(visplane_t *pl)
 #endif
 	spanfunc = spanfuncs[BASEDRAWFUNC];
 
-#ifdef POLYOBJECTS_PLANES
 	if (pl->polyobj && pl->polyobj->translucency != 0)
 	{
 		spanfunctype = SPANDRAWFUNC_TRANS;
@@ -979,95 +960,98 @@ void R_DrawSinglePlane(visplane_t *pl)
 		else
 			light = LIGHTLEVELS-1;
 
-	} else
-#endif
-	if (pl->ffloor)
+	}
+	else
 	{
-		// Don't draw planes that shouldn't be drawn.
-		for (rover = pl->ffloor->target->ffloors; rover; rover = rover->next)
+		if (pl->ffloor)
 		{
-			if ((pl->ffloor->flags & FF_CUTEXTRA) && (rover->flags & FF_EXTRA))
+			// Don't draw planes that shouldn't be drawn.
+			for (rover = pl->ffloor->target->ffloors; rover; rover = rover->next)
 			{
-				if (pl->ffloor->flags & FF_EXTRA)
+				if ((pl->ffloor->flags & FF_CUTEXTRA) && (rover->flags & FF_EXTRA))
 				{
-					// The plane is from an extra 3D floor... Check the flags so
-					// there are no undesired cuts.
-					if (((pl->ffloor->flags & (FF_FOG|FF_SWIMMABLE)) == (rover->flags & (FF_FOG|FF_SWIMMABLE)))
-						&& pl->height < *rover->topheight
-						&& pl->height > *rover->bottomheight)
-						return;
+					if (pl->ffloor->flags & FF_EXTRA)
+					{
+						// The plane is from an extra 3D floor... Check the flags so
+						// there are no undesired cuts.
+						if (((pl->ffloor->flags & (FF_FOG|FF_SWIMMABLE)) == (rover->flags & (FF_FOG|FF_SWIMMABLE)))
+							&& pl->height < *rover->topheight
+							&& pl->height > *rover->bottomheight)
+							return;
+					}
 				}
 			}
-		}
 
-		if (pl->ffloor->flags & FF_TRANSLUCENT)
-		{
-			spanfunctype = SPANDRAWFUNC_TRANS;
-
-			// Hacked up support for alpha value in software mode Tails 09-24-2002
-			if (pl->ffloor->alpha < 12)
-				return; // Don't even draw it
-			else if (pl->ffloor->alpha < 38)
-				ds_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT);
-			else if (pl->ffloor->alpha < 64)
-				ds_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT);
-			else if (pl->ffloor->alpha < 89)
-				ds_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT);
-			else if (pl->ffloor->alpha < 115)
-				ds_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT);
-			else if (pl->ffloor->alpha < 140)
-				ds_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
-			else if (pl->ffloor->alpha < 166)
-				ds_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT);
-			else if (pl->ffloor->alpha < 192)
-				ds_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT);
-			else if (pl->ffloor->alpha < 217)
-				ds_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT);
-			else if (pl->ffloor->alpha < 243)
-				ds_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT);
-			else // Opaque, but allow transparent flat pixels
-				spanfunctype = SPANDRAWFUNC_SPLAT;
-
-			if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG)))
-				light = (pl->lightlevel >> LIGHTSEGSHIFT);
-			else
-				light = LIGHTLEVELS-1;
-		}
-		else if (pl->ffloor->flags & FF_FOG)
-		{
-			spanfunctype = SPANDRAWFUNC_FOG;
-			light = (pl->lightlevel >> LIGHTSEGSHIFT);
-		}
-		else light = (pl->lightlevel >> LIGHTSEGSHIFT);
-
-#ifndef NOWATER
-		if (pl->ffloor->flags & FF_RIPPLE)
-		{
-			INT32 top, bottom;
-
-			itswater = true;
-			if (spanfunctype == SPANDRAWFUNC_TRANS)
+			if (pl->ffloor->flags & FF_TRANSLUCENT)
 			{
-				spanfunctype = SPANDRAWFUNC_WATER;
+				spanfunctype = SPANDRAWFUNC_TRANS;
 
-				// Copy the current scene, ugh
-				top = pl->high-8;
-				bottom = pl->low+8;
+				// Hacked up support for alpha value in software mode Tails 09-24-2002
+				if (pl->ffloor->alpha < 12)
+					return; // Don't even draw it
+				else if (pl->ffloor->alpha < 38)
+					ds_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT);
+				else if (pl->ffloor->alpha < 64)
+					ds_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT);
+				else if (pl->ffloor->alpha < 89)
+					ds_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT);
+				else if (pl->ffloor->alpha < 115)
+					ds_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT);
+				else if (pl->ffloor->alpha < 140)
+					ds_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
+				else if (pl->ffloor->alpha < 166)
+					ds_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT);
+				else if (pl->ffloor->alpha < 192)
+					ds_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT);
+				else if (pl->ffloor->alpha < 217)
+					ds_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT);
+				else if (pl->ffloor->alpha < 243)
+					ds_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT);
+				else // Opaque, but allow transparent flat pixels
+					spanfunctype = SPANDRAWFUNC_SPLAT;
 
-				if (top < 0)
-					top = 0;
-				if (bottom > vid.height)
-					bottom = vid.height;
-
-				// Only copy the part of the screen we need
-				VID_BlitLinearScreen((splitscreen && viewplayer == &players[secondarydisplayplayer]) ? screens[0] + (top+(vid.height>>1))*vid.width : screens[0]+((top)*vid.width), screens[1]+((top)*vid.width),
-				                     vid.width, bottom-top,
-				                     vid.width, vid.width);
+				if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG)))
+					light = (pl->lightlevel >> LIGHTSEGSHIFT);
+				else
+					light = LIGHTLEVELS-1;
 			}
+			else if (pl->ffloor->flags & FF_FOG)
+			{
+				spanfunctype = SPANDRAWFUNC_FOG;
+				light = (pl->lightlevel >> LIGHTSEGSHIFT);
+			}
+			else light = (pl->lightlevel >> LIGHTSEGSHIFT);
+
+	#ifndef NOWATER
+			if (pl->ffloor->flags & FF_RIPPLE)
+			{
+				INT32 top, bottom;
+
+				itswater = true;
+				if (spanfunctype == SPANDRAWFUNC_TRANS)
+				{
+					spanfunctype = SPANDRAWFUNC_WATER;
+
+					// Copy the current scene, ugh
+					top = pl->high-8;
+					bottom = pl->low+8;
+
+					if (top < 0)
+						top = 0;
+					if (bottom > vid.height)
+						bottom = vid.height;
+
+					// Only copy the part of the screen we need
+					VID_BlitLinearScreen((splitscreen && viewplayer == &players[secondarydisplayplayer]) ? screens[0] + (top+(vid.height>>1))*vid.width : screens[0]+((top)*vid.width), screens[1]+((top)*vid.width),
+										 vid.width, bottom-top,
+										 vid.width, vid.width);
+				}
+			}
+	#endif
 		}
-#endif
+		else
+			light = (pl->lightlevel >> LIGHTSEGSHIFT);
 	}
-	else light = (pl->lightlevel >> LIGHTSEGSHIFT);
 
 	if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later
 		&& viewangle != pl->viewangle+pl->plangle)
diff --git a/src/r_plane.h b/src/r_plane.h
index a1a5b7a78..67fa19f38 100644
--- a/src/r_plane.h
+++ b/src/r_plane.h
@@ -47,9 +47,7 @@ typedef struct visplane_s
 	fixed_t xoffs, yoffs; // Scrolling flats.
 
 	struct ffloor_s *ffloor;
-#ifdef POLYOBJECTS_PLANES
 	polyobj_t *polyobj;
-#endif
 	pslope_t *slope;
 } visplane_t;
 
@@ -80,11 +78,7 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2);
 void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2);
 void R_DrawPlanes(void);
 visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle,
-	extracolormap_t *planecolormap, ffloor_t *ffloor
-#ifdef POLYOBJECTS_PLANES
-	, polyobj_t *polyobj
-#endif
-	, pslope_t *slope);
+	extracolormap_t *planecolormap, ffloor_t *ffloor, polyobj_t *polyobj, pslope_t *slope);
 visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop);
 void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
 void R_PlaneBounds(visplane_t *plane);
@@ -112,9 +106,7 @@ typedef struct planemgr_s
 	struct pslope_s *slope;
 
 	struct ffloor_s *ffloor;
-#ifdef POLYOBJECTS_PLANES
 	polyobj_t *polyobj;
-#endif
 } visffloor_t;
 
 extern visffloor_t ffloor[MAXFFLOORS];
diff --git a/src/r_segs.c b/src/r_segs.c
index b6b4ca44c..6a838be79 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -610,7 +610,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 				// draw the texture
 				col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
 
-//#ifdef POLYOBJECTS_PLANES
 #if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red
 				if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES))
 				{
@@ -1309,10 +1308,8 @@ static void R_RenderSegLoop (void)
 
 			for (i = 0; i < numffloors; i++)
 			{
-#ifdef POLYOBJECTS_PLANES
 				if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg))
 					continue;
-#endif
 
 				if (ffloor[i].height < viewz)
 				{
@@ -1325,18 +1322,19 @@ static void R_RenderSegLoop (void)
 					if (bottom_w > bottom)
 						bottom_w = bottom;
 
-#ifdef POLYOBJECTS_PLANES
 					// Polyobject-specific hack to fix plane leaking -Red
-					if (ffloor[i].polyobj && top_w >= bottom_w) {
+					if (ffloor[i].polyobj && top_w >= bottom_w)
+					{
 						ffloor[i].plane->top[rw_x] = 0xFFFF;
 						ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18
-					} else
-#endif
-
-					if (top_w <= bottom_w)
+					}
+					else
 					{
-						ffloor[i].plane->top[rw_x] = (INT16)top_w;
-						ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w;
+						if (top_w <= bottom_w)
+						{
+							ffloor[i].plane->top[rw_x] = (INT16)top_w;
+							ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w;
+						}
 					}
 				}
 				else if (ffloor[i].height > viewz)
@@ -1350,18 +1348,19 @@ static void R_RenderSegLoop (void)
 					if (bottom_w > bottom)
 						bottom_w = bottom;
 
-#ifdef POLYOBJECTS_PLANES
 					// Polyobject-specific hack to fix plane leaking -Red
-					if (ffloor[i].polyobj && top_w >= bottom_w) {
+					if (ffloor[i].polyobj && top_w >= bottom_w)
+					{
 						ffloor[i].plane->top[rw_x] = 0xFFFF;
 						ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18
-					} else
-#endif
-
-					if (top_w <= bottom_w)
+					}
+					else
 					{
-						ffloor[i].plane->top[rw_x] = (INT16)top_w;
-						ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w;
+						if (top_w <= bottom_w)
+						{
+							ffloor[i].plane->top[rw_x] = (INT16)top_w;
+							ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w;
+						}
 					}
 				}
 			}
@@ -1818,10 +1817,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	{
 		for (i = 0; i < numffloors; i++)
 		{
-#ifdef POLYOBJECTS_PLANES
 			if (ffloor[i].polyobj && (!ds_p->curline->polyseg || ffloor[i].polyobj != ds_p->curline->polyseg))
 				continue;
-#endif
 
 			if (ffloor[i].slope) {
 				ffloor[i].f_pos = P_GetZAt(ffloor[i].slope, segleft.x, segleft.y) - viewz;
@@ -2328,33 +2325,40 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 			maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0])
 
-#ifdef POLYOBJECTS
-			if (curline->polyseg) { // use REAL front and back floors please, so midtexture rendering isn't mucked up
+			if (curline->polyseg)
+			{ // use REAL front and back floors please, so midtexture rendering isn't mucked up
 				rw_midtextureslide = rw_midtexturebackslide = 0;
 				if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3))
 					rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz;
 				else
 					rw_midtexturemid = rw_midtextureback = min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz;
-			} else
-#endif
-			// Set midtexture starting height
-			if (linedef->flags & ML_EFFECT2) { // Ignore slopes when texturing
-				rw_midtextureslide = rw_midtexturebackslide = 0;
-				if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3))
-					rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz;
-				else
-					rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz;
+			}
+			else
+			{
+				// Set midtexture starting height
+				if (linedef->flags & ML_EFFECT2)
+				{ // Ignore slopes when texturing
+					rw_midtextureslide = rw_midtexturebackslide = 0;
+					if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3))
+						rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz;
+					else
+						rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz;
 
-			} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
-				rw_midtexturemid = worldbottom;
-				rw_midtextureslide = floorfrontslide;
-				rw_midtextureback = worldlow;
-				rw_midtexturebackslide = floorbackslide;
-			} else {
-				rw_midtexturemid = worldtop;
-				rw_midtextureslide = ceilingfrontslide;
-				rw_midtextureback = worldhigh;
-				rw_midtexturebackslide = ceilingbackslide;
+				}
+				else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3))
+				{
+					rw_midtexturemid = worldbottom;
+					rw_midtextureslide = floorfrontslide;
+					rw_midtextureback = worldlow;
+					rw_midtexturebackslide = floorbackslide;
+				}
+				else
+				{
+					rw_midtexturemid = worldtop;
+					rw_midtextureslide = ceilingfrontslide;
+					rw_midtextureback = worldhigh;
+					rw_midtexturebackslide = ceilingbackslide;
+				}
 			}
 			rw_midtexturemid += sidedef->rowoffset;
 			rw_midtextureback += sidedef->rowoffset;
@@ -2711,7 +2715,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					}
 				}
 			}
-#ifdef POLYOBJECTS_PLANES
 			if (curline->polyseg && frontsector && (curline->polyseg->flags & POF_RENDERPLANES))
 			{
 				while (i < numffloors && ffloor[i].polyobj != curline->polyseg) i++;
@@ -2750,7 +2753,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					i++;
 				}
 			}
-#endif
 
 			numbackffloors = i;
 		}
@@ -2804,7 +2806,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			for (i = 0; i < numffloors; i++)
 				R_ExpandPlane(ffloor[i].plane, rw_x, rw_stopx - 1);
 		}
-#ifdef POLYOBJECTS_PLANES
 		// FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red
 		if (curline->polyseg)
 		{
@@ -2819,7 +2820,6 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					ffloor[i].plane->maxx = rw_stopx - 1;
 			}
 		}
-#endif
 	}
 
 #ifdef WALLSPLATS
diff --git a/src/r_things.c b/src/r_things.c
index b4ffd4408..361cb1961 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1140,7 +1140,6 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
 	}
 
 #if 0 // Unfortunately, this drops CEZ2 down to sub-17 FPS on my i7.
-//#ifdef POLYOBJECTS
 	// Check polyobjects and see if floorz needs to be altered, for rings only because they don't update floorz
 	if (thing->type == MT_RING)
 	{
@@ -2271,7 +2270,6 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
 				entry->ffloor = ds->thicksides[i];
 			}
 		}
-#ifdef POLYOBJECTS_PLANES
 		// Check for a polyobject plane, but only if this is a front line
 		if (ds->curline->polyseg && ds->curline->polyseg->visplane && !ds->curline->side) {
 			plane = ds->curline->polyseg->visplane;
@@ -2287,7 +2285,6 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
 			}
 			ds->curline->polyseg->visplane = NULL;
 		}
-#endif
 		if (ds->maskedtexturecol)
 		{
 			entry = R_CreateDrawNode(head);
@@ -2335,7 +2332,6 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
 	if (tempskip)
 		return;
 
-#ifdef POLYOBJECTS_PLANES
 	// find all the remaining polyobject planes and add them on the end of the list
 	// probably this is a terrible idea if we wanted them to be sorted properly
 	// but it works getting them in for now
@@ -2356,7 +2352,6 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
 		// note: no seg is set, for what should be obvious reasons
 		PolyObjects[i].visplane = NULL;
 	}
-#endif
 
 	// No vissprites in this mask?
 	if (mask->vissprites[1] - mask->vissprites[0] == 0)

From 1528f2aef8814e3841cf9e20d63d3fe9a7894008 Mon Sep 17 00:00:00 2001
From: Monster Iestyn <iestynjealous@ntlworld.com>
Date: Sat, 2 May 2020 17:13:16 +0100
Subject: [PATCH 231/251] Fix drop shadow and rotsprite code to use SHORT()

---
 src/hardware/hw_main.c | 14 +++++++-------
 src/r_patch.c          | 14 ++++++++++----
 src/r_things.c         | 30 +++++++++++++++---------------
 3 files changed, 32 insertions(+), 26 deletions(-)

diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index be03ba083..927bad34c 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -4158,7 +4158,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale
 	HWR_GetPatch(gpatch);
 
 	scalemul = FixedMul(FRACUNIT - floordiff/640, scale);
-	scalemul = FixedMul(scalemul, (thing->radius*2) / gpatch->height);
+	scalemul = FixedMul(scalemul, (thing->radius*2) / SHORT(gpatch->height));
 
 	fscale = FIXED_TO_FLOAT(scalemul);
 	fx = FIXED_TO_FLOAT(thing->x);
@@ -4170,9 +4170,9 @@ static void HWR_DrawDropShadow(mobj_t *thing, gr_vissprite_t *spr, fixed_t scale
 	//  0--1
 
 	if (thing && fabsf(fscale - 1.0f) > 1.0E-36f)
-		offset = (gpatch->height/2) * fscale;
+		offset = (SHORT(gpatch->height)/2) * fscale;
 	else
-		offset = (float)(gpatch->height/2);
+		offset = (float)(SHORT(gpatch->height)/2);
 
 	shadowVerts[0].x = shadowVerts[3].x = fx - offset;
 	shadowVerts[2].x = shadowVerts[1].x = fx + offset;
@@ -5551,10 +5551,10 @@ static void HWR_ProjectSprite(mobj_t *thing)
 		rotsprite = sprframe->rotsprite.patch[rot][rollangle];
 		if (rotsprite != NULL)
 		{
-			spr_width = rotsprite->width << FRACBITS;
-			spr_height = rotsprite->height << FRACBITS;
-			spr_offset = rotsprite->leftoffset << FRACBITS;
-			spr_topoffset = rotsprite->topoffset << FRACBITS;
+			spr_width = SHORT(rotsprite->width) << FRACBITS;
+			spr_height = SHORT(rotsprite->height) << FRACBITS;
+			spr_offset = SHORT(rotsprite->leftoffset) << FRACBITS;
+			spr_topoffset = SHORT(rotsprite->topoffset) << FRACBITS;
 			// flip -> rotate, not rotate -> flip
 			flip = 0;
 		}
diff --git a/src/r_patch.c b/src/r_patch.c
index 9e31d4d19..ad4b3329a 100644
--- a/src/r_patch.c
+++ b/src/r_patch.c
@@ -1231,9 +1231,9 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
 		if (!R_CheckIfPatch(lump))
 			return;
 
-		width = patch->width;
-		height = patch->height;
-		leftoffset = patch->leftoffset;
+		width = SHORT(patch->width);
+		height = SHORT(patch->height);
+		leftoffset = SHORT(patch->leftoffset);
 
 		// rotation pivot
 		px = SPRITE_XCENTER;
@@ -1348,7 +1348,7 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
 			newpatch = R_MaskedFlatToPatch(rawdst, newwidth, newheight, 0, 0, &size);
 			{
 				newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px);
-				newpatch->topoffset = (newpatch->height / 2) + (patch->topoffset - py);
+				newpatch->topoffset = (newpatch->height / 2) + (SHORT(patch->topoffset) - py);
 			}
 
 			//BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer
@@ -1358,6 +1358,12 @@ void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, sp
 			// P_PrecacheLevel
 			if (devparm) spritememory += size;
 
+			// convert everything to little-endian, for big-endian support
+			newpatch->width = SHORT(newpatch->width);
+			newpatch->height = SHORT(newpatch->height);
+			newpatch->leftoffset = SHORT(newpatch->leftoffset);
+			newpatch->topoffset = SHORT(newpatch->topoffset);
+
 #ifdef HWRENDER
 			if (rendermode == render_opengl)
 			{
diff --git a/src/r_things.c b/src/r_things.c
index d2f3b4902..1956e1e7d 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -890,7 +890,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
 		vis->x2 = vid.width-1;
 
 	localcolfunc = (vis->cut & SC_VFLIP) ? R_DrawFlippedMaskedColumn : R_DrawMaskedColumn;
-	lengthcol = patch->height;
+	lengthcol = SHORT(patch->height);
 
 	// Split drawing loops for paper and non-paper to reduce conditional checks per sprite
 	if (vis->scalestep)
@@ -1235,8 +1235,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
 	yscale = FixedDiv(projectiony, tz);
 	shadowxscale = FixedMul(thing->radius*2, scalemul);
 	shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(floorz - viewz), tz));
-	shadowyscale = min(shadowyscale, shadowxscale) / patch->height;
-	shadowxscale /= patch->width;
+	shadowyscale = min(shadowyscale, shadowxscale) / SHORT(patch->height);
+	shadowxscale /= SHORT(patch->width);
 	shadowskew = 0;
 
 	if (floorslope)
@@ -1251,24 +1251,24 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
 		//CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope);
 
 		if (viewz < floorz)
-			shadowyscale += FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope);
+			shadowyscale += FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope);
 		else
-			shadowyscale -= FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope);
+			shadowyscale -= FixedMul(FixedMul(thing->radius*2 / SHORT(patch->height), scalemul), zslope);
 
 		shadowyscale = abs(shadowyscale);
 
 		shadowskew = xslope;
 	}
 
-	tx -= patch->width * shadowxscale/2;
+	tx -= SHORT(patch->width) * shadowxscale/2;
 	x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
 	if (x1 >= viewwidth) return;
 
-	tx += patch->width * shadowxscale;
+	tx += SHORT(patch->width) * shadowxscale;
 	x2 = ((centerxfrac + FixedMul(tx,xscale))>>FRACBITS); x2--;
 	if (x2 < 0 || x2 <= x1) return;
 
-	if (shadowyscale < FRACUNIT/patch->height) return; // fix some crashes?
+	if (shadowyscale < FRACUNIT/SHORT(patch->height)) return; // fix some crashes?
 
 	shadow = R_NewVisSprite();
 	shadow->patch = patch;
@@ -1283,8 +1283,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
 	shadow->dispoffset = vis->dispoffset - 5;
 	shadow->gx = thing->x;
 	shadow->gy = thing->y;
-	shadow->gzt = shadow->pz + shadow->patch->height * shadowyscale / 2;
-	shadow->gz = shadow->gzt - shadow->patch->height * shadowyscale;
+	shadow->gzt = shadow->pz + SHORT(patch->height) * shadowyscale / 2;
+	shadow->gz = shadow->gzt - SHORT(patch->height) * shadowyscale;
 	shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale));
 	if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
 		shadow->texturemid = FixedMul(shadow->texturemid, ((skin_t *)thing->skin)->highresscale);
@@ -1305,7 +1305,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
 
 	shadow->startfrac = 0;
 	//shadow->xiscale = 0x7ffffff0 / (shadow->xscale/2);
-	shadow->xiscale = (patch->width<<FRACBITS)/(x2-x1+1); // fuck it
+	shadow->xiscale = (SHORT(patch->width)<<FRACBITS)/(x2-x1+1); // fuck it
 
 	if (shadow->x1 > x1)
 		shadow->startfrac += shadow->xiscale*(shadow->x1-x1);
@@ -1534,10 +1534,10 @@ static void R_ProjectSprite(mobj_t *thing)
 		rotsprite = sprframe->rotsprite.patch[rot][rollangle];
 		if (rotsprite != NULL)
 		{
-			spr_width = rotsprite->width << FRACBITS;
-			spr_height = rotsprite->height << FRACBITS;
-			spr_offset = rotsprite->leftoffset << FRACBITS;
-			spr_topoffset = rotsprite->topoffset << FRACBITS;
+			spr_width = SHORT(rotsprite->width) << FRACBITS;
+			spr_height = SHORT(rotsprite->height) << FRACBITS;
+			spr_offset = SHORT(rotsprite->leftoffset) << FRACBITS;
+			spr_topoffset = SHORT(rotsprite->topoffset) << FRACBITS;
 			// flip -> rotate, not rotate -> flip
 			flip = 0;
 		}

From 887c25e04757c7e6af4f5c40a666842485da5394 Mon Sep 17 00:00:00 2001
From: Steel Titanium <steeltitanium1@gmail.com>
Date: Sat, 2 May 2020 17:39:55 -0400
Subject: [PATCH 232/251] Remove inline keyword from P_DoTwinSpin function

The compiler doesn't like this and will give you a "inlining failed in call to 'P_DoTwinSpin': call is unlikely and code size would grow" error
---
 src/p_user.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_user.c b/src/p_user.c
index 4991c3065..9df71587d 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -5004,7 +5004,7 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range)
 	player->pflags |= PF_THOKKED;
 }
 
-static inline void P_DoTwinSpin(player_t *player)
+static void P_DoTwinSpin(player_t *player)
 {
 	player->pflags &= ~PF_NOJUMPDAMAGE;
 	player->pflags |= P_GetJumpFlags(player) | PF_THOKKED;

From dd50990e85199f80d93ed19d2b419d9b944096b3 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 3 May 2020 15:22:13 +0200
Subject: [PATCH 233/251] Add "trigger egg capsule" linedef executor

---
 extras/conf/SRB2-22.cfg |  8 ++++++++
 src/p_spec.c            | 41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg
index ea783908a..75563e505 100644
--- a/extras/conf/SRB2-22.cfg
+++ b/extras/conf/SRB2-22.cfg
@@ -2218,6 +2218,13 @@ linedeftypes
 			prefix = "(462)";
 			flags8text = "[3] Set delay by backside sector";
 		}
+
+		464
+		{
+			title = "Trigger Egg Capsule";
+			prefix = "(464)";
+			flags64text = "[6] Don't end level";
+		}
 	}
 
 	linedefexecmisc
@@ -3704,6 +3711,7 @@ thingtypes
 			width = 8;
 			height = 16;
 			sprite = "internal:capsule";
+			angletext = "Tag";
 		}
 		292
 		{
diff --git a/src/p_spec.c b/src/p_spec.c
index cebab0902..e7a600875 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -4010,6 +4010,47 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			}
 			break;
 
+		case 464: // Trigger Egg Capsule
+			{
+				thinker_t *th;
+				mobj_t *mo2;
+
+				// Find the center of the Eggtrap and release all the pretty animals!
+				// The chimps are my friends.. heeheeheheehehee..... - LouisJM
+				for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
+				{
+					if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
+						continue;
+
+					mo2 = (mobj_t *)th;
+
+					if (mo2->type != MT_EGGTRAP)
+						continue;
+
+					if (!mo2->spawnpoint)
+						continue;
+
+					if (mo2->spawnpoint->angle != line->tag)
+						continue;
+
+					P_KillMobj(mo2, NULL, mo, 0);
+				}
+
+				if (!(line->flags & ML_NOCLIMB))
+				{
+					INT32 i;
+
+					// Mark all players with the time to exit thingy!
+					for (i = 0; i < MAXPLAYERS; i++)
+					{
+						if (!playeringame[i])
+							continue;
+						P_DoPlayerExit(&players[i]);
+					}
+				}
+			}
+			break;
+
 #ifdef POLYOBJECTS
 		case 480: // Polyobj_DoorSlide
 		case 481: // Polyobj_DoorSwing

From 1b66d1f936521262f33406095ae3d4f139b474f3 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 3 May 2020 15:57:18 +0200
Subject: [PATCH 234/251] Add object dye linedef executors to ZB config

---
 extras/conf/SRB2-22.cfg | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg
index ea783908a..1c1d11809 100644
--- a/extras/conf/SRB2-22.cfg
+++ b/extras/conf/SRB2-22.cfg
@@ -1908,6 +1908,27 @@ linedeftypes
 			prefix = "(333)";
 		}
 
+		334
+		{
+			title = "Object Dye - Continuous";
+			flags64text = "[6] Disable for this color";
+			prefix = "(334)";
+		}
+
+		335
+		{
+			title = "Object Dye - Each Time";
+			flags64text = "[6] Disable for this color";
+			prefix = "(335)";
+		}
+
+		336
+		{
+			title = "Object Dye - Once";
+			flags64text = "[6] Disable for this color";
+			prefix = "(336)";
+		}
+
 		399
 		{
 			title = "Level Load";
@@ -2218,6 +2239,12 @@ linedeftypes
 			prefix = "(462)";
 			flags8text = "[3] Set delay by backside sector";
 		}
+
+		463
+		{
+			title = "Dye Object";
+			prefix = "(463)";
+		}
 	}
 
 	linedefexecmisc

From 4b87bee759ce8e67069228688b7a32fab8f3c4b6 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 3 May 2020 17:56:49 +0200
Subject: [PATCH 235/251] Add level header options for setting special stage
 time and spheres requirements

---
 src/dehacked.c   | 4 ++++
 src/doomstat.h   | 2 ++
 src/lua_maplib.c | 4 ++++
 src/p_setup.c    | 2 ++
 src/p_spec.c     | 4 ++--
 5 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index e9d029be0..c05a8f444 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1863,6 +1863,10 @@ static void readlevelheader(MYFILE *f, INT32 num)
 			}
 			else if (fastcmp(word, "STARTRINGS"))
 				mapheaderinfo[num-1]->startrings = (UINT16)i;
+			else if (fastcmp(word, "SPECIALSTAGETIME"))
+				mapheaderinfo[num-1]->sstimer = i;
+			else if (fastcmp(word, "SPECIALSTAGESPHERES"))
+				mapheaderinfo[num-1]->ssspheres = i;
 			else
 				deh_warning("Level header %d: unknown word '%s'", num, word);
 		}
diff --git a/src/doomstat.h b/src/doomstat.h
index aedb120ff..e6a227a42 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -319,6 +319,8 @@ typedef struct
 
 	char selectheading[22]; ///< Level select heading. Allows for controllable grouping.
 	UINT16 startrings;      ///< Number of rings players start with.
+	INT32 sstimer;          ///< Timer for special stages.
+	UINT32 ssspheres;        ///< Sphere requirement in special stages.
 
 	// Title card.
 	char ltzzpatch[8];      ///< Zig zag patch.
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index d851c820e..1737216e3 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -2082,6 +2082,10 @@ static int mapheaderinfo_get(lua_State *L)
 		lua_pushinteger(L, header->menuflags);
 	else if (fastcmp(field,"startrings"))
 		lua_pushinteger(L, header->startrings);
+	else if (fastcmp(field, "sstimer"))
+		lua_pushinteger(L, header->sstimer);
+	else if (fastcmp(field, "ssspheres"))
+		lua_pushinteger(L, header->ssspheres);
 	// TODO add support for reading numGradedMares and grades
 	else {
 		// Read custom vars now
diff --git a/src/p_setup.c b/src/p_setup.c
index b3b618e51..1d1826a53 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -218,6 +218,8 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
 	mapheaderinfo[num]->typeoflevel = 0;
 	mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
 	mapheaderinfo[num]->startrings = 0;
+	mapheaderinfo[num]->sstimer = 90;
+	mapheaderinfo[num]->ssspheres = 1;
 	mapheaderinfo[num]->keywords[0] = '\0';
 	snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i));
 	mapheaderinfo[num]->musname[6] = 0;
diff --git a/src/p_spec.c b/src/p_spec.c
index c93846438..fafe2cdf3 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6249,8 +6249,8 @@ void P_InitSpecials(void)
 	gravity = FRACUNIT/2;
 
 	// Defaults in case levels don't have them set.
-	sstimer = 90*TICRATE + 6;
-	ssspheres = 1;
+	sstimer = mapheaderinfo[gamemap-1]->sstimer*TICRATE + 6;
+	ssspheres = mapheaderinfo[gamemap-1]->ssspheres;
 
 	CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false;
 

From 700b340827cbe8da1bee2afa423d3666be4fad5f Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 3 May 2020 18:33:18 +0200
Subject: [PATCH 236/251] Allow map-wide gravity to be set via level header

---
 src/dehacked.c   | 2 ++
 src/doomstat.h   | 3 ++-
 src/lua_maplib.c | 2 ++
 src/p_setup.c    | 1 +
 src/p_spec.c     | 2 +-
 5 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/dehacked.c b/src/dehacked.c
index c05a8f444..268f9943c 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1867,6 +1867,8 @@ static void readlevelheader(MYFILE *f, INT32 num)
 				mapheaderinfo[num-1]->sstimer = i;
 			else if (fastcmp(word, "SPECIALSTAGESPHERES"))
 				mapheaderinfo[num-1]->ssspheres = i;
+			else if (fastcmp(word, "GRAVITY"))
+				mapheaderinfo[num-1]->gravity = FLOAT_TO_FIXED(atof(word2));
 			else
 				deh_warning("Level header %d: unknown word '%s'", num, word);
 		}
diff --git a/src/doomstat.h b/src/doomstat.h
index e6a227a42..1ec03a86c 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -320,7 +320,8 @@ typedef struct
 	char selectheading[22]; ///< Level select heading. Allows for controllable grouping.
 	UINT16 startrings;      ///< Number of rings players start with.
 	INT32 sstimer;          ///< Timer for special stages.
-	UINT32 ssspheres;        ///< Sphere requirement in special stages.
+	UINT32 ssspheres;       ///< Sphere requirement in special stages.
+	fixed_t gravity;        ///< Map-wide gravity.
 
 	// Title card.
 	char ltzzpatch[8];      ///< Zig zag patch.
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index 1737216e3..ece42b8d3 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -2086,6 +2086,8 @@ static int mapheaderinfo_get(lua_State *L)
 		lua_pushinteger(L, header->sstimer);
 	else if (fastcmp(field, "ssspheres"))
 		lua_pushinteger(L, header->ssspheres);
+	else if (fastcmp(field, "gravity"))
+		lua_pushfixed(L, header->gravity);
 	// TODO add support for reading numGradedMares and grades
 	else {
 		// Read custom vars now
diff --git a/src/p_setup.c b/src/p_setup.c
index 1d1826a53..b4a5f2c3c 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -220,6 +220,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
 	mapheaderinfo[num]->startrings = 0;
 	mapheaderinfo[num]->sstimer = 90;
 	mapheaderinfo[num]->ssspheres = 1;
+	mapheaderinfo[num]->gravity = FRACUNIT/2;
 	mapheaderinfo[num]->keywords[0] = '\0';
 	snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i));
 	mapheaderinfo[num]->musname[6] = 0;
diff --git a/src/p_spec.c b/src/p_spec.c
index fafe2cdf3..2e5b1f44b 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -6246,7 +6246,7 @@ static void P_RunLevelLoadExecutors(void)
 void P_InitSpecials(void)
 {
 	// Set the default gravity. Custom gravity overrides this setting.
-	gravity = FRACUNIT/2;
+	gravity = mapheaderinfo[gamemap-1]->gravity;
 
 	// Defaults in case levels don't have them set.
 	sstimer = mapheaderinfo[gamemap-1]->sstimer*TICRATE + 6;

From 5de11441a195591b1f619fd42133c76051467372 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 3 May 2020 23:47:26 +0200
Subject: [PATCH 237/251] Remove "explicitly include line in polyobject" code
 which has never worked

---
 src/p_polyobj.c | 106 ++----------------------------------------------
 src/p_polyobj.h |   1 -
 2 files changed, 3 insertions(+), 104 deletions(-)

diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 0431707ac..9173aa12a 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -490,84 +490,6 @@ newseg:
 	CONS_Debug(DBG_POLYOBJ, "Polyobject %d is not closed\n", po->id);
 }
 
-/*
-// structure used to store segs during explicit search process
-typedef struct segitem_s
-{
-	seg_t *seg;
-	INT32   num;
-} segitem_t;
-
-//
-// Polyobj_segCompare
-//
-// Callback for qsort that compares two segitems.
-//
-static int Polyobj_segCompare(const void *s1, const void *s2)
-{
-	const segitem_t *si1 = s1;
-	const segitem_t *si2 = s2;
-
-	return si2->num - si1->num;
-}
-
-//
-// Polyobj_findExplicit
-//
-// Searches for segs to put into a polyobject in an explicitly provided order.
-//
-static void Polyobj_findExplicit(polyobj_t *po)
-{
-	// temporary dynamic seg array
-	segitem_t *segitems = NULL;
-	size_t numSegItems = 0;
-	size_t numSegItemsAlloc = 0;
-
-	size_t i;
-
-	// first loop: save off all segs with polyobject's id number
-	for (i = 0; i < numsegs; ++i)
-	{
-		INT32 polyID, parentID;
-
-		if (segs[i].linedef->special != POLYOBJ_EXPLICIT_LINE)
-			continue;
-
-		Polyobj_GetInfo(segs[i].linedef->tag, &polyID, &parentID, NULL);
-
-		if (polyID == po->id && parentID > 0)
-		{
-			if (numSegItems >= numSegItemsAlloc)
-			{
-				numSegItemsAlloc = numSegItemsAlloc ? numSegItemsAlloc*2 : 4;
-				segitems = Z_Realloc(segitems, numSegItemsAlloc*sizeof(segitem_t), PU_STATIC, NULL);
-			}
-			segitems[numSegItems].seg = &segs[i];
-			segitems[numSegItems].num = parentID;
-			++numSegItems;
-		}
-	}
-
-	// make sure array isn't empty
-	if (numSegItems == 0)
-	{
-		po->isBad = true;
-		CONS_Debug(DBG_POLYOBJ, "Polyobject %d is empty\n", po->id);
-		return;
-	}
-
-	// sort the array if necessary
-	if (numSegItems >= 2)
-		qsort(segitems, numSegItems, sizeof(segitem_t), Polyobj_segCompare);
-
-	// second loop: put the sorted segs into the polyobject
-	for (i = 0; i < numSegItems; ++i)
-		Polyobj_addSeg(po, segitems[i].seg);
-
-	// free the temporary array
-	Z_Free(segitems);
-}*/
-
 // Setup functions
 
 //
@@ -598,9 +520,9 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
 	po->thrust = FRACUNIT;
 	po->spawnflags = po->flags = 0;
 
-	// 1. Search segs for "line start" special with tag matching this
-	//    polyobject's id number. If found, iterate through segs which
-	//    share common vertices and record them into the polyobject.
+	// Search segs for "line start" special with tag matching this
+	// polyobject's id number. If found, iterate through segs which
+	// share common vertices and record them into the polyobject.
 	for (i = 0; i < numsegs; ++i)
 	{
 		seg_t *seg = &segs[i];
@@ -639,29 +561,7 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
 	if (po->isBad)
 		return;
 
-	/*
-	// 2. If no such line existed in the first step, look for a seg with the
-	//    "explicit" special with tag matching this polyobject's id number. If
-	//    found, continue to search for all such lines, storing them in a
-	//    temporary list of segs which is then copied into the polyobject in
-	//    sorted order.
-	if (po->segCount == 0)
-	{
-		UINT16 parent;
-		Polyobj_findExplicit(po);
-		// if an error occurred above, quit processing this object
-		if (po->isBad)
-			return;
-
-		Polyobj_GetInfo(po->segs[0]->linedef->tag, NULL, NULL, &parent);
-		po->parent = parent;
-		if (po->parent == po->id) // do not allow a self-reference
-			po->parent = -1;
-		// TODO: sound sequence is in args[3]
-	}*/
-
 	// make sure array isn't empty
-	// since Polyobj_findExplicit is disabled currently, we have to do things here instead now!
 	if (po->segCount == 0)
 	{
 		po->isBad = true;
diff --git a/src/p_polyobj.h b/src/p_polyobj.h
index 7dfc90ce9..fd660761e 100644
--- a/src/p_polyobj.h
+++ b/src/p_polyobj.h
@@ -29,7 +29,6 @@
 #define POLYOBJ_SPAWNCRUSH_DOOMEDNUM 762 // todo: REMOVE
 
 #define POLYOBJ_START_LINE    20
-#define POLYOBJ_EXPLICIT_LINE 21
 #define POLYINFO_SPECIALNUM   22
 
 typedef enum

From b82c3c2089fd5a2f0459229f335495bbd6056363 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Sun, 3 May 2020 23:55:23 +0200
Subject: [PATCH 238/251] Clean up Polyobj_GetInfo

---
 src/p_polyobj.c | 38 +++++++++++++++++---------------------
 src/p_polyobj.h |  1 -
 2 files changed, 17 insertions(+), 22 deletions(-)

diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 9173aa12a..2cde29da4 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -230,36 +230,38 @@ boolean P_BBoxInsidePolyobj(polyobj_t *po, fixed_t *bbox)
 // Finds the 'polyobject settings' linedef for a polyobject
 // the polyobject's id should be set as its tag
 //
-void Polyobj_GetInfo(INT16 poid, INT32 *poflags, INT32 *parentID, INT32 *potrans)
+static void Polyobj_GetInfo(polyobj_t *po)
 {
-	INT32 i = P_FindSpecialLineFromTag(POLYINFO_SPECIALNUM, poid, -1);
+	INT32 i = P_FindSpecialLineFromTag(POLYINFO_SPECIALNUM, po->id, -1);
 
 	if (i == -1)
 		return; // no extra settings to apply, let's leave it
 
-	if (parentID)
-		*parentID = lines[i].frontsector->special;
+	po->parent = lines[i].frontsector->special;
+	if (po->parent == po->id) // do not allow a self-reference
+		po->parent = -1;
 
-	if (potrans)
-		*potrans = (lines[i].frontsector->floorheight>>FRACBITS) / 100;
+	po->translucency = (lines[i].frontsector->floorheight>>FRACBITS) / 100;
+
+	po->flags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES;
 
 	if (lines[i].flags & ML_EFFECT1)
-		*poflags |= POF_ONESIDE;
+		po->flags |= POF_ONESIDE;
 
 	if (lines[i].flags & ML_EFFECT2)
-		*poflags &= ~POF_SOLID;
+		po->flags &= ~POF_SOLID;
 
 	if (lines[i].flags & ML_EFFECT3)
-		*poflags |= POF_PUSHABLESTOP;
+		po->flags |= POF_PUSHABLESTOP;
 
 	if (lines[i].flags & ML_EFFECT4)
-		*poflags |= POF_RENDERPLANES;
+		po->flags |= POF_RENDERPLANES;
 
 	/*if (lines[i].flags & ML_EFFECT5)
-		*poflags &= ~POF_CLIPPLANES;*/
+		po->flags &= ~POF_CLIPPLANES;*/
 
 	if (lines[i].flags & ML_NOCLIMB) // Has a linedef executor
-		*poflags |= POF_LDEXEC;
+		po->flags |= POF_LDEXEC;
 }
 
 // Reallocating array maintenance
@@ -526,8 +528,6 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
 	for (i = 0; i < numsegs; ++i)
 	{
 		seg_t *seg = &segs[i];
-		INT32 poflags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES;
-		INT32 parentID = 0, potrans = 0;
 
 		if (seg->glseg)
 			continue;
@@ -541,17 +541,13 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
 		if (seg->linedef->tag != po->id)
 			continue;
 
-		Polyobj_GetInfo(po->id, &poflags, &parentID, &potrans); // apply extra settings if they exist!
+		Polyobj_GetInfo(po); // apply extra settings if they exist!
 
 		// save original flags and translucency to reference later for netgames!
-		po->spawnflags = po->flags = poflags;
-		po->spawntrans = po->translucency = potrans;
+		po->spawnflags = po->flags;
+		po->spawntrans = po->translucency;
 
 		Polyobj_findSegs(po, seg);
-		po->parent = parentID;
-		if (po->parent == po->id) // do not allow a self-reference
-			po->parent = -1;
-		// TODO: sound sequence is in args[2]
 		break;
 	}
 
diff --git a/src/p_polyobj.h b/src/p_polyobj.h
index fd660761e..4f022013f 100644
--- a/src/p_polyobj.h
+++ b/src/p_polyobj.h
@@ -319,7 +319,6 @@ boolean P_PointInsidePolyobj(polyobj_t *po, fixed_t x, fixed_t y);
 boolean P_MobjTouchingPolyobj(polyobj_t *po, mobj_t *mo);
 boolean P_MobjInsidePolyobj(polyobj_t *po, mobj_t *mo);
 boolean P_BBoxInsidePolyobj(polyobj_t *po, fixed_t *bbox);
-void Polyobj_GetInfo(INT16 poid, INT32 *poflags, INT32 *parentID, INT32 *potrans);
 
 // thinkers (needed in p_saveg.c)
 void T_PolyObjRotate(polyrotate_t *);

From 8ae635c7ba13ae9b3fbc7394acd91852a9d6c045 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 4 May 2020 00:17:05 +0200
Subject: [PATCH 239/251] Purge uninformative comments

---
 src/p_polyobj.c | 151 ++----------------------------------------------
 1 file changed, 4 insertions(+), 147 deletions(-)

diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 2cde29da4..69b002242 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -140,11 +140,6 @@ FUNCINLINE static ATTRINLINE void Polyobj_vecSub2(vertex_t *dst, vertex_t *v1, v
 	dst->y = v1->y - v2->y;
 }
 
-//
-// P_PointInsidePolyobj
-//
-// Returns TRUE if the XY point is inside the polyobject
-//
 boolean P_PointInsidePolyobj(polyobj_t *po, fixed_t x, fixed_t y)
 {
 	size_t i;
@@ -158,11 +153,6 @@ boolean P_PointInsidePolyobj(polyobj_t *po, fixed_t x, fixed_t y)
 	return true;
 }
 
-//
-// P_MobjTouchingPolyobj
-//
-// Returns TRUE if the mobj is touching the edge of a polyobject
-//
 boolean P_MobjTouchingPolyobj(polyobj_t *po, mobj_t *mo)
 {
 	fixed_t mbbox[4];
@@ -182,11 +172,6 @@ boolean P_MobjTouchingPolyobj(polyobj_t *po, mobj_t *mo)
 	return false;
 }
 
-//
-// P_MobjInsidePolyobj
-//
-// Returns TRUE if the mobj is inside the polyobject
-//
 boolean P_MobjInsidePolyobj(polyobj_t *po, mobj_t *mo)
 {
 	fixed_t mbbox[4];
@@ -206,11 +191,6 @@ boolean P_MobjInsidePolyobj(polyobj_t *po, mobj_t *mo)
 	return true;
 }
 
-//
-// P_BBoxInsidePolyobj
-//
-// Returns TRUE if the bbox is inside the polyobject
-//
 boolean P_BBoxInsidePolyobj(polyobj_t *po, fixed_t *bbox)
 {
 	size_t i;
@@ -224,12 +204,8 @@ boolean P_BBoxInsidePolyobj(polyobj_t *po, fixed_t *bbox)
 	return true;
 }
 
-//
-// Polyobj_GetInfo
-//
 // Finds the 'polyobject settings' linedef for a polyobject
 // the polyobject's id should be set as its tag
-//
 static void Polyobj_GetInfo(polyobj_t *po)
 {
 	INT32 i = P_FindSpecialLineFromTag(POLYINFO_SPECIALNUM, po->id, -1);
@@ -266,15 +242,11 @@ static void Polyobj_GetInfo(polyobj_t *po)
 
 // Reallocating array maintenance
 
-//
-// Polyobj_addVertex
-//
 // Adds a vertex to a polyobject's reallocating vertex arrays, provided
 // that such a vertex isn't already in the array. Each vertex must only
 // be translated once during polyobject movement. Keeping track of them
 // this way results in much more clear and efficient code than what
 // Hexen used.
-//
 static void Polyobj_addVertex(polyobj_t *po, vertex_t *v)
 {
 	size_t i;
@@ -310,14 +282,10 @@ static void Polyobj_addVertex(polyobj_t *po, vertex_t *v)
 	po->numVertices++;
 }
 
-//
-// Polyobj_addLine
-//
 // Adds a linedef to a polyobject's reallocating linedefs array, provided
 // that such a linedef isn't already in the array. Each linedef must only
 // be adjusted once during polyobject movement. Keeping track of them
 // this way provides the same benefits as for vertices.
-//
 static void Polyobj_addLine(polyobj_t *po, line_t *l)
 {
 	size_t i;
@@ -342,14 +310,10 @@ static void Polyobj_addLine(polyobj_t *po, line_t *l)
 	po->lines[po->numLines++] = l;
 }
 
-//
-// Polyobj_addSeg
-//
 // Adds a single seg to a polyobject's reallocating seg pointer array.
 // Most polyobjects will have between 4 and 16 segs, so the array size
 // begins much smaller than usual. Calls Polyobj_addVertex and Polyobj_addLine
 // to add those respective structures for this seg, as well.
-//
 static void Polyobj_addSeg(polyobj_t *po, seg_t *seg)
 {
 	if (po->segCount >= po->numSegsAlloc)
@@ -375,14 +339,10 @@ static void Polyobj_addSeg(polyobj_t *po, seg_t *seg)
 
 // Seg-finding functions
 
-//
-// Polyobj_findSegs
-//
 // This method adds segs to a polyobject by following segs from vertex to
 // vertex.  The process stops when the original starting point is reached
 // or if a particular search ends unexpectedly (ie, the polyobject is not
 // closed).
-//
 static void Polyobj_findSegs(polyobj_t *po, seg_t *seg)
 {
 	fixed_t startx, starty;
@@ -494,11 +454,6 @@ newseg:
 
 // Setup functions
 
-//
-// Polyobj_spawnPolyObj
-//
-// Sets up a Polyobject.
-//
 static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
 {
 	size_t i;
@@ -586,12 +541,8 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
 
 static void Polyobj_attachToSubsec(polyobj_t *po);
 
-//
-// Polyobj_moveToSpawnSpot
-//
 // Translates the polyobject's vertices with respect to the difference between
 // the anchor and spawn spots. Updates linedef bounding boxes as well.
-//
 static void Polyobj_moveToSpawnSpot(mapthing_t *anchor)
 {
 	polyobj_t *po;
@@ -638,11 +589,7 @@ static void Polyobj_moveToSpawnSpot(mapthing_t *anchor)
 	Polyobj_attachToSubsec(po);
 }
 
-//
-// Polyobj_attachToSubsec
-//
 // Attaches a polyobject to its appropriate subsector.
-//
 static void Polyobj_attachToSubsec(polyobj_t *po)
 {
 	subsector_t  *ss;
@@ -677,11 +624,7 @@ static void Polyobj_attachToSubsec(polyobj_t *po)
 	po->attached = true;
 }
 
-//
-// Polyobj_removeFromSubsec
-//
 // Removes a polyobject from the subsector to which it is attached.
-//
 static void Polyobj_removeFromSubsec(polyobj_t *po)
 {
 	if (po->attached)
@@ -693,11 +636,7 @@ static void Polyobj_removeFromSubsec(polyobj_t *po)
 
 // Blockmap Functions
 
-//
-// Polyobj_getLink
-//
 // Retrieves a polymaplink object from the free list or creates a new one.
-//
 static polymaplink_t *Polyobj_getLink(void)
 {
 	polymaplink_t *l;
@@ -716,11 +655,7 @@ static polymaplink_t *Polyobj_getLink(void)
 	return l;
 }
 
-//
-// Polyobj_putLink
-//
 // Puts a polymaplink object into the free list.
-//
 static void Polyobj_putLink(polymaplink_t *l)
 {
 	memset(l, 0, sizeof(*l));
@@ -728,14 +663,10 @@ static void Polyobj_putLink(polymaplink_t *l)
 	bmap_freelist = l;
 }
 
-//
-// Polyobj_linkToBlockmap
-//
 // Inserts a polyobject into the polyobject blockmap. Unlike, mobj_t's,
 // polyobjects need to be linked into every blockmap cell which their
 // bounding box intersects. This ensures the accurate level of clipping
 // which is present with linedefs but absent from most mobj interactions.
-//
 static void Polyobj_linkToBlockmap(polyobj_t *po)
 {
 	fixed_t *blockbox = po->blockbox;
@@ -780,12 +711,8 @@ static void Polyobj_linkToBlockmap(polyobj_t *po)
 	po->linked = true;
 }
 
-//
-// Polyobj_removeFromBlockmap
-//
 // Unlinks a polyobject from all blockmap cells it intersects and returns
 // its polymaplink objects to the free list.
-//
 static void Polyobj_removeFromBlockmap(polyobj_t *po)
 {
 	polymaplink_t *rover;
@@ -824,13 +751,9 @@ static void Polyobj_removeFromBlockmap(polyobj_t *po)
 
 // Movement functions
 
-//
-// Polyobj_untouched
-//
 // A version of Lee's routine from p_maputl.c that accepts an mobj pointer
 // argument instead of using tmthing. Returns true if the line isn't contacted
 // and false otherwise.
-//
 static inline boolean Polyobj_untouched(line_t *ld, mobj_t *mo)
 {
 	fixed_t x, y, ptmbbox[4];
@@ -843,13 +766,9 @@ static inline boolean Polyobj_untouched(line_t *ld, mobj_t *mo)
 		P_BoxOnLineSide(ptmbbox, ld) != -1;
 }
 
-//
-// Polyobj_pushThing
-//
 // Inflicts thrust and possibly damage on a thing which has been found to be
 // blocking the motion of a polyobject. The default thrust amount is only one
 // unit, but the motion of the polyobject can be used to change this.
-//
 static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo)
 {
 	angle_t lineangle;
@@ -884,11 +803,7 @@ static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo)
 	}
 }
 
-//
-// Polyobj_slideThing
-//
 // Moves an object resting on top of a polyobject by (x, y). Template function to make alteration easier.
-//
 static void Polyobj_slideThing(mobj_t *mo, fixed_t dx, fixed_t dy)
 {
 	if (mo->player) { // Finally this doesn't suck eggs -fickle
@@ -936,11 +851,7 @@ static void Polyobj_slideThing(mobj_t *mo, fixed_t dx, fixed_t dy)
 		P_TryMove(mo, mo->x+dx, mo->y+dy, true);
 }
 
-//
-// Polyobj_carryThings
-//
 // Causes objects resting on top of the polyobject to 'ride' with its movement.
-//
 static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy)
 {
 	static INT32 pomovecount = 0;
@@ -992,12 +903,8 @@ static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy)
 	}
 }
 
-//
-// Polyobj_clipThings
-//
 // Checks for things that are in the way of a polyobject line move.
 // Returns true if something was hit.
-//
 static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
 {
 	INT32 hitflags = 0;
@@ -1059,11 +966,8 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
 	return hitflags;
 }
 
-//
-// Polyobj_moveXY
-//
+
 // Moves a polyobject on the x-y plane.
-//
 static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs)
 {
 	size_t i;
@@ -1119,14 +1023,10 @@ static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean check
 	return !(hitflags & 2);
 }
 
-//
-// Polyobj_rotatePoint
-//
 // Rotates a point and then translates it relative to point c.
 // The formula for this can be found here:
 // http://www.inversereality.org/tutorials/graphics%20programming/2dtransformations.html
 // It is, of course, just a vector-matrix multiplication.
-//
 static inline void Polyobj_rotatePoint(vertex_t *v, const vertex_t *c, angle_t ang)
 {
 	vertex_t tmp = *v;
@@ -1138,12 +1038,8 @@ static inline void Polyobj_rotatePoint(vertex_t *v, const vertex_t *c, angle_t a
 	v->y += c->y;
 }
 
-//
-// Polyobj_rotateLine
-//
 // Taken from P_LoadLineDefs; simply updates the linedef's dx, dy, slopetype,
 // and bounding box to be consistent with its vertices.
-//
 static void Polyobj_rotateLine(line_t *ld)
 {
 	vertex_t *v1, *v2;
@@ -1183,11 +1079,7 @@ static void Polyobj_rotateLine(line_t *ld)
 	}
 }
 
-//
-// Polyobj_rotateThings
-//
 // Causes objects resting on top of the rotating polyobject to 'ride' with its movement.
-//
 static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta, UINT8 turnthings)
 {
 	static INT32 pomovecount = 10000;
@@ -1263,11 +1155,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
 	}
 }
 
-//
-// Polyobj_rotate
-//
 // Rotates a polyobject around its start point.
-//
 static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs)
 {
 	size_t i;
@@ -1341,12 +1229,8 @@ static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, bo
 // Global Functions
 //
 
-//
-// Polyobj_GetForNum
-//
 // Retrieves a polyobject by its numeric id using hashing.
 // Returns NULL if no such polyobject exists.
-//
 polyobj_t *Polyobj_GetForNum(INT32 id)
 {
 	INT32 curidx  = PolyObjects[id % numPolyObjects].first;
@@ -1357,12 +1241,9 @@ polyobj_t *Polyobj_GetForNum(INT32 id)
 	return curidx == numPolyObjects ? NULL : &PolyObjects[curidx];
 }
 
-//
-// Polyobj_GetParent
-//
+
 // Retrieves the parenting polyobject if one exists. Returns NULL
 // otherwise.
-//
 #if 0 //unused function
 static polyobj_t *Polyobj_GetParent(polyobj_t *po)
 {
@@ -1370,12 +1251,8 @@ static polyobj_t *Polyobj_GetParent(polyobj_t *po)
 }
 #endif
 
-//
-// Polyobj_GetChild
-//
 // Iteratively retrieves the children POs of a parent,
 // sorta like P_FindSectorSpecialFromTag.
-//
 static polyobj_t *Polyobj_GetChild(polyobj_t *po, INT32 *start)
 {
 	for (; *start < numPolyObjects; (*start)++)
@@ -1394,12 +1271,8 @@ typedef struct mobjqitem_s
 	mobj_t *mo;
 } mobjqitem_t;
 
-//
-// Polyobj_InitLevel
-//
 // Called at the beginning of each map after all other line and thing
 // processing is finished.
-//
 void Polyobj_InitLevel(void)
 {
 	thinker_t   *th;
@@ -1518,9 +1391,6 @@ void Polyobj_InitLevel(void)
 	M_QueueFree(&anchorqueue);
 }
 
-//
-// Polyobj_MoveOnLoad
-//
 // Called when a savegame is being loaded. Rotates and translates an
 // existing polyobject to its position when the game was saved.
 //
@@ -1545,11 +1415,7 @@ void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y)
 
 // Thinker Functions
 
-//
-// T_PolyObjRotate
-//
 // Thinker function for PolyObject rotation.
-//
 void T_PolyObjRotate(polyrotate_t *th)
 {
 	polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
@@ -1610,11 +1476,7 @@ void T_PolyObjRotate(polyrotate_t *th)
 	}
 }
 
-//
-// Polyobj_componentSpeed
-//
 // Calculates the speed components from the desired resultant velocity.
-//
 FUNCINLINE static ATTRINLINE void Polyobj_componentSpeed(INT32 resVel, INT32 angle,
                                             fixed_t *xVel, fixed_t *yVel)
 {
@@ -1695,11 +1557,6 @@ void T_PolyObjMove(polymove_t *th)
 	}
 }
 
-//
-// T_PolyObjWaypoint
-//
-// Kinda like 'Zoom Tubes for PolyObjects'
-//
 void T_PolyObjWaypoint(polywaypoint_t *th)
 {
 	mobj_t *mo2;
@@ -2193,7 +2050,7 @@ void T_PolyDoorSwing(polyswingdoor_t *th)
 	}
 }
 
-// T_PolyObjDisplace: shift a polyobject based on a control sector's heights.
+// Shift a polyobject based on a control sector's heights.
 void T_PolyObjDisplace(polydisplace_t *th)
 {
 	polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);
@@ -2233,7 +2090,7 @@ void T_PolyObjDisplace(polydisplace_t *th)
 		th->oldHeights = newheights;
 }
 
-// T_PolyObjRotDisplace: rotate a polyobject based on a control sector's heights.
+// Rotate a polyobject based on a control sector's heights.
 void T_PolyObjRotDisplace(polyrotdisplace_t *th)
 {
 	polyobj_t *po = Polyobj_GetForNum(th->polyObjNum);

From 02c347ada269131bfc61f9eeeb98180112b7f96b Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 4 May 2020 01:28:21 +0200
Subject: [PATCH 240/251] Refactor Polyobj_findSegs

---
 src/p_polyobj.c | 126 +++++++++++++++++++++++++-----------------------
 1 file changed, 67 insertions(+), 59 deletions(-)

diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 69b002242..5c71e356a 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -356,25 +356,29 @@ static void Polyobj_findSegs(polyobj_t *po, seg_t *seg)
 		// Find backfacings
 		for (s = 0;  s < numsegs; s++)
 		{
+			size_t r;
+
 			if (segs[s].glseg)
 				continue;
-			if (segs[s].linedef == seg->linedef
-				&& segs[s].side == 1)
+
+			if (segs[s].linedef != seg->linedef)
+				continue;
+
+			if (segs[s].side != 1)
+				continue;
+
+			for (r = 0; r < po->segCount; r++)
 			{
-				size_t r;
-				for (r = 0; r < po->segCount; r++)
-				{
-					if (po->segs[r] == &segs[s])
-						break;
-				}
-
-				if (r != po->segCount)
-					continue;
-
-				segs[s].dontrenderme = true;
-
-				Polyobj_addSeg(po, &segs[s]);
+				if (po->segs[r] == &segs[s])
+					break;
 			}
+
+			if (r != po->segCount)
+				continue;
+
+			segs[s].dontrenderme = true;
+
+			Polyobj_addSeg(po, &segs[s]);
 		}
 	}
 
@@ -394,56 +398,60 @@ newseg:
 	// seg's ending vertex.
 	for (i = 0; i < numsegs; ++i)
 	{
+		size_t q;
+
 		if (segs[i].glseg)
 			continue;
 		if (segs[i].side != 0) // needs to be frontfacing
 			continue;
-		if (segs[i].v1->x == seg->v2->x && segs[i].v1->y == seg->v2->y)
+		if (segs[i].v1->x != seg->v2->x)
+			continue;
+		if (segs[i].v1->y != seg->v2->y)
+			continue;
+
+		// Make sure you didn't already add this seg...
+		for (q = 0; q < po->segCount; q++)
 		{
-			// Make sure you didn't already add this seg...
-			size_t q;
-			for (q = 0; q < po->segCount; q++)
-			{
-				if (po->segs[q] == &segs[i])
-					break;
-			}
-
-			if (q != po->segCount)
-				continue;
-
-			// add the new seg and recurse
-			Polyobj_addSeg(po, &segs[i]);
-			seg = &segs[i];
-
-			if (!(po->flags & POF_ONESIDE))
-			{
-				// Find backfacings
-				for (q = 0;  q < numsegs; q++)
-				{
-					if (segs[q].glseg)
-						continue;
-
-					if (segs[q].linedef == segs[i].linedef
-						&& segs[q].side == 1)
-					{
-						size_t r;
-						for (r=0; r < po->segCount; r++)
-						{
-							if (po->segs[r] == &segs[q])
-								break;
-						}
-
-						if (r != po->segCount)
-							continue;
-
-						segs[q].dontrenderme = true;
-						Polyobj_addSeg(po, &segs[q]);
-					}
-				}
-			}
-
-			goto newseg;
+			if (po->segs[q] == &segs[i])
+				break;
 		}
+
+		if (q != po->segCount)
+			continue;
+
+		// add the new seg and recurse
+		Polyobj_addSeg(po, &segs[i]);
+		seg = &segs[i];
+
+		if (!(po->flags & POF_ONESIDE))
+		{
+			// Find backfacings
+			for (q = 0; q < numsegs; q++)
+			{
+				size_t r;
+
+				if (segs[q].glseg)
+					continue;
+				if (segs[q].linedef != segs[i].linedef)
+					continue;
+				if (segs[q].side != 1)
+					continue;
+
+				for (r = 0; r < po->segCount; r++)
+				{
+					if (po->segs[r] == &segs[q])
+						break;
+				}
+
+				if (r != po->segCount)
+					continue;
+
+				segs[q].dontrenderme = true;
+				Polyobj_addSeg(po, &segs[q]);
+			}
+		}
+
+		goto newseg;
 	}
 
 	// error: if we reach here, the seg search never found another seg to

From 482adc6124fb574fa9e366ea9ea66d966d35b981 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 4 May 2020 09:54:32 +0200
Subject: [PATCH 241/251] Pass parameters to EV_DoPolyObjFlag in a struct and
 not via the line

---
 src/p_polyobj.c | 16 ++++++++--------
 src/p_polyobj.h | 10 +++++++++-
 src/p_spec.c    |  9 ++++++++-
 3 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 5c71e356a..be751e153 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -2691,7 +2691,7 @@ void T_PolyObjFlag(polymove_t *th)
 	Polyobj_attachToSubsec(po);     // relink to subsector
 }
 
-INT32 EV_DoPolyObjFlag(line_t *pfdata)
+INT32 EV_DoPolyObjFlag(polyflagdata_t *pfdata)
 {
 	polyobj_t *po;
 	polyobj_t *oldpo;
@@ -2699,9 +2699,9 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata)
 	size_t i;
 	INT32 start;
 
-	if (!(po = Polyobj_GetForNum(pfdata->tag)))
+	if (!(po = Polyobj_GetForNum(pfdata->polyObjNum)))
 	{
-		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", pfdata->tag);
+		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", pfdata->polyObjNum);
 		return 0;
 	}
 
@@ -2724,11 +2724,11 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata)
 	po->thinker = &th->thinker;
 
 	// set fields
-	th->polyObjNum = pfdata->tag;
+	th->polyObjNum = pfdata->polyObjNum;
 	th->distance   = 0;
-	th->speed      = P_AproxDistance(pfdata->dx, pfdata->dy)>>FRACBITS;
-	th->angle      = R_PointToAngle2(pfdata->v1->x, pfdata->v1->y, pfdata->v2->x, pfdata->v2->y)>>ANGLETOFINESHIFT;
-	th->momx       = sides[pfdata->sidenum[0]].textureoffset>>FRACBITS;
+	th->speed      = pfdata->speed;
+	th->angle      = pfdata->angle;
+	th->momx       = pfdata->momx;
 
 	// save current positions
 	for (i = 0; i < po->numVertices; ++i)
@@ -2740,7 +2740,7 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata)
 	start = 0;
 	while ((po = Polyobj_GetChild(oldpo, &start)))
 	{
-		pfdata->tag = po->id;
+		pfdata->polyObjNum = po->id;
 		EV_DoPolyObjFlag(pfdata);
 	}
 
diff --git a/src/p_polyobj.h b/src/p_polyobj.h
index 4f022013f..4ba2b469c 100644
--- a/src/p_polyobj.h
+++ b/src/p_polyobj.h
@@ -298,6 +298,14 @@ typedef struct polyrotdisplacedata_s
 	UINT8 turnobjs;
 } polyrotdisplacedata_t;
 
+typedef struct polyflagdata_s
+{
+	INT32 polyObjNum;
+	INT32 speed;
+	UINT32 angle;
+	fixed_t momx;
+} polyflagdata_t;
+
 typedef struct polyfadedata_s
 {
 	INT32 polyObjNum;
@@ -337,7 +345,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *);
 INT32 EV_DoPolyObjRotate(polyrotdata_t *);
 INT32 EV_DoPolyObjDisplace(polydisplacedata_t *);
 INT32 EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *);
-INT32 EV_DoPolyObjFlag(struct line_s *);
+INT32 EV_DoPolyObjFlag(polyflagdata_t *);
 INT32 EV_DoPolyObjFade(polyfadedata_t *);
 
 
diff --git a/src/p_spec.c b/src/p_spec.c
index c93846438..6355b7717 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -7282,8 +7282,15 @@ void P_SpawnSpecials(boolean fromnetsave)
 		switch (lines[i].special)
 		{
 			case 30: // Polyobj_Flag
-				EV_DoPolyObjFlag(&lines[i]);
+			{
+				polyflagdata_t pfd;
+				pfd.polyObjNum = lines[i].tag;
+				pfd.speed = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS;
+				pfd.angle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y) >> ANGLETOFINESHIFT;
+				pfd.momx = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS;
+				EV_DoPolyObjFlag(&pfd);
 				break;
+			}
 
 			case 31: // Polyobj_Displace
 				PolyDisplace(&lines[i]);

From 2be775e74ce867380a344f0bcf3bf86a65db4f51 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 4 May 2020 09:58:27 +0200
Subject: [PATCH 242/251] Move parameter parsing for EV_DoPolyObjFlag into its
 own function

---
 src/p_spec.c | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index 6355b7717..091f0faff 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -1352,6 +1352,19 @@ static boolean PolyRotate(line_t *line)
 	return EV_DoPolyObjRotate(&prd);
 }
 
+// Parses arguments for polyobject flag waving special
+static boolean PolyFlag(line_t *line)
+{
+	polyflagdata_t pfd;
+
+	pfd.polyObjNum = line->tag;
+	pfd.speed = P_AproxDistance(line->dx, line->dy) >> FRACBITS;
+	pfd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y) >> ANGLETOFINESHIFT;
+	pfd.momx = sides[line->sidenum[0]].textureoffset >> FRACBITS;
+
+	return EV_DoPolyObjFlag(&pfd);
+}
+
 //
 // PolyDisplace
 //
@@ -7282,15 +7295,8 @@ void P_SpawnSpecials(boolean fromnetsave)
 		switch (lines[i].special)
 		{
 			case 30: // Polyobj_Flag
-			{
-				polyflagdata_t pfd;
-				pfd.polyObjNum = lines[i].tag;
-				pfd.speed = P_AproxDistance(lines[i].dx, lines[i].dy) >> FRACBITS;
-				pfd.angle = R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y) >> ANGLETOFINESHIFT;
-				pfd.momx = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS;
-				EV_DoPolyObjFlag(&pfd);
+				PolyFlag(&lines[i]);
 				break;
-			}
 
 			case 31: // Polyobj_Displace
 				PolyDisplace(&lines[i]);

From 78a700f5fa905916acc1745c814d178145bc3fa4 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 4 May 2020 10:01:44 +0200
Subject: [PATCH 243/251] Remove non-descriptive comments

---
 src/p_spec.c | 44 +++-----------------------------------------
 1 file changed, 3 insertions(+), 41 deletions(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index 091f0faff..1d9c2b143 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -1044,9 +1044,6 @@ static INT32 P_FindLineFromTag(INT32 tag, INT32 start)
 	}
 }
 
-//
-// P_FindSpecialLineFromTag
-//
 INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start)
 {
 	if (tag == -1)
@@ -1076,11 +1073,8 @@ INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start)
 	}
 }
 
-//
-// PolyDoor
-//
+
 // Parses arguments for parameterized polyobject door types
-//
 static boolean PolyDoor(line_t *line)
 {
 	polydoordata_t pdd;
@@ -1117,11 +1111,7 @@ static boolean PolyDoor(line_t *line)
 	return EV_DoPolyDoor(&pdd);
 }
 
-//
-// PolyMove
-//
 // Parses arguments for parameterized polyobject move specials
-//
 static boolean PolyMove(line_t *line)
 {
 	polymovedata_t pmd;
@@ -1136,12 +1126,8 @@ static boolean PolyMove(line_t *line)
 	return EV_DoPolyObjMove(&pmd);
 }
 
-//
-// PolyInvisible
-//
 // Makes a polyobject invisible and intangible
 // If NOCLIMB is ticked, the polyobject will still be tangible, just not visible.
-//
 static void PolyInvisible(line_t *line)
 {
 	INT32 polyObjNum = line->tag;
@@ -1164,12 +1150,8 @@ static void PolyInvisible(line_t *line)
 	po->flags &= ~POF_RENDERALL;
 }
 
-//
-// PolyVisible
-//
 // Makes a polyobject visible and tangible
 // If NOCLIMB is ticked, the polyobject will not be tangible, just visible.
-//
 static void PolyVisible(line_t *line)
 {
 	INT32 polyObjNum = line->tag;
@@ -1192,12 +1174,9 @@ static void PolyVisible(line_t *line)
 	po->flags |= (po->spawnflags & POF_RENDERALL);
 }
 
-//
-// PolyTranslucency
-//
+
 // Sets the translucency of a polyobject
 // Frontsector floor / 100 = translevel
-//
 static void PolyTranslucency(line_t *line)
 {
 	INT32 polyObjNum = line->tag;
@@ -1234,11 +1213,7 @@ static void PolyTranslucency(line_t *line)
 				: max(min(line->frontsector->floorheight>>FRACBITS, 1000), 0) / 100);
 }
 
-//
-// PolyFade
-//
 // Makes a polyobject translucency fade and applies tangibility
-//
 static boolean PolyFade(line_t *line)
 {
 	INT32 polyObjNum = line->tag;
@@ -1303,11 +1278,7 @@ static boolean PolyFade(line_t *line)
 	return EV_DoPolyObjFade(&pfd);
 }
 
-//
-// PolyWaypoint
-//
 // Parses arguments for parameterized polyobject waypoint movement
-//
 static boolean PolyWaypoint(line_t *line)
 {
 	polywaypointdata_t pwd;
@@ -1323,11 +1294,7 @@ static boolean PolyWaypoint(line_t *line)
 	return EV_DoPolyObjWaypoint(&pwd);
 }
 
-//
-// PolyRotate
-//
 // Parses arguments for parameterized polyobject rotate specials
-//
 static boolean PolyRotate(line_t *line)
 {
 	polyrotdata_t prd;
@@ -1365,11 +1332,7 @@ static boolean PolyFlag(line_t *line)
 	return EV_DoPolyObjFlag(&pfd);
 }
 
-//
-// PolyDisplace
-//
 // Parses arguments for parameterized polyobject move-by-sector-heights specials
-//
 static boolean PolyDisplace(line_t *line)
 {
 	polydisplacedata_t pdd;
@@ -1384,8 +1347,7 @@ static boolean PolyDisplace(line_t *line)
 }
 
 
-/** Similar to PolyDisplace().
- */
+// Parses arguments for parameterized polyobject rotate-by-sector-heights specials
 static boolean PolyRotDisplace(line_t *line)
 {
 	polyrotdisplacedata_t pdd;

From e3ddb413aa2c6378a2014a79db3cea9398a8063b Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 4 May 2020 10:07:38 +0200
Subject: [PATCH 244/251] Make PolyObject special functions return boolean
 instead of INT32

---
 src/p_polyobj.c | 80 ++++++++++++++++++++++++-------------------------
 src/p_polyobj.h | 16 +++++-----
 2 files changed, 48 insertions(+), 48 deletions(-)

diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index be751e153..e35a124cd 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -2144,7 +2144,7 @@ static inline INT32 Polyobj_AngSpeed(INT32 speed)
 
 // Linedef Handlers
 
-INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata)
+boolean EV_DoPolyObjRotate(polyrotdata_t *prdata)
 {
 	polyobj_t *po;
 	polyobj_t *oldpo;
@@ -2154,16 +2154,16 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata)
 	if (!(po = Polyobj_GetForNum(prdata->polyObjNum)))
 	{
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", prdata->polyObjNum);
-		return 0;
+		return false;
 	}
 
 	// don't allow line actions to affect bad polyobjects
 	if (po->isBad)
-		return 0;
+		return false;
 
 	// check for override if this polyobj already has a thinker
 	if (po->thinker && !prdata->overRide)
-		return 0;
+		return false;
 
 	// create a new thinker
 	th = Z_Malloc(sizeof(polyrotate_t), PU_LEVSPEC, NULL);
@@ -2206,10 +2206,10 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata)
 	}
 
 	// action was successful
-	return 1;
+	return true;
 }
 
-INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
+boolean EV_DoPolyObjMove(polymovedata_t *pmdata)
 {
 	polyobj_t *po;
 	polyobj_t *oldpo;
@@ -2219,16 +2219,16 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
 	if (!(po = Polyobj_GetForNum(pmdata->polyObjNum)))
 	{
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjMove: bad polyobj %d\n", pmdata->polyObjNum);
-		return 0;
+		return false;
 	}
 
 	// don't allow line actions to affect bad polyobjects
 	if (po->isBad)
-		return 0;
+		return false;
 
 	// check for override if this polyobj already has a thinker
 	if (po->thinker && !pmdata->overRide)
-		return 0;
+		return false;
 
 	// create a new thinker
 	th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL);
@@ -2265,10 +2265,10 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
 	}
 
 	// action was successful
-	return 1;
+	return true;
 }
 
-INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
+boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
 {
 	polyobj_t *po;
 	polywaypoint_t *th;
@@ -2281,15 +2281,15 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
 	if (!(po = Polyobj_GetForNum(pwdata->polyObjNum)))
 	{
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: bad polyobj %d\n", pwdata->polyObjNum);
-		return 0;
+		return false;
 	}
 
 	// don't allow line actions to affect bad polyobjects
 	if (po->isBad)
-		return 0;
+		return false;
 
 	if (po->thinker) // Don't crowd out another thinker.
-		return 0;
+		return false;
 
 	// create a new thinker
 	th = Z_Malloc(sizeof(polywaypoint_t), PU_LEVSPEC, NULL);
@@ -2356,7 +2356,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: Missing starting waypoint!\n");
 		po->thinker = NULL;
 		P_RemoveThinker(&th->thinker);
-		return 0;
+		return false;
 	}
 
 	// Hotfix to not crash on single-waypoint sequences -Red
@@ -2419,7 +2419,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: Missing target waypoint!\n");
 		po->thinker = NULL;
 		P_RemoveThinker(&th->thinker);
-		return 0;
+		return false;
 	}
 
 	// Set pointnum
@@ -2430,7 +2430,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
 
 	// We don't deal with the mirror crap here, we'll
 	// handle that in the T_Thinker function.
-	return 1;
+	return true;
 }
 
 static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata)
@@ -2522,20 +2522,20 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata)
 		Polyobj_doSwingDoor(po, doordata);
 }
 
-INT32 EV_DoPolyDoor(polydoordata_t *doordata)
+boolean EV_DoPolyDoor(polydoordata_t *doordata)
 {
 	polyobj_t *po;
 
 	if (!(po = Polyobj_GetForNum(doordata->polyObjNum)))
 	{
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyDoor: bad polyobj %d\n", doordata->polyObjNum);
-		return 0;
+		return false;
 	}
 
 	// don't allow line actions to affect bad polyobjects;
 	// polyobject doors don't allow action overrides
 	if (po->isBad || po->thinker)
-		return 0;
+		return false;
 
 	switch (doordata->doorType)
 	{
@@ -2547,13 +2547,13 @@ INT32 EV_DoPolyDoor(polydoordata_t *doordata)
 		break;
 	default:
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyDoor: unknown door type %d", doordata->doorType);
-		return 0;
+		return false;
 	}
 
-	return 1;
+	return true;
 }
 
-INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata)
+boolean EV_DoPolyObjDisplace(polydisplacedata_t *prdata)
 {
 	polyobj_t *po;
 	polyobj_t *oldpo;
@@ -2563,12 +2563,12 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata)
 	if (!(po = Polyobj_GetForNum(prdata->polyObjNum)))
 	{
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", prdata->polyObjNum);
-		return 0;
+		return false;
 	}
 
 	// don't allow line actions to affect bad polyobjects
 	if (po->isBad)
-		return 0;
+		return false;
 
 	// create a new thinker
 	th = Z_Malloc(sizeof(polydisplace_t), PU_LEVSPEC, NULL);
@@ -2596,10 +2596,10 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata)
 	}
 
 	// action was successful
-	return 1;
+	return true;
 }
 
-INT32 EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *prdata)
+boolean EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *prdata)
 {
 	polyobj_t *po;
 	polyobj_t *oldpo;
@@ -2609,12 +2609,12 @@ INT32 EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *prdata)
 	if (!(po = Polyobj_GetForNum(prdata->polyObjNum)))
 	{
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", prdata->polyObjNum);
-		return 0;
+		return false;
 	}
 
 	// don't allow line actions to affect bad polyobjects
 	if (po->isBad)
-		return 0;
+		return false;
 
 	// create a new thinker
 	th = Z_Malloc(sizeof(polyrotdisplace_t), PU_LEVSPEC, NULL);
@@ -2642,7 +2642,7 @@ INT32 EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *prdata)
 	}
 
 	// action was successful
-	return 1;
+	return true;
 }
 
 void T_PolyObjFlag(polymove_t *th)
@@ -2691,7 +2691,7 @@ void T_PolyObjFlag(polymove_t *th)
 	Polyobj_attachToSubsec(po);     // relink to subsector
 }
 
-INT32 EV_DoPolyObjFlag(polyflagdata_t *pfdata)
+boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
 {
 	polyobj_t *po;
 	polyobj_t *oldpo;
@@ -2702,19 +2702,19 @@ INT32 EV_DoPolyObjFlag(polyflagdata_t *pfdata)
 	if (!(po = Polyobj_GetForNum(pfdata->polyObjNum)))
 	{
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", pfdata->polyObjNum);
-		return 0;
+		return false;
 	}
 
 	// don't allow line actions to affect bad polyobjects,
 	// polyobject doors don't allow action overrides
 	if (po->isBad || po->thinker)
-		return 0;
+		return false;
 
 	// Must have even # of vertices
 	if (po->numVertices & 1)
 	{
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: Polyobject has odd # of vertices!\n");
-		return 0;
+		return false;
 	}
 
 	// create a new thinker
@@ -2745,7 +2745,7 @@ INT32 EV_DoPolyObjFlag(polyflagdata_t *pfdata)
 	}
 
 	// action was successful
-	return 1;
+	return true;
 }
 
 void T_PolyObjFade(polyfade_t *th)
@@ -2843,7 +2843,7 @@ void T_PolyObjFade(polyfade_t *th)
 	}
 }
 
-INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata)
+boolean EV_DoPolyObjFade(polyfadedata_t *pfdata)
 {
 	polyobj_t *po;
 	polyobj_t *oldpo;
@@ -2853,16 +2853,16 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata)
 	if (!(po = Polyobj_GetForNum(pfdata->polyObjNum)))
 	{
 		CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjFade: bad polyobj %d\n", pfdata->polyObjNum);
-		return 0;
+		return false;
 	}
 
 	// don't allow line actions to affect bad polyobjects
 	if (po->isBad)
-		return 0;
+		return false;
 
 	// already equal, nothing to do
 	if (po->translucency == pfdata->destvalue)
-		return 1;
+		return true;
 
 	if (po->thinker && po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade)
 		P_RemoveThinker(po->thinker);
@@ -2904,7 +2904,7 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata)
 	}
 
 	// action was successful
-	return 1;
+	return true;
 }
 
 // EOF
diff --git a/src/p_polyobj.h b/src/p_polyobj.h
index 4ba2b469c..68aff4bf1 100644
--- a/src/p_polyobj.h
+++ b/src/p_polyobj.h
@@ -339,14 +339,14 @@ void T_PolyObjRotDisplace  (polyrotdisplace_t *);
 void T_PolyObjFlag  (polymove_t *);
 void T_PolyObjFade  (polyfade_t *);
 
-INT32 EV_DoPolyDoor(polydoordata_t *);
-INT32 EV_DoPolyObjMove(polymovedata_t *);
-INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *);
-INT32 EV_DoPolyObjRotate(polyrotdata_t *);
-INT32 EV_DoPolyObjDisplace(polydisplacedata_t *);
-INT32 EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *);
-INT32 EV_DoPolyObjFlag(polyflagdata_t *);
-INT32 EV_DoPolyObjFade(polyfadedata_t *);
+boolean EV_DoPolyDoor(polydoordata_t *);
+boolean EV_DoPolyObjMove(polymovedata_t *);
+boolean EV_DoPolyObjWaypoint(polywaypointdata_t *);
+boolean EV_DoPolyObjRotate(polyrotdata_t *);
+boolean EV_DoPolyObjDisplace(polydisplacedata_t *);
+boolean EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *);
+boolean EV_DoPolyObjFlag(polyflagdata_t *);
+boolean EV_DoPolyObjFade(polyfadedata_t *);
 
 
 //

From 248df41a2fc603b19ddd67e26d667ec13c0cc7cf Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 4 May 2020 10:29:35 +0200
Subject: [PATCH 245/251] Simplify set/fade polyobject translucency code

---
 src/p_spec.c | 58 ++++++++++++++++++++++------------------------------
 1 file changed, 24 insertions(+), 34 deletions(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index 1d9c2b143..430b6077c 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -1181,6 +1181,7 @@ static void PolyTranslucency(line_t *line)
 {
 	INT32 polyObjNum = line->tag;
 	polyobj_t *po;
+	INT32 value;
 
 	if (!(po = Polyobj_GetForNum(polyObjNum)))
 	{
@@ -1192,25 +1193,19 @@ static void PolyTranslucency(line_t *line)
 	if (po->isBad)
 		return;
 
-	// if DONTPEGBOTTOM, specify raw translucency value in Front X Offset
-	// else, take it out of 1000. If Front X Offset is specified, use that. Else, use floorheight.
+	// If Front X Offset is specified, use that. Else, use floorheight.
+	value = (sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : line->frontsector->floorheight) >> FRACBITS;
+
+	// If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000.
+	if (!(line->flags & ML_DONTPEGBOTTOM))
+		value /= 100;
+
 	if (line->flags & ML_EFFECT3) // relative calc
-		po->translucency = max(min(po->translucency + ((line->flags & ML_DONTPEGBOTTOM) ?
-			(sides[line->sidenum[0]].textureoffset ?
-				max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS)
-				: max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS))
-			: (sides[line->sidenum[0]].textureoffset ?
-				max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), -1000) / 100
-				: max(min(line->frontsector->floorheight>>FRACBITS, 1000), -1000) / 100)),
-			NUMTRANSMAPS), 0);
+		po->translucency += value;
 	else
-		po->translucency = (line->flags & ML_DONTPEGBOTTOM) ?
-			(sides[line->sidenum[0]].textureoffset ?
-				max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0)
-				: max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), 0))
-			: (sides[line->sidenum[0]].textureoffset ?
-				max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), 0) / 100
-				: max(min(line->frontsector->floorheight>>FRACBITS, 1000), 0) / 100);
+		po->translucency = value;
+
+	po->translucency = max(min(po->translucency, NUMTRANSMAPS), 0);
 }
 
 // Makes a polyobject translucency fade and applies tangibility
@@ -1219,6 +1214,7 @@ static boolean PolyFade(line_t *line)
 	INT32 polyObjNum = line->tag;
 	polyobj_t *po;
 	polyfadedata_t pfd;
+	INT32 value;
 
 	if (!(po = Polyobj_GetForNum(polyObjNum)))
 	{
@@ -1241,25 +1237,19 @@ static boolean PolyFade(line_t *line)
 
 	pfd.polyObjNum = polyObjNum;
 
-	// if DONTPEGBOTTOM, specify raw translucency value in Front X Offset
-	// else, take it out of 1000. If Front X Offset is specified, use that. Else, use floorheight.
+	// If Front X Offset is specified, use that. Else, use floorheight.
+	value = (sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : line->frontsector->floorheight) >> FRACBITS;
+
+	// If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000.
+	if (!(line->flags & ML_DONTPEGBOTTOM))
+		value /= 100;
+
 	if (line->flags & ML_EFFECT3) // relative calc
-		pfd.destvalue = max(min(po->translucency + ((line->flags & ML_DONTPEGBOTTOM) ?
-			(sides[line->sidenum[0]].textureoffset ?
-				max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS)
-				: max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), -NUMTRANSMAPS))
-			: (sides[line->sidenum[0]].textureoffset ?
-				max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), -1000) / 100
-				: max(min(line->frontsector->floorheight>>FRACBITS, 1000), -1000) / 100)),
-			NUMTRANSMAPS), 0);
+		pfd.destvalue = po->translucency + value;
 	else
-		pfd.destvalue = (line->flags & ML_DONTPEGBOTTOM) ?
-			(sides[line->sidenum[0]].textureoffset ?
-				max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, NUMTRANSMAPS), 0)
-				: max(min(line->frontsector->floorheight>>FRACBITS, NUMTRANSMAPS), 0))
-			: (sides[line->sidenum[0]].textureoffset ?
-				max(min(sides[line->sidenum[0]].textureoffset>>FRACBITS, 1000), 0) / 100
-				: max(min(line->frontsector->floorheight>>FRACBITS, 1000), 0) / 100);
+		pfd.destvalue = value;
+
+	pfd.destvalue = max(min(pfd.destvalue, NUMTRANSMAPS), 0);
 
 	// already equal, nothing to do
 	if (po->translucency == pfd.destvalue)

From de100b076a5843f695325dab5bf56c53d6a22072 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 4 May 2020 19:47:39 +0200
Subject: [PATCH 246/251] PolyObject: Allow translucency to be set via X offset

---
 src/p_polyobj.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index e35a124cd..13f7decf9 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -217,7 +217,11 @@ static void Polyobj_GetInfo(polyobj_t *po)
 	if (po->parent == po->id) // do not allow a self-reference
 		po->parent = -1;
 
-	po->translucency = (lines[i].frontsector->floorheight>>FRACBITS) / 100;
+	po->translucency = (lines[i].flags & ML_DONTPEGTOP)
+						? (sides[lines[i].sidenum[0]].textureoffset>>FRACBITS)
+						: ((lines[i].frontsector->floorheight>>FRACBITS) / 100);
+
+	po->translucency = max(min(po->translucency, NUMTRANSMAPS), 0);
 
 	po->flags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES;
 

From 41efc0786dee6d33692856cdfab5f329ba9638b1 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Mon, 4 May 2020 19:55:25 +0200
Subject: [PATCH 247/251] Add new PolyObject flag to ZB config

---
 extras/conf/SRB2-22.cfg | 1 +
 1 file changed, 1 insertion(+)

diff --git a/extras/conf/SRB2-22.cfg b/extras/conf/SRB2-22.cfg
index 1c1d11809..11206e75a 100644
--- a/extras/conf/SRB2-22.cfg
+++ b/extras/conf/SRB2-22.cfg
@@ -760,6 +760,7 @@ linedeftypes
 		{
 			title = "Parameters";
 			prefix = "(22)";
+			flags8text = "[3] Set translucency by X offset";
 			flags32text = "[5] Render outer sides only";
 			flags64text = "[6] Trigger linedef executor";
 			flags128text = "[7] Intangible";

From 5282f01a533fcb084e2e4ff6d176b6179c52377c Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Tue, 5 May 2020 08:40:59 +0200
Subject: [PATCH 248/251] Fix PolyObject flags not being applied when there is
 no parameter line

---
 src/p_polyobj.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 13f7decf9..cd63f4509 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -210,6 +210,8 @@ static void Polyobj_GetInfo(polyobj_t *po)
 {
 	INT32 i = P_FindSpecialLineFromTag(POLYINFO_SPECIALNUM, po->id, -1);
 
+	po->flags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES;
+
 	if (i == -1)
 		return; // no extra settings to apply, let's leave it
 
@@ -223,8 +225,6 @@ static void Polyobj_GetInfo(polyobj_t *po)
 
 	po->translucency = max(min(po->translucency, NUMTRANSMAPS), 0);
 
-	po->flags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES;
-
 	if (lines[i].flags & ML_EFFECT1)
 		po->flags |= POF_ONESIDE;
 

From 2d6c9a94f43bba89bf7843ab1ff743fa5f7952a5 Mon Sep 17 00:00:00 2001
From: Louis-Antoine <lamr@free.fr>
Date: Tue, 5 May 2020 14:05:19 +0200
Subject: [PATCH 249/251] Fix compiler warning

---
 src/d_clisrv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index f7755c148..43321d92d 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -5062,7 +5062,7 @@ void NetUpdate(void)
 
 		// In case the cvar value was lowered
 		if (joindelay)
-			joindelay = min(joindelay - 1, 3 * cv_joindelay.value * TICRATE);
+			joindelay = min(joindelay - 1, 3 * (tic_t)cv_joindelay.value * TICRATE);
 	}
 
 	nowtime /= NEWTICRATERATIO;

From 38232ce07ec09e44058bdc74d6d7dd4e122cdf88 Mon Sep 17 00:00:00 2001
From: Alam Ed Arias <alam@srb2.org>
Date: Wed, 6 May 2020 18:35:54 -0400
Subject: [PATCH 250/251] fix build errors in public master

---
 src/s_sound.c       | 2 +-
 src/w_wad.c         | 4 ++++
 src/win32/win_sys.c | 4 +++-
 src/win32/win_vid.c | 6 +++++-
 4 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/s_sound.c b/src/s_sound.c
index 8e9461d78..7cd025786 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -1672,7 +1672,7 @@ void S_LoadMusicDefs(UINT16 wadnum)
 	char *lf;
 	char *stoken;
 
-	size_t nlf;
+	size_t nlf = 0xFFFFFFFF;
 	size_t ncr;
 
 	musicdef_t *def = NULL;
diff --git a/src/w_wad.c b/src/w_wad.c
index 797f286d5..ea0a82fe9 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -76,6 +76,10 @@ int	snprintf(char *str, size_t n, const char *fmt, ...);
 //int	vsnprintf(char *str, size_t n, const char *fmt, va_list ap);
 #endif
 
+#ifdef _DEBUG
+#include "console.h"
+#endif
+
 #ifndef O_BINARY
 #define O_BINARY 0
 #endif
diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c
index 42733c309..f9d66be7f 100644
--- a/src/win32/win_sys.c
+++ b/src/win32/win_sys.c
@@ -3199,7 +3199,7 @@ INT32 I_GetKey(void)
 // -----------------
 #define DI_KEYBOARD_BUFFERSIZE 32 // number of data elements in keyboard buffer
 
-void I_StartupKeyboard(void)
+static void I_StartupKeyboard(void)
 {
 	DIPROPDWORD dip;
 
@@ -3435,6 +3435,8 @@ INT32 I_StartupSystem(void)
 	// some 'more global than globals' things to initialize here ?
 	graphics_started = keyboard_started = sound_started = cdaudio_started = false;
 
+	I_StartupKeyboard();
+
 #ifdef NDEBUG
 
 #ifdef BUGTRAP
diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c
index 4e7bab569..5fa219586 100644
--- a/src/win32/win_vid.c
+++ b/src/win32/win_vid.c
@@ -56,6 +56,7 @@ static consvar_t cv_stretch = {"stretch", "On", CV_SAVE|CV_NOSHOWHELP, CV_OnOff,
 static consvar_t cv_ontop = {"ontop", "Never", 0, CV_NeverOnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 
 boolean highcolor;
+int vid_opengl_state = 0;
 
 static BOOL bDIBMode; // means we are using DIB instead of DirectDraw surfaces
 static LPBITMAPINFO bmiMain = NULL;
@@ -949,7 +950,10 @@ INT32 VID_SetMode(INT32 modenum)
 }
 
 void VID_CheckRenderer(void) {}
-void VID_CheckGLLoaded(rendermode_t oldrender) {}
+void VID_CheckGLLoaded(rendermode_t oldrender)
+{
+	(void)oldrender;
+}
 
 // ========================================================================
 // Free the video buffer of the last video mode,

From 650f44566f5e8e2298b331cd5c14fcd252d11250 Mon Sep 17 00:00:00 2001
From: MascaraSnake <jonassauer27@gmail.com>
Date: Thu, 7 May 2020 21:59:39 +0200
Subject: [PATCH 251/251] Fixed a typo

---
 src/p_spec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/p_spec.c b/src/p_spec.c
index ac72eec15..feac4dea0 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -7710,7 +7710,7 @@ static void P_SpawnScrollers(void)
 			// scroll wall according to linedef
 			// (same direction and speed as scrolling floors)
 			case 502:
-				for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;)
+				for (s = -1; (s = P_FindLineFromTag(l->tag, s)) >= 0 ;)
 					if (s != (INT32)i)
 						Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[0], accel, 0);
 				break;