From 640948703f2c055b6efb9124400e2cb3350f5ee2 Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Mon, 9 Apr 2018 17:53:52 +0300
Subject: [PATCH 01/13] Level compatibility via ZScript -- PoC

---
 src/compatibility.cpp                         | 11 ++++++
 wadsrc/static/compatibility.txt               | 15 --------
 wadsrc/static/zscript.txt                     |  1 +
 wadsrc/static/zscript/level_compatibility.txt | 34 +++++++++++++++++++
 wadsrc/static/zscript/mapdata.txt             |  6 ++++
 5 files changed, 52 insertions(+), 15 deletions(-)
 create mode 100644 wadsrc/static/zscript/level_compatibility.txt

diff --git a/src/compatibility.cpp b/src/compatibility.cpp
index ff36f9434..7be7b4237 100644
--- a/src/compatibility.cpp
+++ b/src/compatibility.cpp
@@ -54,6 +54,7 @@
 #include "w_wad.h"
 #include "textures.h"
 #include "g_levellocals.h"
+#include "vm.h"
 
 // MACROS ------------------------------------------------------------------
 
@@ -532,6 +533,16 @@ void CheckCompatibility(MapData *map)
 
 void SetCompatibilityParams()
 {
+	PClass *const cls = PClass::FindClass("LevelCompatibility");
+	if (cls != nullptr)
+	{
+		PFunction *const func = dyn_cast<PFunction>(cls->FindSymbol("Apply", true));
+		if (func != nullptr)
+		{
+			VMCall(func->Variants[0].Implementation, nullptr, 0, nullptr, 0);
+		}
+	}
+
 	if (ii_compatparams != -1)
 	{
 		unsigned i = ii_compatparams;
diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt
index 673002877..7fec2a528 100644
--- a/wadsrc/static/compatibility.txt
+++ b/wadsrc/static/compatibility.txt
@@ -631,16 +631,6 @@ AAECADD4D97970AFF702D86FAFAC7D17 // doom.wad e4m4
 	setsectorspecial 264 0
 }
 
-
-AB24AE6E2CB13CBDD04600A4D37F9189 // doom2.wad map02
-1EC0AF1E3985650F0C9000319C599D0C // doom2bfg.wad map02
-{
-	// missing textures
-	setwalltexture 327 front bot STONE4
-	setwalltexture 328 front bot STONE4
-	setwalltexture 338 front bot STONE4
-	setwalltexture 339 front bot STONE4
-}
 CEC791136A83EEC4B91D39718BDF9D82 // doom2.wad map04
 {
 	// missing textures
@@ -667,11 +657,6 @@ CEC791136A83EEC4B91D39718BDF9D82 // doom2.wad map04
 	setsectortag 4 0
 	setsectortag 153 0
 }
-66C46385EB1A23D60839D1532522076B // doom2.wad map08
-{
-	// missing texture
-	setwalltexture 101 back top BRICK7
-}
 5BDA34DA60C0530794CC1EA2DA017976 // doom2.wad map14
 {
 	// missing textures
diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt
index 755e427dd..31531ed28 100644
--- a/wadsrc/static/zscript.txt
+++ b/wadsrc/static/zscript.txt
@@ -7,6 +7,7 @@ version "3.3"
 #include "zscript/actor.txt"
 #include "zscript/actor_checks.txt"
 #include "zscript/events.txt"
+#include "zscript/level_compatibility.txt"
 
 #include "zscript/menu/menuitembase.txt"
 #include "zscript/menu/menu.txt"
diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
new file mode 100644
index 000000000..17bddba13
--- /dev/null
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -0,0 +1,34 @@
+
+class LevelCompatibility play
+{
+	private static void Apply()
+	{
+		string checksum = level.GetChecksum();
+
+		if (   checksum ~== "AB24AE6E2CB13CBDD04600A4D37F9189"   // doom2.wad map02
+			|| checksum ~== "1EC0AF1E3985650F0C9000319C599D0C")  // doom2bfg.wad map02
+		{
+			// Missing textures
+			TextureID stone4 = TexMan.CheckForTexture("STONE4", TexMan.Type_Wall);
+			SetWallTextureID(327, Line.front, Side.bottom, stone4);
+			SetWallTextureID(328, Line.front, Side.bottom, stone4);
+			SetWallTextureID(338, Line.front, Side.bottom, stone4);
+			SetWallTextureID(339, Line.front, Side.bottom, stone4);
+		}
+		else if (checksum ~== "66C46385EB1A23D60839D1532522076B")  // doom2.wad map08
+		{
+			// Missing texture
+			SetWallTexture(101, Line.back, Side.top, "BRICK7");
+		}
+	}
+
+	private static void SetWallTexture(int line, int side, int texpart, String texture)
+	{
+		SetWallTextureID(line, side, texpart, TexMan.CheckForTexture(texture, TexMan.Type_Wall));
+	}
+
+	private static void SetWallTextureID(int line, int side, int texpart, TextureID texture)
+	{
+		level.Lines[line].sidedef[side].SetTexture(texpart, texture);
+	}
+}
diff --git a/wadsrc/static/zscript/mapdata.txt b/wadsrc/static/zscript/mapdata.txt
index 4267b7b05..fb62faff7 100644
--- a/wadsrc/static/zscript/mapdata.txt
+++ b/wadsrc/static/zscript/mapdata.txt
@@ -102,6 +102,12 @@ struct Side native play
 
 struct Line native play
 {
+	enum ESide
+	{
+		front=0,
+		back=1
+	}
+
 	enum ELineFlags
 	{
 		ML_BLOCKING					=0x00000001,	// solid, is an obstacle

From 9daad477c38823731f47de9a51416dad381305b3 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Mon, 9 Apr 2018 22:09:28 +0200
Subject: [PATCH 02/13] - some improvements to compatibility scripts:

* use names, not strings, to allow use of switch/case.
* avoid creating the checksum a second time per level.
* do an early-out check for maps that do not have scripted compatibility.
---
 src/compatibility.cpp                         | 32 ++++++++++-------
 src/compatibility.h                           |  4 +--
 src/p_setup.cpp                               |  4 +--
 wadsrc/static/zscript/level_compatibility.txt | 36 ++++++++++---------
 4 files changed, 44 insertions(+), 32 deletions(-)

diff --git a/src/compatibility.cpp b/src/compatibility.cpp
index 7be7b4237..52eb3aac4 100644
--- a/src/compatibility.cpp
+++ b/src/compatibility.cpp
@@ -466,7 +466,7 @@ void ParseCompatibility()
 //
 //==========================================================================
 
-void CheckCompatibility(MapData *map)
+FName CheckCompatibility(MapData *map)
 {
 	FMD5Holder md5;
 	FCompatValues *flags;
@@ -489,13 +489,16 @@ void CheckCompatibility(MapData *map)
 
 	flags = BCompatMap.CheckKey(md5);
 
+	FString hash;
+
+	for (size_t j = 0; j < sizeof(md5.Bytes); ++j)
+	{
+		hash.AppendFormat("%02X", md5.Bytes[j]);
+	}
+
 	if (developer >= DMSG_NOTIFY)
 	{
-		Printf("MD5 = ");
-		for (size_t j = 0; j < sizeof(md5.Bytes); ++j)
-		{
-			Printf("%02X", md5.Bytes[j]);
-		}
+		Printf("MD5 = %s", hash.GetChars());
 		if (flags != NULL)
 		{
 			Printf(", cflags = %08x, cflags2 = %08x, bflags = %08x\n",
@@ -523,6 +526,7 @@ void CheckCompatibility(MapData *map)
 	{
 		ib_compatflags |= BCOMPATF_FLOATBOB;
 	}
+	return FName(hash, true);	// if this returns NAME_None it means there is no scripted compatibility handler.
 }
 
 //==========================================================================
@@ -531,15 +535,19 @@ void CheckCompatibility(MapData *map)
 //
 //==========================================================================
 
-void SetCompatibilityParams()
+void SetCompatibilityParams(FName checksum)
 {
-	PClass *const cls = PClass::FindClass("LevelCompatibility");
-	if (cls != nullptr)
+	if (checksum != NAME_None)
 	{
-		PFunction *const func = dyn_cast<PFunction>(cls->FindSymbol("Apply", true));
-		if (func != nullptr)
+		PClass *const cls = PClass::FindClass("LevelCompatibility");
+		if (cls != nullptr)
 		{
-			VMCall(func->Variants[0].Implementation, nullptr, 0, nullptr, 0);
+			PFunction *const func = dyn_cast<PFunction>(cls->FindSymbol("Apply", true));
+			if (func != nullptr)
+			{
+				VMValue param = { (int)checksum };
+				VMCall(func->Variants[0].Implementation, &param, 1, nullptr, 0);
+			}
 		}
 	}
 
diff --git a/src/compatibility.h b/src/compatibility.h
index 125f83f34..e219f5d0a 100644
--- a/src/compatibility.h
+++ b/src/compatibility.h
@@ -36,7 +36,7 @@ struct FMD5HashTraits
 extern TMap<FMD5Holder, FCompatValues, FMD5HashTraits> BCompatMap;
 
 void ParseCompatibility();
-void CheckCompatibility(MapData *map);
-void SetCompatibilityParams();
+FName CheckCompatibility(MapData *map);
+void SetCompatibilityParams(FName);
 
 #endif
diff --git a/src/p_setup.cpp b/src/p_setup.cpp
index 648502542..6f84da6d9 100644
--- a/src/p_setup.cpp
+++ b/src/p_setup.cpp
@@ -3756,7 +3756,7 @@ void P_SetupLevel (const char *lumpname, int position)
 		{
 			level.maptype = MAPTYPE_UDMF;
 		}
-		CheckCompatibility(map);
+		FName checksum = CheckCompatibility(map);
 		if (ib_compatflags & BCOMPATF_REBUILDNODES)
 		{
 			ForceNodeBuild = true;
@@ -3834,7 +3834,7 @@ void P_SetupLevel (const char *lumpname, int position)
 			times[0].Unclock();
 		}
 
-		SetCompatibilityParams();
+		SetCompatibilityParams(checksum);
 
 		times[6].Clock();
 		P_LoopSidedefs (true);
diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
index 17bddba13..7b446370a 100644
--- a/wadsrc/static/zscript/level_compatibility.txt
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -1,24 +1,28 @@
 
 class LevelCompatibility play
 {
-	private static void Apply()
+	private static void Apply(Name checksum)
 	{
-		string checksum = level.GetChecksum();
-
-		if (   checksum ~== "AB24AE6E2CB13CBDD04600A4D37F9189"   // doom2.wad map02
-			|| checksum ~== "1EC0AF1E3985650F0C9000319C599D0C")  // doom2bfg.wad map02
+		switch (checksum)
 		{
-			// Missing textures
-			TextureID stone4 = TexMan.CheckForTexture("STONE4", TexMan.Type_Wall);
-			SetWallTextureID(327, Line.front, Side.bottom, stone4);
-			SetWallTextureID(328, Line.front, Side.bottom, stone4);
-			SetWallTextureID(338, Line.front, Side.bottom, stone4);
-			SetWallTextureID(339, Line.front, Side.bottom, stone4);
-		}
-		else if (checksum ~== "66C46385EB1A23D60839D1532522076B")  // doom2.wad map08
-		{
-			// Missing texture
-			SetWallTexture(101, Line.back, Side.top, "BRICK7");
+			case 'AB24AE6E2CB13CBDD04600A4D37F9189':   // doom2.wad map02
+			case '1EC0AF1E3985650F0C9000319C599D0C':  // doom2bfg.wad map02
+			{
+				// Missing textures
+				TextureID stone4 = TexMan.CheckForTexture("STONE4", TexMan.Type_Wall);
+				SetWallTextureID(327, Line.front, Side.bottom, stone4);
+				SetWallTextureID(328, Line.front, Side.bottom, stone4);
+				SetWallTextureID(338, Line.front, Side.bottom, stone4);
+				SetWallTextureID(339, Line.front, Side.bottom, stone4);
+				break;
+			}
+			
+			case '66C46385EB1A23D60839D1532522076B':  // doom2.wad map08
+			{
+				// Missing texture
+				SetWallTexture(101, Line.back, Side.top, "BRICK7");
+				break;
+			}
 		}
 	}
 

From 65a219eeccb381b1797884e2c7d24b726c372141 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Tue, 10 Apr 2018 20:02:41 +0200
Subject: [PATCH 03/13] - sorted compatibility.txt so that levels which only
 have flags set are at the top of the file.

---
 wadsrc/static/compatibility.txt               | 390 +++++++-----------
 wadsrc/static/zscript/level_compatibility.txt |   5 +
 2 files changed, 153 insertions(+), 242 deletions(-)

diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt
index 7fec2a528..cf682f732 100644
--- a/wadsrc/static/compatibility.txt
+++ b/wadsrc/static/compatibility.txt
@@ -1,35 +1,3 @@
-6DC9F6CCEAE7A91AEC48EBE506F22BC4 // void.wad MAP01
-{
-	// Slightly squash the pillars in the starting room with "stimpacks"
-	// floating on them so that they can be obtained.
-	setsectoroffset 62 floor -8
-	setwallyscale 286 front bot 1.090909
-	setwallyscale 287 front bot 1.090909
-	setwallyscale 288 front bot 1.090909
-	setwallyscale 289 front bot 1.090909
-	
-	setsectoroffset 63 floor -8
-	setwallyscale 290 front bot 1.090909
-	setwallyscale 291 front bot 1.090909
-	setwallyscale 292 front bot 1.090909
-	setwallyscale 293 front bot 1.090909
-	
-	setsectoroffset 118 floor -8
-	setwallyscale 710 front bot 1.090909
-	setwallyscale 711 front bot 1.090909
-	setwallyscale 712 front bot 1.090909
-	setwallyscale 713 front bot 1.090909
-	
-	setsectoroffset 119 floor -8
-	setwallyscale 714 front bot 1.090909
-	setwallyscale 715 front bot 1.090909
-	setwallyscale 716 front bot 1.090909
-	setwallyscale 717 front bot 1.090909
-
-	setslopeoverflow
-	polyobj
-}
-
 B2D8DA03489D1C67F60DC87FBC4EA338 // map01 - Massmouth 2
 801304DA3784308D333951B5E0CF8E9E // map02
 6EA4D5CAEA16857B2A882467E1633BC2 // map03
@@ -52,15 +20,6 @@ A80E7EE40E0D0C76A6FBD242BE29FE27 // map15
 	resetplayerspeed
 }
 
-5C594C67CF7721005DE71429F9811370 // Eternal Doom map03
-{
-	// fix broken staircase. The compatibility option is not sufficient
-	// to reliably handle this so clear the tags from the unwanted sectors.
-	setsectortag 212 0
-	setsectortag 213 0
-	setsectortag 214 0
-}
-
 6DA6FCBA8089161BDEC6A1D3F6C8D60F // Eternal Doom MAP25
 {
 	stairs
@@ -77,7 +36,6 @@ A80E7EE40E0D0C76A6FBD242BE29FE27 // map15
 	useblocking
 }
 
-// mostly cosmetic (except AV MAP07 and MM2 MAP25)
 0EECBF37B328C9CAAF20DED4949A4157 // Sudtic e2m6
 4ACE0644883BDA0CBA254FA02C9ACF83 // Teutic e3m4
 9F2BE080A33F775294BD78822456924E // Nukemine e1m4
@@ -87,6 +45,7 @@ CD31793D3A4B00231B124C0C23649644 // Strain map02
 F84AB4557464A383E93F37CD3A82AC48 // MM2 map03
 1497894956B3C8EBE8A240B7FDD99C6A // MM2 map25
 941E4CB56EE4184E0B1ED43486AB0BBF // AV map07
+6D4156EE0D12B77AD143A37C4D3DCF98 // dmonfear.wad map22
 {
 	shorttex
 }
@@ -97,11 +56,6 @@ F84AB4557464A383E93F37CD3A82AC48 // MM2 map03
 	trace
 }
 
-9D50EBE17CEC78938C7A668DB0768611 // Strain map07: Make the exit accessible
-{
-	clearlineflags 1021 1
-}
-
 71C2E6D9CFA3D8750C6A9599FB2453BD // Hacx map03: There are some switches behind 
 96368EB950E33AF62EA6423434E3CEF7 // HacX map17: shootable covers in these levels
 BA530202AF0BA0C6CBAE6A0C7076FB72 // Requiem map04
@@ -180,11 +134,6 @@ CA267398C9B3A8F79349D3394F8B2106 // map20
 	spritesort
 }
 
-DCE862393CAAA6FF1294FB7056B53057 // UAC Ultra map07: Contains a scroller depending on Boom side effects
-{
-	setlinespecial 391 Sector_CopyScroller 99 6 0 0 0
-}
-
 1D9E43988940CCD3555724E15DD8B1AB // Happy Time Circus map01 has bad teleporters
 040F83028FFA74456E335ED300BE2C33 // MAP17 (TownInfection.wad)
 156FA31F5FF72A87BF345B68029D3051 // MAP02 (nprject5.wad)
@@ -201,6 +150,101 @@ AF40D0E49BD1B76D4B1AADD8212ADC46 // MAP01 (the wad that shall not be named =P)
 	badangles
 }
 
+8FA29398776146189396AA1AC6BB9E13 // Roger Ritenour's Phobos map03
+{
+	floormove
+}
+
+// There is a special at the beginning of the level which relies on the Pain Elemental's lost soul limit.
+811A0C97777A198BC9B2BB558CB46E6A // Hell Revealed map19
+{
+	limitpain
+}
+
+7C1913DEE396BA26CFF22A0E9369B7D2 // Nuke Mine, e1m2
+{
+	pointonline
+}
+
+8B2AC8D4DB4A49A5DCCBB067E04434D6 // The Hell Factory Hub One, map04
+65A1EB4C87386F290816660A52932FF1 // Master Levels, garrison.wad
+3DEE4EFEFAF3260C800A30734F54CE75 // Hellbound, map14
+5FAA25F5A6AAB3409CAE0AF87F910341 // DOOM.wad e1m6
+94893A0DC429A22ADC4B3A73DA537E16 // DOOM2.WAD map25
+{
+	rebuildnodes
+}
+
+64B6CE3CB7349B6F6B1A885C449ACB96 // Super Sonic Doom, map31
+{
+	// During the end-of-level tally, both PROP_FROZEN and PROP_TOTALLYFROZEN
+	// are set, but only PROP_TOTALLYFROZEN is cleared, so PROP_FROZEN is
+	// still set when returning to the origin map.
+	linkfrozenprops
+}
+
+E89CCC7E155F1032F693359CC219BE6C // hexen.wad map30
+B9DFF13207EACAC675C71D82624D0007 // XtheaterIII map01
+6941BDC2F80C0FEBE34EFA23D5FB72B7 // sonic.wad map10
+3ABB618A475BCBC531B457BAA6E4E70A // Daedalus map04
+795FDE3CC1C97140F326D0152B3FCE2A // Daedalus map24
+{
+	DisablePushWindowCheck
+}
+
+D0139194F7817BF06F3988DFC47DB38D // Whispers of Satan map29
+{
+	
+}
+
+5397C3B7D9B33AAF526D15A81A762828 // daedalus.wad Travel tubes (they are all identical)
+{
+	multiexit
+}
+
+C98F79709BD7E0E4C19026AB9575EC6F // cc-cod.zip:codlev.wad map07
+{
+	maskedmidtex
+}
+
+7B82B12A6990E09553B12FDB4E3824A0 // hti.wad map01
+{
+	teleport
+}
+
+8570AA0D6737C0A19DB66767764F157F // sonic.wad map04
+{
+	noslopeid
+}
+
+3FFAF2F624C1B4BB6F581DCF7B99CBA7 // hexen.wad MAP36
+7DC65D5029DD834481CD716B3D71388A // hexdd.wad MAP47
+05AA32F1D2220A462DCDA245ED22B94B // sonic.wad map09
+{
+	polyobj
+}
+
+
+D7F6E9F08C39A17026349A04F8C0B0BE // Return to Hadron, e1m9
+19D03FFC875589E21EDBB7AB74EF4AEF // Return to Hadron, e1m9, 2016.01.03 update
+{
+	pointonline
+}
+
+1ED329858AB154C55878DA1C11A4F100 // unloved.pk3:unlovedmaps.wad map01
+FA23E72FA955E66EC68609F72C0BA71E // unloved.pk3:unlovedmaps.wad map02
+41BEC1F643CFEEC997AF98276A05EC88 // unloved.pk3:unlovedmaps.wad map03
+AF9A6370BE562584BC11165ECF364713 // unloved.pk3:unlovedmaps.wad map04
+DC96228097DD004C40CCB1DB14A91EAA // unloved.pk3:unlovedmaps.wad map05
+261E64897A572C8DB8DC041E64BE27AD // unloved2beta1.pk3:u2_new2maps2.wad map06
+04800B1F35E8C036EBABC8C616402927 // unloved2beta1.pk3:u2_new2maps2.wad map07
+9E54F70648A77BBD090FF78A3AA05367 // unloved2beta1.pk3:u2_new2maps2.wad map08
+72E9E0F41F691B7F956E62F35B4A617F // unloved2beta1.pk3:u2_new2maps2.wad map09
+3D3FE412E87AD8B2316DAEC9E25F2E5D // unloved2beta1.pk3:u2_new2maps2.wad map10
+{
+	clipmidtex
+}
+
 E2B5D1400279335811C1C1C0B437D9C8 // Deathknights of the Dark Citadel, map54
 {
 	// This map has two gear boxes which are flagged for player cross
@@ -214,103 +258,6 @@ E2B5D1400279335811C1C1C0B437D9C8 // Deathknights of the Dark Citadel, map54
 	clearlinespecial 66
 }
 
-8FA29398776146189396AA1AC6BB9E13 // Roger Ritenour's Phobos map03
-{
-	floormove
-}
-
-// There is a special at the beginning of the level which relies on the Pain Elemental's lost soul limit.
-811A0C97777A198BC9B2BB558CB46E6A // Hell Revealed map19
-{
-	limitpain
-}
-
-// Daedalus: Fix SPAC_Push lines that aren't on lines you can actually push
-3ABB618A475BCBC531B457BAA6E4E70A // map04
-{
-	// forcefields
-	// the lines we're setting are already set for repeatable SPAC_Push
-	clearlinespecial 90
-	setlinespecial 3749 ACS_Execute 23 0 1 0 0
-	clearlinespecial 94
-	setlinespecial 3766 ACS_Execute 23 0 2 0 0
-	clearlinespecial 92
-	setlinespecial 3777 ACS_Execute 23 0 3 0 0
-	clearlinespecial 98
-	setlinespecial 3784 ACS_Execute 23 0 4 0 0
-}
-795FDE3CC1C97140F326D0152B3FCE2A // map24
-{
-	// doors
-	clearlinespecial 1512
-	setlinespecial 1505 Door_Raise 213 50 100 0 0
-	setlineflags 1505 0x200		// repeatable
-	setactivation 1505 16		// SPAC_Push
-	clearlinespecial 1514
-	setlinespecial 1508 Door_Raise 213 50 100 0 0
-	setlineflags 1508 0x200
-	setactivation 1508 16
-	
-	clearlinespecial 1525
-	setlinespecial 1522 Door_Raise 214 50 100 0 0
-	setlineflags 1522 0x200
-	setactivation 1522 16
-	clearlinespecial 1530
-	setlinespecial 1527 Door_Raise 214 50 100 0 0
-	setlineflags 1527 0x200
-	setactivation 1527 16
-	
-	clearlinespecial 5277
-	setlinespecial 5209 Door_Raise 24 20 255 0 0
-	setlineflags 5209 0x200
-	setactivation 5209 16
-	clearlinespecial 5714
-	setlinespecial 5267 Door_Raise 24 20 255 0 0
-	setlineflags 5267 0x200
-	setactivation 5267 16
-	
-	clearlinespecial 5715
-	setlinespecial 5229 Door_Raise 24 20 255 0 0
-	setlineflags 5229 0x200
-	setactivation 5229 16
-	clearlinespecial 5345
-	setlinespecial 5232 Door_Raise 24 20 255 0 0
-	setlineflags 5232 0x200
-	setactivation 5232 16
-	
-	// consoles?
-	clearlinespecial 3639
-	setlinespecial 3633 ACS_Execute 14 0 0 0 0
-	setlinespecial 3635 ACS_Execute 14 0 0 0 0
-	setlineflags 3633 0x200
-	setlineflags 3635 0x200
-	setactivation 3633 16
-	setactivation 3635 16
-
-	clearlinespecial 3647
-	setlinespecial 3644 ACS_Execute 14 0 0 0 0
-	setlinespecial 3641 ACS_Execute 14 0 0 0 0
-	setlineflags 3644 0x200
-	setlineflags 3641 0x200
-	setactivation 3644 16
-	setactivation 3641 16
-	
-	clearlinespecial 3659
-	clearlinespecial 3657
-	setlinespecial 3653 ACS_Execute 13 0 0 0 0
-	setlinespecial 3655 ACS_Execute 13 0 0 0 0
-	setlinespecial 3651 ACS_Execute 13 0 0 0 0
-	setlinespecial 3654 ACS_Execute 13 0 0 0 0
-	setlineflags 3653 0x200
-	setlineflags 3655 0x200
-	setlineflags 3651 0x200
-	setlineflags 3654 0x200
-	setactivation 3653 16
-	setactivation 3655 16
-	setactivation 3651 16
-	setactivation 3654 16
-}
-
 // Community Chest 3
 F481922F4881F74760F3C0437FD5EDD0 // map03
 {
@@ -320,11 +267,6 @@ F481922F4881F74760F3C0437FD5EDD0 // map03
 	setlinespecial 3559 Sector_CopyScroller 17 6 0 0 0
 }
 
-7C1913DEE396BA26CFF22A0E9369B7D2 // Nuke Mine, e1m2
-{
-	pointonline
-}
-
 5B862477519B21B30059A466F2FF6460 // Khorus, map08
 {
 	// This map uses a voodoo conveyor with slanted walls to shunt the
@@ -342,14 +284,6 @@ F481922F4881F74760F3C0437FD5EDD0 // map03
 	setactivation 455 16		// SPAC_Push
 }
 
-8B2AC8D4DB4A49A5DCCBB067E04434D6 // The Hell Factory Hub One, map04
-65A1EB4C87386F290816660A52932FF1 // Master Levels, garrison.wad
-3DEE4EFEFAF3260C800A30734F54CE75 // Hellbound, map14
-5FAA25F5A6AAB3409CAE0AF87F910341 // DOOM.wad e1m6
-{
-	rebuildnodes
-}
-
 3D1E36E50F5A8D289E15433941605224 // Master Levels, catwalk.wad
 {
 	// make it impossible to open door to 1-way bridge before getting red key
@@ -407,14 +341,6 @@ F0E6F30F57B0425F17E43600AA813E80 // Ultimate Simplicity, map11
 	setthingz 918 296
 }
 
-64B6CE3CB7349B6F6B1A885C449ACB96 // Super Sonic Doom, map31
-{
-	// During the end-of-level tally, both PROP_FROZEN and PROP_TOTALLYFROZEN
-	// are set, but only PROP_TOTALLYFROZEN is cleared, so PROP_FROZEN is
-	// still set when returning to the origin map.
-	linkfrozenprops
-}
-
 D62DCA9EC226DE49108D5DD9271F7631 // Cheogsh 2 map04
 {
 	// Stuff in megasphere cage is positioned too low
@@ -430,13 +356,6 @@ D62DCA9EC226DE49108D5DD9271F7631 // Cheogsh 2 map04
 	setthingz 1649 528
 }
 
-E89CCC7E155F1032F693359CC219BE6C // hexen.wad map30
-B9DFF13207EACAC675C71D82624D0007 // XtheaterIII map01
-6941BDC2F80C0FEBE34EFA23D5FB72B7 // sonic.wad map10
-{
-	DisablePushWindowCheck
-}
-
 DFC18B92BF3E8142B8684ECD8BD2EF06 // TNT: Evilution map15
 {
 	// raise up sector with its counterpart so 100% kills becomes possible
@@ -489,43 +408,6 @@ D99AD22FF21A41B4EECDB3A7C803D75E // TNT: Evilution map32
 	setlinespecial 1227 Plat_DownWaitUpStayLip 20 64 150 0 0
 }
 
-D0139194F7817BF06F3988DFC47DB38D // Whispers of Satan map29
-{
-	nopassover
-}
-
-5397C3B7D9B33AAF526D15A81A762828 // daedalus.wad Travel tubes (they are all identical)
-{
-	multiexit
-}
-
-C98F79709BD7E0E4C19026AB9575EC6F // cc-cod.zip:codlev.wad map07
-{
-	maskedmidtex
-}
-
-7B82B12A6990E09553B12FDB4E3824A0 // hti.wad map01
-{
-	teleport
-}
-
-8570AA0D6737C0A19DB66767764F157F // sonic.wad map04
-{
-	noslopeid
-}
-
-05AA32F1D2220A462DCDA245ED22B94B // sonic.wad map09
-{
-	polyobj
-}
-
-
-D7F6E9F08C39A17026349A04F8C0B0BE // Return to Hadron, e1m9
-19D03FFC875589E21EDBB7AB74EF4AEF // Return to Hadron, e1m9, 2016.01.03 update
-{
-	pointonline
-}
-
 5B26545FF21B051CA06D389CE535684C // doom.wad e1m4
 {
 	// missing textures	
@@ -685,10 +567,6 @@ EBDAC00E9D25D884B2C8F4B1F0390539 // doom2.wad map21
 	setsectoroffset 50 ceil -56
 	setsectoroffset 54 ceil -56
 }
-94893A0DC429A22ADC4B3A73DA537E16 // DOOM2.WAD map25
-{
-   rebuildnodes
-}
 110F84DE041052B59307FAF0293E6BC0 // Doom II, map27
 {
 	setsectorspecial 93 0
@@ -747,19 +625,6 @@ B68EB7CFB4CC481796E2919B9C16DFBD // Moc11.wad e1m6
 	setlinespecial 2410 Sector_Set3DFloor 32002 4 1 0 0
 }
 
-1ED329858AB154C55878DA1C11A4F100 // unloved.pk3:unlovedmaps.wad map01
-FA23E72FA955E66EC68609F72C0BA71E // unloved.pk3:unlovedmaps.wad map02
-41BEC1F643CFEEC997AF98276A05EC88 // unloved.pk3:unlovedmaps.wad map03
-AF9A6370BE562584BC11165ECF364713 // unloved.pk3:unlovedmaps.wad map04
-DC96228097DD004C40CCB1DB14A91EAA // unloved.pk3:unlovedmaps.wad map05
-261E64897A572C8DB8DC041E64BE27AD // unloved2beta1.pk3:u2_new2maps2.wad map06
-04800B1F35E8C036EBABC8C616402927 // unloved2beta1.pk3:u2_new2maps2.wad map07
-9E54F70648A77BBD090FF78A3AA05367 // unloved2beta1.pk3:u2_new2maps2.wad map08
-72E9E0F41F691B7F956E62F35B4A617F // unloved2beta1.pk3:u2_new2maps2.wad map09
-3D3FE412E87AD8B2316DAEC9E25F2E5D // unloved2beta1.pk3:u2_new2maps2.wad map10
-{
-	clipmidtex
-}
 
 
 // Cosmetic fixes for Heretic: Shadow of the Serpent Riders
@@ -832,12 +697,6 @@ CA3773ED313E8899311F3DD0CA195A68 // e3m6
 	setwalltexture 3431 back top BRKGRY01
 }
 
-3FFAF2F624C1B4BB6F581DCF7B99CBA7 // hexen.wad MAP36
-7DC65D5029DD834481CD716B3D71388A // hexdd.wad MAP47
-{
-	polyobj
-}
-
 3D8ED20BF5CAAE6D6AE0E10999C75084 // hgarden.pk3 map01
 {
 	// spawn trees on top of arches
@@ -849,11 +708,6 @@ CA3773ED313E8899311F3DD0CA195A68 // e3m6
 	setthingz 404 168
 }
 
-6D4156EE0D12B77AD143A37C4D3DCF98 // dmonfear.wad map22
-{
-	shorttex
-}
-
 FCCA97FC851F6473EAA069F74247B317 // pg-raw.wad map31
 {
 	setlinesectorref 331 front 74
@@ -867,3 +721,55 @@ FCCA97FC851F6473EAA069F74247B317 // pg-raw.wad map31
 	setsectortag 74 4
 	setlinespecial 357 Transfer_Heights 4 2 0 0 0 
 }
+
+6DC9F6CCEAE7A91AEC48EBE506F22BC4 // void.wad MAP01
+{
+	// Slightly squash the pillars in the starting room with "stimpacks"
+	// floating on them so that they can be obtained.
+	setsectoroffset 62 floor -8
+	setwallyscale 286 front bot 1.090909
+	setwallyscale 287 front bot 1.090909
+	setwallyscale 288 front bot 1.090909
+	setwallyscale 289 front bot 1.090909
+	
+	setsectoroffset 63 floor -8
+	setwallyscale 290 front bot 1.090909
+	setwallyscale 291 front bot 1.090909
+	setwallyscale 292 front bot 1.090909
+	setwallyscale 293 front bot 1.090909
+	
+	setsectoroffset 118 floor -8
+	setwallyscale 710 front bot 1.090909
+	setwallyscale 711 front bot 1.090909
+	setwallyscale 712 front bot 1.090909
+	setwallyscale 713 front bot 1.090909
+	
+	setsectoroffset 119 floor -8
+	setwallyscale 714 front bot 1.090909
+	setwallyscale 715 front bot 1.090909
+	setwallyscale 716 front bot 1.090909
+	setwallyscale 717 front bot 1.090909
+
+	setslopeoverflow
+	polyobj
+}
+
+5C594C67CF7721005DE71429F9811370 // Eternal Doom map03
+{
+	// fix broken staircase. The compatibility option is not sufficient
+	// to reliably handle this so clear the tags from the unwanted sectors.
+	setsectortag 212 0
+	setsectortag 213 0
+	setsectortag 214 0
+}
+
+9D50EBE17CEC78938C7A668DB0768611 // Strain map07: Make the exit accessible
+{
+	clearlineflags 1021 1
+}
+
+DCE862393CAAA6FF1294FB7056B53057 // UAC Ultra map07: Contains a scroller depending on Boom side effects
+{
+	setlinespecial 391 Sector_CopyScroller 99 6 0 0 0
+}
+
diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
index 7b446370a..695a43b01 100644
--- a/wadsrc/static/zscript/level_compatibility.txt
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -35,4 +35,9 @@ class LevelCompatibility play
 	{
 		level.Lines[line].sidedef[side].SetTexture(texpart, texture);
 	}
+	
+	private static void SetSectorSpecial(int sectornum, int special)
+	{
+		level.sectors[sectornum].special = special;
+	}
 }

From 0ecbf07769b6a738c3b92e327746312b6d7e73ea Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Tue, 10 Apr 2018 23:19:22 +0200
Subject: [PATCH 04/13] -ported a large part of compatibility.txt

---
 src/compatibility.cpp                         |  72 +++
 wadsrc/static/compatibility.txt               | 357 ---------------
 wadsrc/static/zscript/level_compatibility.txt | 415 ++++++++++++++++++
 3 files changed, 487 insertions(+), 357 deletions(-)

diff --git a/src/compatibility.cpp b/src/compatibility.cpp
index 52eb3aac4..beb07dc9c 100644
--- a/src/compatibility.cpp
+++ b/src/compatibility.cpp
@@ -772,6 +772,78 @@ void SetCompatibilityParams(FName checksum)
 	}
 }
 
+DEFINE_ACTION_FUNCTION(DLevelCompatibility, OffsetSectorPlane)
+{
+	PARAM_PROLOGUE;
+	PARAM_INT(sector);
+	PARAM_INT(planeval);
+	PARAM_FLOAT(delta);
+
+	sector_t *sec = &level.sectors[sector];
+	secplane_t& plane = sector_t::floor == planeval? sec->floorplane : sec->ceilingplane;
+	plane.ChangeHeight(delta);
+	sec->ChangePlaneTexZ(planeval, delta);
+	return 0;
+}
+
+DEFINE_ACTION_FUNCTION(DLevelCompatibility, ClearSectorTags)
+{
+	PARAM_PROLOGUE;
+	PARAM_INT(sector);
+	tagManager.RemoveSectorTags(sector);
+	return 0;
+}
+
+DEFINE_ACTION_FUNCTION(DLevelCompatibility, AddSectorTag)
+{
+	PARAM_PROLOGUE;
+	PARAM_INT(sector);
+	PARAM_INT(tag);
+	tagManager.AddSectorTag(sector, tag);
+	return 0;
+}
+
+DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingSkills)
+{
+	PARAM_PROLOGUE;
+	PARAM_INT(thing);
+	PARAM_INT(skillmask);
+
+	if ((unsigned)thing < MapThingsConverted.Size())
+	{
+		MapThingsConverted[thing].SkillFilter = skillmask;
+	}
+	return 0;
+}
+
+DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingZ)
+{
+	PARAM_PROLOGUE;
+	PARAM_INT(thing);
+	PARAM_FLOAT(z);
+
+	if ((unsigned)thing < MapThingsConverted.Size())
+	{
+		MapThingsConverted[thing].pos.Z = z;
+	}
+	return 0;
+}
+
+DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingFlags)
+{
+	PARAM_PROLOGUE;
+	PARAM_INT(thing);
+	PARAM_INT(flags);
+
+	if ((unsigned)thing < MapThingsConverted.Size())
+	{
+		MapThingsConverted[thing].flags = flags;
+	}
+	return 0;
+}
+
+
+
 //==========================================================================
 //
 // CCMD mapchecksum
diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt
index cf682f732..7ca81e403 100644
--- a/wadsrc/static/compatibility.txt
+++ b/wadsrc/static/compatibility.txt
@@ -245,366 +245,9 @@ DC96228097DD004C40CCB1DB14A91EAA // unloved.pk3:unlovedmaps.wad map05
 	clipmidtex
 }
 
-E2B5D1400279335811C1C1C0B437D9C8 // Deathknights of the Dark Citadel, map54
-{
-	// This map has two gear boxes which are flagged for player cross
-	// activation instead of the proper player uses activation.
-	setactivation 963 2
-	setactivation 943 2
-}
 
-3F249EDD62A3A08F53A6C53CB4C7ABE5 // Artica 3 map01
-{
-	clearlinespecial 66
-}
 
-// Community Chest 3
-F481922F4881F74760F3C0437FD5EDD0 // map03
-{
-	// I have no idea how this conveyor belt setup manages to work under Boom.
-	// Set the sector the voodoo doll ends up standing on when sectors tagged
-	// 1 are raised so that the voodoo doll will be carried.
-	setlinespecial 3559 Sector_CopyScroller 17 6 0 0 0
-}
 
-5B862477519B21B30059A466F2FF6460 // Khorus, map08
-{
-	// This map uses a voodoo conveyor with slanted walls to shunt the
-	// voodoo doll into side areas. For some reason, this voodoo doll
-	// is unable to slide on them, because the slide calculation gets
-	// them slightly inside the walls and thinks they are stuck. I could
-	// not reproduce this with the real player, which is what has me
-	// stumped. So, help them out be attaching some ThrustThing specials
-	// to the walls.
-	setlinespecial 443 ThrustThing 96 4 0 0 0
-	setlineflags 443 0x200		// repeatable
-	setactivation 443 16		// SPAC_Push
-	setlinespecial 455 ThrustThing 96 4 0 0 0
-	setlineflags 455 0x200		// repeatable
-	setactivation 455 16		// SPAC_Push
-}
-
-3D1E36E50F5A8D289E15433941605224 // Master Levels, catwalk.wad
-{
-	// make it impossible to open door to 1-way bridge before getting red key
-	setsectortag 35 0 // existing tag must be cleared before new one can be set
-	setsectortag 35 15
-	setactivation 605 1 // SPAC_PCross
-	setactivation 606 1
-	setactivation 607 1
-	setactivation 608 1
-	setlinespecial 605 Door_Open 15 64 0 0 0 // fast, stay open
-	setlinespecial 606 Door_Open 15 64 0 0 0
-	setlinespecial 607 Door_Open 15 64 0 0 0
-	setlinespecial 608 Door_Open 15 64 0 0 0
-}
-
-3B9CAA02952F405269353FAAD8F8EC33 // Master Levels, nessus.wad
-{
-	// move secret sector from too-thin doorframe to BFG closet
-	setsectorspecial 211 0
-	setsectorspecial 212 1024
-	// lower floor a bit so secret sector can be entered fully
-	setsectoroffset 212 floor -16
-	// make secret door stay open so you can't get locked in closet
-	setlinespecial 1008 Door_Open 0 64 0 0 0
-}
-
-7ED9800213C00D6E7FB98652AB48B3DE // Ultimate Simplicity, map04
-{
-	// Add missing map spots on easy and medium skills
-	// Demons will teleport into starting room making 100% kills possible
-	setthingskills 31 31
-	setthingskills 32 31
-}
-
-1891E029994B023910CFE0B3209C3CDB // Ultimate Simplicity, map07
-{
-	// It is possible to get stuck on skill 0 or 1 when no shots have been fired
-	// after sector 17 became accessible and before entering famous mancubus room.
-	// Monsters from the mentioned sector won't be alerted and so 
-	// they won't teleport into the battle. ACS will wait forever for their deaths.
-	setlinespecial 397 NoiseAlert 0 0 0 0 0
-	setlinespecial 411 NoiseAlert 0 0 0 0 0
-}
-
-F0E6F30F57B0425F17E43600AA813E80 // Ultimate Simplicity, map11
-{
-	// If door (sector #309) is closed it cannot be open again
-	// from one side potentially blocking level progression
-	clearlinespecial 2445
-}
-
-952CC8D03572E17BA550B01B366EFBB9 // Cheogsh map01
-{
-	// make the blue key spawn above the 3D floor
-	setthingz 918 296
-}
-
-D62DCA9EC226DE49108D5DD9271F7631 // Cheogsh 2 map04
-{
-	// Stuff in megasphere cage is positioned too low
-	setthingz 1640 528
-	setthingz 1641 528
-	setthingz 1642 528
-	setthingz 1643 528
-	setthingz 1644 528
-	setthingz 1645 528
-	setthingz 1646 528
-	setthingz 1647 528
-	setthingz 1648 528
-	setthingz 1649 528
-}
-
-DFC18B92BF3E8142B8684ECD8BD2EF06 // TNT: Evilution map15
-{
-	// raise up sector with its counterpart so 100% kills becomes possible
-	setsectortag 330 11
-}
-
-2C4A3356C5EB3526D2C72A4AA4B18A36 // TNT: Evilution map29
-{
-	// remove mancubus who always gets stuck in teleport tunnel, preventing
-	// 100% kills on HMP
-	setthingflags 405 0
-}
-
-A53AE580A4AF2B5D0B0893F86914781E // TNT: Evilution map31
-{
-	setthingflags 470 2016
-}
-
-D99AD22FF21A41B4EECDB3A7C803D75E // TNT: Evilution map32
-{
-	// door can close permanently; make switch that opens it repeatable
-	setlineflags 872 0x200
-	// switch should only open way to red key, don't lower bars yet,
-	// instead make line just before red key open bars
-	setsectortag 197 0
-	setsectortag 197 8
-	setlinespecial 1279 Floor_LowerToLowest 8 32 0 0 0
-	setactivation 1240 1 // SPAC_PCross
-	setlinespecial 1240 Floor_LowerToLowest 38 32 0 0 0
-}
-
-279BB50468FE9F5B36C6D821E4902369 // Plutonia Experiment map30
-{
-	// flag items in deathmatch-only area correctly so that 100% items
-	// are possible in solo
-	setthingflags 250 17
-	setthingflags 251 17
-	setthingflags 252 17
-	setthingflags 253 17
-	setthingflags 254 17
-	setthingflags 206 17
-}
-
-4CB7AAC5C43CF32BDF05FD36481C1D9F // Plutonia: Revisited map27
-{
-	setlinespecial 1214 Plat_DownWaitUpStayLip 20 64 150 0 0
-	setlinespecial 1215 Plat_DownWaitUpStayLip 20 64 150 0 0
-	setlinespecial 1216 Plat_DownWaitUpStayLip 20 64 150 0 0
-	setlinespecial 1217 Plat_DownWaitUpStayLip 20 64 150 0 0
-	setlinespecial 1227 Plat_DownWaitUpStayLip 20 64 150 0 0
-}
-
-5B26545FF21B051CA06D389CE535684C // doom.wad e1m4
-{
-	// missing textures	
-	setwalltexture 693 back top BROWN1
-	// fix HOM errors with sectors too low
-	setsectoroffset 9 floor 8
-	setsectoroffset 105 floor 8
-	setsectoroffset 132 floor 8
-	setsectoroffset 137 floor 8
-}
-A24FE135D5B6FD427FE27BEF89717A65 // doom.wad e2m2
-{
-	// missing textures
-	setwalltexture 947 back top BROWN1
-	setwalltexture 1596 back top WOOD1
-}
-1BC04D646B32D3A3E411DAF3C1A38FF8 // doom.wad e2m4
-{
-	// missing textures
-	setwalltexture 551 back top PIPE4
-	setwalltexture 865 back bot STEP5
-	setwalltexture 1062 front top GSTVINE1
-	setwalltexture 1071 front top MARBLE1	
-}
-99C580AD8FABE923CAB485CB7F3C5E5D // doom.wad e2m5
-{
-	// missing textures
-	setwalltexture 590 back top GRAYBIG
-	setwalltexture 590 front bot BROWN1
-}
-3838AB29292587A7EE3CA71E7040868D // doom.wad e2m6
-{
-	// missing texture
-	setwalltexture 1091 back top compspan
-}
-8590F489879870C098CD7029C3187159 // doom.wad e2m7
-{
-	// missing texture
-	setwalltexture 1286 front bot SHAWN2
-}
-8A6399FAAA2E68649D4E4B16642074BE // doom.wad e2m9
-{
-	// missing textures
-	setwalltexture 121 back top SW1LION
-	setwalltexture 123 back top GSTONE1
-	setwalltexture 140 back top GSTONE1
-}
-2B65CB046EA40D2E44576949381769CA // Commercial Doom e3m4
-{
-	// This line is erroneously specified as Door_Raise that monsters
-	// can operate. If they do, they block you off from half the map. Change
-	// this into a one-shot Door_Open so that it won't close.
-	setlinespecial 1069 Door_Open 0 16 0 0 0
-	clearlineflags 1069 0x200
-}
-5AC51CA9F1B57D4538049422A5E37291 // doom.wad e3m7
-{
-	// missing texture
-	setwalltexture 971 back top SP_HOT1
-}
-DA0C8281AC70EEC31127C228BCD7FE2C // doom.wad e4m1
-{
-	// missing texture
-	setwalltexture 470 front top GSTONE1
-}
-F6EE16F770AD309D608EA0B1F1E249FC // Ultimate Doom, e4m3
-{
-	// Remove unreachable secrets
-	setsectorspecial 124 0
-	setsectorspecial 125 0
-	// clear staircase to secret area
-	setsectorspecial 127 0
-	setsectorspecial 128 0
-	setsectorspecial 129 0
-	setsectorspecial 130 0
-	setsectorspecial 131 0
-	setsectorspecial 132 0
-	setsectorspecial 133 0
-	setsectorspecial 134 0
-	setsectorspecial 136 0
-	setsectorspecial 137 0
-	setsectorspecial 138 0
-	setsectorspecial 147 0
-	setsectorspecial 148 0
-	setsectorspecial 149 0
-	setsectorspecial 150 0
-	setsectorspecial 151 0
-	setsectorspecial 152 0
-	setsectorspecial 155 0
-}
-AAECADD4D97970AFF702D86FAFAC7D17 // doom.wad e4m4
-{
-	// missing textures
-	setwalltexture 427 back top BROWNHUG
-	setwalltexture 558 back top BROWNHUG
-	setwalltexture 567 front top BROWNHUG
-	setwalltexture 572 front top BROWNHUG
-}
-94D4C869A0C02EF4F7375022B36AAE45 // Ultimate Doom, e4m7
-{
-	// Remove unreachable secrets
-	setsectorspecial 263 0
-	setsectorspecial 264 0
-}
-
-CEC791136A83EEC4B91D39718BDF9D82 // doom2.wad map04
-{
-	// missing textures
-	setwalltexture 456 back top SUPPORT3
-	setwalltexture 108 front top STONE
-	setwalltexture 109 front top STONE
-	setwalltexture 110 front top STONE
-	setwalltexture 111 front top STONE
-	setwalltexture 127 front top STONE
-	setwalltexture 128 front top STONE
-	// remove erroneous blue keycard pickup ambush sector tags (nearby viewing windows, and the lights)
-	setsectortag 19 0
-	setsectortag 20 0
-	setsectortag 23 0
-	setsectortag 28 0
-	setsectortag 33 0
-	setsectortag 34 0
-	setsectortag 83 0
-	setsectortag 85 0
-}
-9E061AD7FBCD7FAD968C976CB4AA3B9D // doom2.wad map05
-{
-	// fix bug with opening westmost door in door hallway - incorrect sector tagging - see doomwiki.org for more info
-	setsectortag 4 0
-	setsectortag 153 0
-}
-5BDA34DA60C0530794CC1EA2DA017976 // doom2.wad map14
-{
-	// missing textures
-	setwalltexture 1259 back top BSTONE2
-	setwalltexture 1305 back top BSTONE2
-}
-1A540BA717BF9EC85F8522594C352F2A // Doom II, map15
-{
-	setsectorspecial 147 0
-}
-0D491365C1B88B7D1B603890100DD03E // doom2.wad map18
-{
-	// missing textures
-	setwalltexture 451 front mid metal
-	setwalltexture 459 front mid metal
-}
-B5506B1E8F2FC272AD0C77B9E0DF5491 // doom2.wad map19
-{
-	// missing textures
-	setwalltexture 355 back top STONE2
-	setwalltexture 736 front top SLADWALL
-}
-EBDAC00E9D25D884B2C8F4B1F0390539 // doom2.wad map21
-{
-	// push ceiling down in glitchy sectors above the stair switches
-	setsectoroffset 50 ceil -56
-	setsectoroffset 54 ceil -56
-}
-110F84DE041052B59307FAF0293E6BC0 // Doom II, map27
-{
-	setsectorspecial 93 0
-	setwalltexture 582 back top ZIMMER3
-}
-20251EDA21B2F2ECF6FF5B8BBC00B26C // Doom II, MAP29
-{
-	// Missing textures on teleporters
-	setwalltexture 405 back bot SUPPORT3
-	setwalltexture 406 back bot SUPPORT3
-	setwalltexture 407 back bot SUPPORT3
-	setwalltexture 408 back bot SUPPORT3
-	setwalltexture 516 back bot SUPPORT3
-	setwalltexture 517 back bot SUPPORT3
-	setwalltexture 518 back bot SUPPORT3
-	setwalltexture 519 back bot SUPPORT3
-	setwalltexture 524 back bot SUPPORT3
-	setwalltexture 525 back bot SUPPORT3
-	setwalltexture 526 back bot SUPPORT3
-	setwalltexture 527 back bot SUPPORT3
-	setwalltexture 1146 back bot SUPPORT3
-	setwalltexture 1147 back bot SUPPORT3
-	setwalltexture 1148 back bot SUPPORT3
-	setwalltexture 1149 back bot SUPPORT3
-	setwalltexture 1138 back bot SUPPORT3
-	setwalltexture 1139 back bot SUPPORT3
-	setwalltexture 1140 back bot SUPPORT3
-	setwalltexture 1141 back bot SUPPORT3
-}
-ABC4EB5A1535ECCD0061AD14F3547908 // Plutonia Experiment, map26
-{
-	setsectorspecial 156 0
-}
-
-FF635FB9A2F076566299910F8C78F707 // nerve.wad, level04
-{
-	setsectorspecial 868 0
-}
 
 B68EB7CFB4CC481796E2919B9C16DFBD // Moc11.wad e1m6
 {
diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
index 695a43b01..134255c3b 100644
--- a/wadsrc/static/zscript/level_compatibility.txt
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -23,9 +23,399 @@ class LevelCompatibility play
 				SetWallTexture(101, Line.back, Side.top, "BRICK7");
 				break;
 			}
+			
+			case 'E2B5D1400279335811C1C1C0B437D9C8': // Deathknights of the Dark Citadel, map54
+			{
+				// This map has two gear boxes which are flagged for player cross
+				// activation instead of the proper player uses activation.
+				SetLineActivation(943, SPAC_Use);
+				SetLineActivation(963, SPAC_Use);
+				break;
+			}
+			
+			case '3F249EDD62A3A08F53A6C53CB4C7ABE5': // Artica 3 map01
+			{
+				ClearLineSpecial(66);
+				break;
+			}
+			
+			case 'F481922F4881F74760F3C0437FD5EDD0': // // Community Chest 3 map03
+			{
+				// I have no idea how this conveyor belt setup manages to work under Boom.
+				// Set the sector the voodoo doll ends up standing on when sectors tagged
+				// 1 are raised so that the voodoo doll will be carried.
+				SetLineSpecial(3559, Sector_CopyScroller, 17, 6);
+				break;
+			}
+
+			case '5B862477519B21B30059A466F2FF6460': // Khorus, map08
+			{
+				// This map uses a voodoo conveyor with slanted walls to shunt the
+				// voodoo doll into side areas. For some reason, this voodoo doll
+				// is unable to slide on them, because the slide calculation gets
+				// them slightly inside the walls and thinks they are stuck. I could
+				// not reproduce this with the real player, which is what has me
+				// stumped. So, help them out be attaching some ThrustThing specials
+				// to the walls.
+				SetLineSpecial(443, ThrustThing, 96, 4);
+				SetLineFlags(443, Line.ML_REPEAT_SPECIAL);
+				SetLineActivation(443, SPAC_Push);
+				SetLineSpecial(455, ThrustThing, 96, 4);
+				SetLineFlags(455, Line.ML_REPEAT_SPECIAL);
+				SetLineActivation(455, SPAC_Push);
+				break;
+			}
+
+			case '3D1E36E50F5A8D289E15433941605224': // Master Levels, catwalk.wad
+			{
+				// make it impossible to open door to 1-way bridge before getting red key
+				ClearSectorTags(35);
+				AddSectorTag(35, 15);
+				for(int i=605; i<609;i++)
+				{
+					SetLineActivation(i, SPAC_PCross);
+					SetLineSpecial(i, Door_Open, 15, 64);
+				}
+				break;
+			}
+			
+			case '3B9CAA02952F405269353FAAD8F8EC33': // Master Levels, nessus.wad
+			{
+				// move secret sector from too-thin doorframe to BFG closet
+				SetSectorSpecial(211, 0);
+				SetSectorSpecial(212, 1024);
+				// lower floor a bit so secret sector can be entered fully
+				OffsetSectorPlane(212, Sector.floor, -16);
+				// make secret door stay open so you can't get locked in closet
+				SetLineSpecial(1008, Door_Open, 0, 64);
+				break;
+			}
+
+			case '7ED9800213C00D6E7FB98652AB48B3DE': // Ultimate Simplicity, map04
+			{
+				// Add missing map spots on easy and medium skills
+				// Demons will teleport into starting room making 100% kills possible
+				SetThingSkills(31, 31);
+				SetThingSkills(32, 31);
+				break;
+			}
+  
+			case '1891E029994B023910CFE0B3209C3CDB': // Ultimate Simplicity, map07
+			{
+				// It is possible to get stuck on skill 0 or 1 when no shots have been fired
+				// after sector 17 became accessible and before entering famous mancubus room.
+				// Monsters from the mentioned sector won't be alerted and so 
+				// they won't teleport into the battle. ACS will wait forever for their deaths.
+				SetLineSpecial(397, NoiseAlert);
+				SetLineSpecial(411, NoiseAlert);
+				break;
+			}
+
+			case 'F0E6F30F57B0425F17E43600AA813E80': // Ultimate Simplicity, map11
+			{
+				// If door (sector #309) is closed it cannot be open again
+				// from one side potentially blocking level progression
+				ClearLineSpecial(2445);
+				break;
+			}
+
+			case '952CC8D03572E17BA550B01B366EFBB9': // Cheogsh map01
+			{
+				// make the blue key spawn above the 3D floor
+				SetThingZ(918, 296);
+				break;
+			}
+
+			case 'D62DCA9EC226DE49108D5DD9271F7631': // Cheogsh 2 map04
+			{
+				// Stuff in megasphere cage is positioned too low
+				for(int i=1640; i<=1649; i++)
+				{
+					SetThingZ(i, 528);
+				}
+				break;
+			}
+
+			case 'DFC18B92BF3E8142B8684ECD8BD2EF06': // TNT: Evilution map15
+			{
+				// raise up sector with its counterpart so 100% kills becomes possible
+				AddSectorTag(330, 11);
+				break;
+			}
+
+			case '2C4A3356C5EB3526D2C72A4AA4B18A36': // TNT: Evilution map29
+			{
+				// remove mancubus who always gets stuck in teleport tunnel, preventing
+				// 100% kills on HMP
+				SetThingFlags(405, 0);
+				break;
+			}
+
+			case 'A53AE580A4AF2B5D0B0893F86914781E': // TNT: Evilution map31
+			{
+				// The famous missing yellow key...
+				SetThingFlags(470, 2016);
+				break;
+			}
+
+			case 'D99AD22FF21A41B4EECDB3A7C803D75E': // TNT: Evilution map32
+			{
+				// door can close permanently; make switch that opens it repeatable
+				SetLineFlags(872, Line.ML_REPEAT_SPECIAL);
+				// switch should only open way to red key, don't lower bars yet,
+				// instead make line just before red key open bars
+				ClearSectorTags(197);
+				AddSectorTag(197, 8);
+				SetLineSpecial(1279, Floor_LowerToLowest, 8, 32);
+				SetLineActivation(1240, SPAC_PCross);
+				SetLineSpecial(1240, Floor_LowerToLowest, 38, 32);
+				break;
+			}
+
+			case '279BB50468FE9F5B36C6D821E4902369': // Plutonia Experiment map30
+			{
+				// flag items in deathmatch-only area correctly so that 100% items
+				// are possible in solo
+				SetThingFlags(250, 17);
+				SetThingFlags(251, 17);
+				SetThingFlags(252, 17);
+				SetThingFlags(253, 17);
+				SetThingFlags(254, 17);
+				SetThingFlags(206, 17);
+				break;
+			}
+
+			case '4CB7AAC5C43CF32BDF05FD36481C1D9F': // Plutonia: Revisited map27
+			{
+				SetLineSpecial(1214, Plat_DownWaitUpStayLip, 20, 64, 150);
+				SetLineSpecial(1215, Plat_DownWaitUpStayLip, 20, 64, 150);
+				SetLineSpecial(1216, Plat_DownWaitUpStayLip, 20, 64, 150);
+				SetLineSpecial(1217, Plat_DownWaitUpStayLip, 20, 64, 150);
+				SetLineSpecial(1227, Plat_DownWaitUpStayLip, 20, 64, 150);
+				break;
+			}
+
+			case '5B26545FF21B051CA06D389CE535684C': // doom.wad e1m4
+			{
+				// missing textures	
+				SetWallTexture(693, Line.back, Side.top, "BROWN1");
+				// fix HOM errors with sectors too low
+				OffsetSectorPlane(9,  Sector.floor, 8);
+				OffsetSectorPlane(105, Sector.floor, 8);
+				OffsetSectorPlane(132, Sector.floor, 8);
+				OffsetSectorPlane(137, Sector.floor, 8);
+				break;
+			}
+			case 'A24FE135D5B6FD427FE27BEF89717A65': // doom.wad e2m2
+			{
+				// missing textures
+				SetWallTexture(947, Line.back, Side.top, "BROWN1");
+				SetWallTexture(1596, Line.back, Side.top, "WOOD1");
+				break;
+			}
+			case '1BC04D646B32D3A3E411DAF3C1A38FF8': // doom.wad e2m4
+			{
+				// missing textures
+				SetWallTexture(551, Line.back, Side.top, "PIPE4");
+				SetWallTexture(865, Line.back, Side.bottom, "STEP5");
+				SetWallTexture(1062, Line.front, Side.top, "GSTVINE1");
+				SetWallTexture(1071, Line.front, Side.top, "MARBLE1");
+				break;
+			}
+			case '99C580AD8FABE923CAB485CB7F3C5E5D': // doom.wad e2m5
+			{
+				// missing textures
+				SetWallTexture(590, Line.back, Side.top, "GRAYBIG");
+				SetWallTexture(590, Line.front, Side.bottom, "BROWN1");
+				break;
+			}
+			case '3838AB29292587A7EE3CA71E7040868D': // doom.wad e2m6
+			{
+				// missing texture
+				SetWallTexture(1091, Line.back, Side.top, "compspan");
+				break;
+			}
+			case '8590F489879870C098CD7029C3187159': // doom.wad e2m7
+			{
+				// missing texture
+				SetWallTexture(1286, Line.front, Side.bottom, "SHAWN2");
+				break;
+			}
+			case '8A6399FAAA2E68649D4E4B16642074BE': // doom.wad e2m9
+			{
+				// missing textures
+				SetWallTexture(121, Line.back, Side.top, "SW1LION");
+				SetWallTexture(123, Line.back, Side.top, "GSTONE1");
+				SetWallTexture(140, Line.back, Side.top, "GSTONE1");
+				break;
+			}
+			case '2B65CB046EA40D2E44576949381769CA': // Commercial Doom e3m4
+			{
+				// This line is erroneously specified as Door_Raise that monsters
+				// can operate. If they do, they block you off from half the map. Change
+				// this into a one-shot Door_Open so that it won't close.
+				SetLineSpecial(1069, Door_Open, 0, 16);
+				SetLineFlags(1069, 0, Line.ML_REPEAT_SPECIAL);
+				break;
+			}
+			case '5AC51CA9F1B57D4538049422A5E37291': // doom.wad e3m7
+			{
+				// missing texture
+				SetWallTexture(971, Line.back, Side.top, "SP_HOT1");
+				break;
+			}
+			case 'DA0C8281AC70EEC31127C228BCD7FE2C': // doom.wad e4m1
+			{
+				// missing texture
+				SetWallTexture(470, Line.front, Side.top, "GSTONE1");
+				break;
+			}
+			case 'F6EE16F770AD309D608EA0B1F1E249FC': // Ultimate Doom, e4m3
+			{
+				// Remove unreachable secrets
+				SetSectorSpecial(124, 0);
+				SetSectorSpecial(125, 0);
+				// clear staircase to secret area
+				SetSectorSpecial(127, 0);
+				SetSectorSpecial(128, 0);
+				SetSectorSpecial(129, 0);
+				SetSectorSpecial(130, 0);
+				SetSectorSpecial(131, 0);
+				SetSectorSpecial(132, 0);
+				SetSectorSpecial(133, 0);
+				SetSectorSpecial(134, 0);
+				SetSectorSpecial(136, 0);
+				SetSectorSpecial(137, 0);
+				SetSectorSpecial(138, 0);
+				SetSectorSpecial(147, 0);
+				SetSectorSpecial(148, 0);
+				SetSectorSpecial(149, 0);
+				SetSectorSpecial(150, 0);
+				SetSectorSpecial(151, 0);
+				SetSectorSpecial(152, 0);
+				SetSectorSpecial(155, 0);
+				break;
+			}
+			case 'AAECADD4D97970AFF702D86FAFAC7D17': // doom.wad e4m4
+			{
+				// missing textures
+				TextureID brownhug = TexMan.CheckForTexture("BROWNHUG", TexMan.Type_Wall);
+				SetWallTextureID(427, Line.back, Side.top, BROWNHUG);
+				SetWallTextureID(558, Line.back, Side.top, BROWNHUG);
+				SetWallTextureID(567, Line.front, Side.top, BROWNHUG);
+				SetWallTextureID(572, Line.front, Side.top, BROWNHUG);
+				break;
+			}
+			case '94D4C869A0C02EF4F7375022B36AAE45': // Ultimate Doom, e4m7
+			{
+				// Remove unreachable secrets
+				SetSectorSpecial(263, 0);
+				SetSectorSpecial(264, 0);
+				break;
+			}
+
+			case 'CEC791136A83EEC4B91D39718BDF9D82': // doom2.wad map04
+			{
+				// missing textures
+				SetWallTexture(456, Line.back, Side.top, "SUPPORT3");
+				TextureID stone = TexMan.CheckForTexture("STONE", TexMan.Type_Wall);
+				SetWallTextureID(108, Line.front, Side.top, STONE);
+				SetWallTextureID(109, Line.front, Side.top, STONE);
+				SetWallTextureID(110, Line.front, Side.top, STONE);
+				SetWallTextureID(111, Line.front, Side.top, STONE);
+				SetWallTextureID(127, Line.front, Side.top, STONE);
+				SetWallTextureID(128, Line.front, Side.top, STONE);
+				// remove erroneous blue keycard pickup ambush sector tags (nearby viewing windows, and the lights)
+				ClearSectorTags(19);
+				ClearSectorTags(20);
+				ClearSectorTags(23);
+				ClearSectorTags(28);
+				ClearSectorTags(33);
+				ClearSectorTags(34);
+				ClearSectorTags(83);
+				ClearSectorTags(85);
+				break;
+			}
+			case '9E061AD7FBCD7FAD968C976CB4AA3B9D': // doom2.wad map05
+			{
+				// fix bug with opening westmost door in door hallway - incorrect sector tagging - see doomwiki.org for more info
+				ClearSectorTags(4);
+				ClearSectorTags(153);
+				break;
+			}
+			case '5BDA34DA60C0530794CC1EA2DA017976': // doom2.wad map14
+			{
+				// missing textures
+				SetWallTexture(1259, Line.back, Side.top, "BSTONE2");
+				SetWallTexture(1305, Line.back, Side.top, "BSTONE2");
+			}
+			case '1A540BA717BF9EC85F8522594C352F2A': // Doom II, map15
+			{
+				SetSectorSpecial(147, 0);
+				break;
+			}
+			case '0D491365C1B88B7D1B603890100DD03E': // doom2.wad map18
+			{
+				// missing textures
+				SetWallTexture(451, Line.front, Side.mid, "metal");
+				SetWallTexture(459, Line.front, Side.mid, "metal");
+				break;
+			}
+			case 'B5506B1E8F2FC272AD0C77B9E0DF5491': // doom2.wad map19
+			{
+				// missing textures
+				SetWallTexture(355, Line.back, Side.top, "STONE2");
+				SetWallTexture(736, Line.front, Side.top, "SLADWALL");
+				break;
+			}
+			case 'EBDAC00E9D25D884B2C8F4B1F0390539': // doom2.wad map21
+			{
+				// push ceiling down in glitchy sectors above the stair switches
+				OffsetSectorPlane(50, Sector.ceiling, -56);
+				OffsetSectorPlane(54, Sector.ceiling, -56);
+				break;
+			}
+			case '110F84DE041052B59307FAF0293E6BC0': // Doom II, map27
+			{
+				SetSectorSpecial(93, 0);
+				SetWallTexture(582, Line.back, Side.top, "ZIMMER3");
+				break;
+			}
+			case '20251EDA21B2F2ECF6FF5B8BBC00B26C': // Doom II, MAP29
+			{
+				// Missing textures on teleporters
+				TextureID support3 = TexMan.CheckForTexture("SUPPORT3", TexMan.Type_Wall);
+				for(int i=0;i<4;i++)
+				{
+					SetWallTextureID(405+i, Line.back, Side.bottom, SUPPORT3);
+					SetWallTextureID(516+i, Line.back, Side.bottom, SUPPORT3);
+					SetWallTextureID(524+1, Line.back, Side.bottom, SUPPORT3);
+					SetWallTextureID(1146+i, Line.back, Side.bottom, SUPPORT3);
+					SetWallTextureID(1138+i, Line.back, Side.bottom, SUPPORT3);
+				}
+				break;
+			}
+			case 'ABC4EB5A1535ECCD0061AD14F3547908': // Plutonia Experiment, map26
+			{
+				SetSectorSpecial(156, 0);
+				break;
+			}
+
+			case 'FF635FB9A2F076566299910F8C78F707': // nerve.wad, level04
+			{
+				SetSectorSpecial(868, 0);
+				break;
+			}
 		}
 	}
 
+	private static native void ClearSectorTags(int sector);
+	private static native void AddSectorTag(int sector, int tag);
+	private static native void OffsetSectorPlane(int sector, int plane, double offset);
+	private static native void SetThingSkills(int thing, int skills);
+	private static native void SetThingZ(int thing, double z);
+	private static native void SetThingFlags(int thing, int flags);
+	
 	private static void SetWallTexture(int line, int side, int texpart, String texture)
 	{
 		SetWallTextureID(line, side, texpart, TexMan.CheckForTexture(texture, TexMan.Type_Wall));
@@ -36,6 +426,31 @@ class LevelCompatibility play
 		level.Lines[line].sidedef[side].SetTexture(texpart, texture);
 	}
 	
+	private static void SetLineFlags(int line, int setflags, int clearflags = 0)
+	{
+		level.Lines[line].flags = (level.Lines[line].flags & ~clearflags) | setflags;
+	}
+	
+	private static void SetLineActivation(int line, int acttype)
+	{
+		level.Lines[line].activation = acttype;
+	}
+	
+	private static void ClearLineSpecial(int line)
+	{
+		level.Lines[line].special = 0;
+	}
+	
+	private static void SetLineSpecial(int line, int special, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0, int arg5 = 0)
+	{
+		level.Lines[line].special = special;
+		level.Lines[line].args[0] = arg1;
+		level.Lines[line].args[1] = arg2;
+		level.Lines[line].args[2] = arg3;
+		level.Lines[line].args[3] = arg4;
+		level.Lines[line].args[4] = arg5;
+	}
+	
 	private static void SetSectorSpecial(int sectornum, int special)
 	{
 		level.sectors[sectornum].special = special;

From 05dcd308387159c73a2c770ffd670ae7b114cd8d Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Wed, 11 Apr 2018 11:52:07 +0300
Subject: [PATCH 05/13] Made 100% secrets possible on The Realm of Parthoris
 E1M5

https://forum.zdoom.org/viewtopic.php?t=60181#p1049393
---
 wadsrc/static/zscript/level_compatibility.txt | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
index 134255c3b..cb32088da 100644
--- a/wadsrc/static/zscript/level_compatibility.txt
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -406,6 +406,13 @@ class LevelCompatibility play
 				SetSectorSpecial(868, 0);
 				break;
 			}
+
+			case 'DB31D71B11E3E4393B9C0CCB44A8639F': // rop_2015.wad e1m5
+			{
+				// Lower floor a bit so secret switch becomes accessible
+				OffsetSectorPlane(527, Sector.floor, -32);
+				break;
+			}
 		}
 	}
 

From 69222c3c36a0c80d3a253cff77f46834e3e681b1 Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Wed, 11 Apr 2018 11:54:27 +0300
Subject: [PATCH 06/13] Fixed missing texture with hardware renderer on Jenesis
 MAP16

https://forum.drdteam.org/viewtopic.php?t=7337
---
 wadsrc/static/zscript/level_compatibility.txt | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
index cb32088da..9a1387620 100644
--- a/wadsrc/static/zscript/level_compatibility.txt
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -413,6 +413,13 @@ class LevelCompatibility play
 				OffsetSectorPlane(527, Sector.floor, -32);
 				break;
 			}
+
+			case 'CC3911090452D7C39EC8B3D97CEFDD6F': // jenesis.wad map16
+			{
+				// Missing texture with hardware renderer because of wrongly lowered sector
+				ClearSectorTags(483);
+				break;
+			}
 		}
 	}
 

From 950443683b60bfabc1f5359472c05a7e8290f299 Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Wed, 11 Apr 2018 12:35:45 +0300
Subject: [PATCH 07/13] Scriptified compatibility of more Heretic levels

---
 src/compatibility.cpp                         | 13 ++++
 wadsrc/static/compatibility.txt               | 65 ----------------
 wadsrc/static/zscript/level_compatibility.txt | 77 +++++++++++++++++++
 3 files changed, 90 insertions(+), 65 deletions(-)

diff --git a/src/compatibility.cpp b/src/compatibility.cpp
index beb07dc9c..d77f2dafa 100644
--- a/src/compatibility.cpp
+++ b/src/compatibility.cpp
@@ -842,6 +842,19 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingFlags)
 	return 0;
 }
 
+DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetVertex)
+{
+	PARAM_PROLOGUE;
+	PARAM_UINT(vertex);
+	PARAM_FLOAT(x);
+	PARAM_FLOAT(y);
+
+	if (vertex < level.vertexes.Size())
+	{
+		level.vertexes[vertex].p = DVector2(x, y);
+	}
+	return 0;
+}
 
 
 //==========================================================================
diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt
index 7ca81e403..d217b92ee 100644
--- a/wadsrc/static/compatibility.txt
+++ b/wadsrc/static/compatibility.txt
@@ -249,12 +249,6 @@ DC96228097DD004C40CCB1DB14A91EAA // unloved.pk3:unlovedmaps.wad map05
 
 
 
-B68EB7CFB4CC481796E2919B9C16DFBD // Moc11.wad e1m6
-{
-	setvertex 1650 -3072 2671
-	setvertex 1642 -2944 2671
-}
-
 712BB4CFBD0753178CA0C6814BE4C288 // map12 BTSX_E1 - patch some rendering glitches that are problematic to detect
 {
 	setsectortag 545 32000
@@ -270,65 +264,6 @@ B68EB7CFB4CC481796E2919B9C16DFBD // Moc11.wad e1m6
 
 
 
-// Cosmetic fixes for Heretic: Shadow of the Serpent Riders
-D94587625BA779644D58151A87897CF1 // e1m2
-{
-	// Missing textures
-	setwalltexture 477 back top MOSSRCK1
-	setwalltexture 478 back top MOSSRCK1
-	setwalltexture 479 back top MOSSRCK1
-	setwalltexture 1057 front top MOSSRCK1
-}
-ADD0FAC41AFB0B3C9B9F3C0006F93805 // e1m3
-{
-	// Broken door between the hallway that leads to a Torch 
-	// and the passage that has a Bag of Holding at its end
-	setsectoroffset 86 floor -128
-	setsectoroffset 86 ceil -128
-}
-916318D8B06DAC2D83424B23E4B66531 // e1m4
-{
-	// Wrong sector offsets
-	setsectoroffset 0 ceil 8
-	setsectoroffset 1 ceil 8
-	setsectoroffset 2 ceil 8
-	setsectoroffset 3 ceil 8
-	setsectoroffset 4 ceil 8
-	setsectoroffset 6 ceil 8
-	setsectoroffset 6 floor 8
-	setsectoroffset 17 ceil 8
-	// Yellow key door
-	setsectoroffset 284 floor -8
-	setsectoroffset 284 ceil -8
-	// Missing textures
-	setwalltexture 490 back bot GRSTNPB
-	setwalltexture 722 front bot WOODWL
-	setwalltexture 911 front bot WOODWL
-	setwalltexture 1296 front bot WOODWL
-}
-397A0E17A39542E4E8294E156FAB0502 // e2m2
-{
-	// Missing green door statues on easy and hard difficulties
-	setthingskills 17 31
-	setthingskills 18 31
-}
-CA3773ED313E8899311F3DD0CA195A68 // e3m6
-{
-	// Quartz flask outside of map
-	setthingskills 373 0
-	// Missing wall torch on hard difficulty
-	setthingskills 448 31
-	// Missing textures
-	setwalltexture 343 front top MOSSRCK1
-	setwalltexture 370 front top MOSSRCK1
-}
-5E3FCFDE78310BB89F92B1626A47D0AD // heretic.wad E4M7
-{
-	// Missing textures
-	setwalltexture 1274 front top CSTLRCK
-	setwalltexture 1277 back top CSTLRCK
-	setwalltexture 1278 front top CSTLRCK
-}
 
 39C594CAC07EE51C80F757DA465FCC94 // strife1.wad map10
 {
diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
index 9a1387620..9f63b8811 100644
--- a/wadsrc/static/zscript/level_compatibility.txt
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -407,6 +407,75 @@ class LevelCompatibility play
 				break;
 			}
 
+			case 'D94587625BA779644D58151A87897CF1': // heretic.wad e1m2
+			{
+				// Missing textures
+				TextureID mossrck1 = TexMan.CheckForTexture("MOSSRCK1", TexMan.Type_Wall);
+				SetWallTextureID( 477, Line.back,  Side.top, mossrck1);
+				SetWallTextureID( 478, Line.back,  Side.top, mossrck1);
+				SetWallTextureID( 479, Line.back,  Side.top, mossrck1);
+				SetWallTextureID(1057, Line.front, Side.top, mossrck1);
+				break;
+			}
+			case 'ADD0FAC41AFB0B3C9B9F3C0006F93805': // heretic.wad e1m3
+			{
+				// Broken door between the hallway that leads to a Torch 
+				// and the passage that has a Bag of Holding at its end
+				OffsetSectorPlane(86, Sector.floor,   -128);
+				OffsetSectorPlane(86, Sector.ceiling, -128);
+				break;
+			}
+			case '916318D8B06DAC2D83424B23E4B66531': // heretic.wad e1m4
+			{
+				// Wrong sector offsets
+				OffsetSectorPlane( 0, Sector.ceiling, 8);
+				OffsetSectorPlane( 1, Sector.ceiling, 8);
+				OffsetSectorPlane( 2, Sector.ceiling, 8);
+				OffsetSectorPlane( 3, Sector.ceiling, 8);
+				OffsetSectorPlane( 4, Sector.ceiling, 8);
+				OffsetSectorPlane( 6, Sector.ceiling, 8);
+				OffsetSectorPlane( 6, Sector.floor,   8);
+				OffsetSectorPlane(17, Sector.ceiling, 8);
+				// Yellow key door
+				OffsetSectorPlane(284, Sector.floor,   -8);
+				OffsetSectorPlane(284, Sector.ceiling, -8);
+				// Missing textures
+				SetWallTexture(490, Line.back,  Side.bottom, "GRSTNPB");
+				TextureID woodwl = TexMan.CheckForTexture("WOODWL", TexMan.Type_Wall);
+				SetWallTextureID( 722, Line.front, Side.bottom, woodwl);
+				SetWallTextureID( 911, Line.front, Side.bottom, woodwl);
+				SetWallTextureID(1296, Line.front, Side.bottom, woodwl);
+				break;
+			}
+			case '397A0E17A39542E4E8294E156FAB0502': // heretic.wad e2m2
+			{
+				// Missing green door statues on easy and hard difficulties
+				SetThingSkills(17, 31);
+				SetThingSkills(18, 31);
+				break;
+			}
+			case 'CA3773ED313E8899311F3DD0CA195A68': // heretic.wad e3m6
+			{
+				// Quartz flask outside of map
+				SetThingSkills(373, 0);
+				// Missing wall torch on hard difficulty
+				SetThingSkills(448, 31);
+				// Missing textures
+				TextureID mossrck1 = TexMan.CheckForTexture("MOSSRCK1", TexMan.Type_Wall);
+				SetWallTextureID(343, Line.front, Side.top, mossrck1);
+				SetWallTextureID(370, Line.front, Side.top, mossrck1);
+				break;
+			}
+			case '5E3FCFDE78310BB89F92B1626A47D0AD': // heretic.wad E4M7
+			{
+				// Missing textures
+				TextureID cstlrck = TexMan.CheckForTexture("CSTLRCK", TexMan.Type_Wall);
+				SetWallTextureID(1274, Line.front, Side.top, cstlrck);
+				SetWallTextureID(1277, Line.back,  Side.top, cstlrck);
+				SetWallTextureID(1278, Line.front, Side.top, cstlrck);
+				break;
+			}
+
 			case 'DB31D71B11E3E4393B9C0CCB44A8639F': // rop_2015.wad e1m5
 			{
 				// Lower floor a bit so secret switch becomes accessible
@@ -420,6 +489,13 @@ class LevelCompatibility play
 				ClearSectorTags(483);
 				break;
 			}
+
+			case 'B68EB7CFB4CC481796E2919B9C16DFBD':  // Moc11.wad e1m6
+			{
+				SetVertex(1650, -3072, 2671);
+				SetVertex(1642, -2944, 2671);
+				break;
+			}
 		}
 	}
 
@@ -429,6 +505,7 @@ class LevelCompatibility play
 	private static native void SetThingSkills(int thing, int skills);
 	private static native void SetThingZ(int thing, double z);
 	private static native void SetThingFlags(int thing, int flags);
+	private static native void SetVertex(uint vertex, double x, double y);
 	
 	private static void SetWallTexture(int line, int side, int texpart, String texture)
 	{

From 5f5adbe1617b8fa2076d42c5e8017cb538243fdf Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Wed, 11 Apr 2018 13:02:26 +0300
Subject: [PATCH 08/13] Scriptified compatibility of Strife level along with
 needed functions

---
 wadsrc/static/compatibility.txt               | 10 --------
 wadsrc/static/zscript/level_compatibility.txt | 25 +++++++++++++++++++
 2 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt
index d217b92ee..16be5d613 100644
--- a/wadsrc/static/compatibility.txt
+++ b/wadsrc/static/compatibility.txt
@@ -265,16 +265,6 @@ DC96228097DD004C40CCB1DB14A91EAA // unloved.pk3:unlovedmaps.wad map05
 
 
 
-39C594CAC07EE51C80F757DA465FCC94 // strife1.wad map10
-{
-	// fix the shooting range by matching sector 138 and 145 properties together
-	setsectoroffset 145 floor -32
-	setsectoroffset 145 ceil 40
-	setsectortexture 145 floor F_CONCRP
-	setsectorlight 138 192
-	setwalltexture 3431 back top BRKGRY01
-}
-
 3D8ED20BF5CAAE6D6AE0E10999C75084 // hgarden.pk3 map01
 {
 	// spawn trees on top of arches
diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
index 9f63b8811..d16a0a133 100644
--- a/wadsrc/static/zscript/level_compatibility.txt
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -476,6 +476,16 @@ class LevelCompatibility play
 				break;
 			}
 
+			case '39C594CAC07EE51C80F757DA465FCC94': // strife1.wad map10
+			{
+				// fix the shooting range by matching sector 138 and 145 properties together
+				OffsetSectorPlane(145, Sector.floor,  -32);
+				OffsetSectorPlane(145, Sector.ceiling, 40);
+				SetSectorTexture(145, Sector.floor, "F_CONCRP");
+				SetSectorLight(138, 192);
+				SetWallTexture(3431, Line.back, Side.top, "BRKGRY01");
+			}
+
 			case 'DB31D71B11E3E4393B9C0CCB44A8639F': // rop_2015.wad e1m5
 			{
 				// Lower floor a bit so secret switch becomes accessible
@@ -546,4 +556,19 @@ class LevelCompatibility play
 	{
 		level.sectors[sectornum].special = special;
 	}
+
+	private static void SetSectorTextureID(int sectornum, int plane, TextureID texture)
+	{
+		level.sectors[sectornum].SetTexture(plane, texture);
+	}
+
+	private static void SetSectorTexture(int sectornum, int plane, String texture)
+	{
+		SetSectorTextureID(sectornum, plane, TexMan.CheckForTexture(texture, TexMan.Type_Flat));
+	}
+
+	private static void SetSectorLight(int sectornum, int newval)
+	{
+		level.sectors[sectornum].SetLightLevel(newval);
+	}
 }

From 6480946d4080d34cc50a86bd024a805031ac8440 Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Wed, 11 Apr 2018 15:57:27 +0300
Subject: [PATCH 09/13] Scriptified more compatibility entries

---
 wadsrc/static/compatibility.txt               | 33 +---------------
 wadsrc/static/zscript/level_compatibility.txt | 39 ++++++++++++++++++-
 2 files changed, 39 insertions(+), 33 deletions(-)

diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt
index 16be5d613..b923d263f 100644
--- a/wadsrc/static/compatibility.txt
+++ b/wadsrc/static/compatibility.txt
@@ -194,7 +194,7 @@ B9DFF13207EACAC675C71D82624D0007 // XtheaterIII map01
 
 D0139194F7817BF06F3988DFC47DB38D // Whispers of Satan map29
 {
-	
+	nopassover
 }
 
 5397C3B7D9B33AAF526D15A81A762828 // daedalus.wad Travel tubes (they are all identical)
@@ -224,7 +224,6 @@ C98F79709BD7E0E4C19026AB9575EC6F // cc-cod.zip:codlev.wad map07
 	polyobj
 }
 
-
 D7F6E9F08C39A17026349A04F8C0B0BE // Return to Hadron, e1m9
 19D03FFC875589E21EDBB7AB74EF4AEF // Return to Hadron, e1m9, 2016.01.03 update
 {
@@ -265,16 +264,6 @@ DC96228097DD004C40CCB1DB14A91EAA // unloved.pk3:unlovedmaps.wad map05
 
 
 
-3D8ED20BF5CAAE6D6AE0E10999C75084 // hgarden.pk3 map01
-{
-	// spawn trees on top of arches
-	setthingz 399 168
-	setthingz 400 168
-	setthingz 401 168
-	setthingz 402 168
-	setthingz 403 168
-	setthingz 404 168
-}
 
 FCCA97FC851F6473EAA069F74247B317 // pg-raw.wad map31
 {
@@ -321,23 +310,3 @@ FCCA97FC851F6473EAA069F74247B317 // pg-raw.wad map31
 	setslopeoverflow
 	polyobj
 }
-
-5C594C67CF7721005DE71429F9811370 // Eternal Doom map03
-{
-	// fix broken staircase. The compatibility option is not sufficient
-	// to reliably handle this so clear the tags from the unwanted sectors.
-	setsectortag 212 0
-	setsectortag 213 0
-	setsectortag 214 0
-}
-
-9D50EBE17CEC78938C7A668DB0768611 // Strain map07: Make the exit accessible
-{
-	clearlineflags 1021 1
-}
-
-DCE862393CAAA6FF1294FB7056B53057 // UAC Ultra map07: Contains a scroller depending on Boom side effects
-{
-	setlinespecial 391 Sector_CopyScroller 99 6 0 0 0
-}
-
diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
index d16a0a133..df01ebc96 100644
--- a/wadsrc/static/zscript/level_compatibility.txt
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -39,7 +39,7 @@ class LevelCompatibility play
 				break;
 			}
 			
-			case 'F481922F4881F74760F3C0437FD5EDD0': // // Community Chest 3 map03
+			case 'F481922F4881F74760F3C0437FD5EDD0': // Community Chest 3 map03
 			{
 				// I have no idea how this conveyor belt setup manages to work under Boom.
 				// Set the sector the voodoo doll ends up standing on when sectors tagged
@@ -484,6 +484,7 @@ class LevelCompatibility play
 				SetSectorTexture(145, Sector.floor, "F_CONCRP");
 				SetSectorLight(138, 192);
 				SetWallTexture(3431, Line.back, Side.top, "BRKGRY01");
+				break;
 			}
 
 			case 'DB31D71B11E3E4393B9C0CCB44A8639F': // rop_2015.wad e1m5
@@ -506,6 +507,42 @@ class LevelCompatibility play
 				SetVertex(1642, -2944, 2671);
 				break;
 			}
+
+			case '5C594C67CF7721005DE71429F9811370': // Eternal Doom map03
+			{
+				// fix broken staircase. The compatibility option is not sufficient
+				// to reliably handle this so clear the tags from the unwanted sectors.
+				ClearSectorTags(212);
+				ClearSectorTags(213);
+				ClearSectorTags(214);
+				break;
+			}
+		
+			case 'DCE862393CAAA6FF1294FB7056B53057': // UAC Ultra map07
+			{
+				// Contains a scroller depending on Boom side effects
+				SetLineSpecial(391, Sector_CopyScroller, 99, 6);
+				break;
+			}
+
+			case '9D50EBE17CEC78938C7A668DB0768611': // Strain map07
+			{
+				// Make the exit accessible
+				SetLineFlags(1021, 0, 1);
+				break;
+			}
+
+			case '3D8ED20BF5CAAE6D6AE0E10999C75084': // hgarden.pk3 map01
+			{
+				// spawn trees on top of arches
+				SetThingZ(399, 168);
+				SetThingZ(400, 168);
+				SetThingZ(401, 168);
+				SetThingZ(402, 168);
+				SetThingZ(403, 168);
+				SetThingZ(404, 168);
+				break;
+			}
 		}
 	}
 

From 6631f208b17e5f0c1b461c9bc6d43c77d29657fd Mon Sep 17 00:00:00 2001
From: "alexey.lysiuk" <alexey.lysiuk@gmail.com>
Date: Wed, 11 Apr 2018 17:01:57 +0300
Subject: [PATCH 10/13] Scriptified remaining compatibility entries

---
 src/compatibility.cpp                         | 19 +++++++
 wadsrc/static/compatibility.txt               | 55 ++-----------------
 wadsrc/static/zscript/level_compatibility.txt | 40 +++++++++++++-
 3 files changed, 62 insertions(+), 52 deletions(-)

diff --git a/src/compatibility.cpp b/src/compatibility.cpp
index d77f2dafa..576154dc0 100644
--- a/src/compatibility.cpp
+++ b/src/compatibility.cpp
@@ -856,6 +856,25 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetVertex)
 	return 0;
 }
 
+DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetLineSectorRef)
+{
+	PARAM_PROLOGUE;
+	PARAM_UINT(lineidx);
+	PARAM_UINT(sideidx);
+	PARAM_UINT(sectoridx);
+
+	if (   sideidx < 2
+		&& lineidx < level.lines.Size()
+		&& sectoridx < level.sectors.Size())
+	{
+		if (side_t *side = level.lines[lineidx].sidedef[sideidx])
+		{
+			side->sector = &level.sectors[sectoridx];
+		}
+	}
+	return 0;
+}
+
 
 //==========================================================================
 //
diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt
index b923d263f..69de0fa9b 100644
--- a/wadsrc/static/compatibility.txt
+++ b/wadsrc/static/compatibility.txt
@@ -244,6 +244,11 @@ DC96228097DD004C40CCB1DB14A91EAA // unloved.pk3:unlovedmaps.wad map05
 	clipmidtex
 }
 
+6DC9F6CCEAE7A91AEC48EBE506F22BC4 // void.wad MAP01
+{
+	setslopeoverflow
+	polyobj
+}
 
 
 
@@ -260,53 +265,3 @@ DC96228097DD004C40CCB1DB14A91EAA // unloved.pk3:unlovedmaps.wad map05
 	setsectortag 910 32002
 	setlinespecial 2410 Sector_Set3DFloor 32002 4 1 0 0
 }
-
-
-
-
-
-FCCA97FC851F6473EAA069F74247B317 // pg-raw.wad map31
-{
-	setlinesectorref 331 front 74
-	setlinesectorref 326 front 74
-	setlinesectorref 497 front 74
-	setlinesectorref 474 front 74
-	setlinesectorref 471 front 74
-	setlinesectorref 327 front 74
-	setlinesectorref 328 front 74
-	setlinesectorref 329 front 74
-	setsectortag 74 4
-	setlinespecial 357 Transfer_Heights 4 2 0 0 0 
-}
-
-6DC9F6CCEAE7A91AEC48EBE506F22BC4 // void.wad MAP01
-{
-	// Slightly squash the pillars in the starting room with "stimpacks"
-	// floating on them so that they can be obtained.
-	setsectoroffset 62 floor -8
-	setwallyscale 286 front bot 1.090909
-	setwallyscale 287 front bot 1.090909
-	setwallyscale 288 front bot 1.090909
-	setwallyscale 289 front bot 1.090909
-	
-	setsectoroffset 63 floor -8
-	setwallyscale 290 front bot 1.090909
-	setwallyscale 291 front bot 1.090909
-	setwallyscale 292 front bot 1.090909
-	setwallyscale 293 front bot 1.090909
-	
-	setsectoroffset 118 floor -8
-	setwallyscale 710 front bot 1.090909
-	setwallyscale 711 front bot 1.090909
-	setwallyscale 712 front bot 1.090909
-	setwallyscale 713 front bot 1.090909
-	
-	setsectoroffset 119 floor -8
-	setwallyscale 714 front bot 1.090909
-	setwallyscale 715 front bot 1.090909
-	setwallyscale 716 front bot 1.090909
-	setwallyscale 717 front bot 1.090909
-
-	setslopeoverflow
-	polyobj
-}
diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
index df01ebc96..acfbfda69 100644
--- a/wadsrc/static/zscript/level_compatibility.txt
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -440,7 +440,7 @@ class LevelCompatibility play
 				OffsetSectorPlane(284, Sector.floor,   -8);
 				OffsetSectorPlane(284, Sector.ceiling, -8);
 				// Missing textures
-				SetWallTexture(490, Line.back,  Side.bottom, "GRSTNPB");
+				SetWallTexture(490, Line.back, Side.bottom, "GRSTNPB");
 				TextureID woodwl = TexMan.CheckForTexture("WOODWL", TexMan.Type_Wall);
 				SetWallTextureID( 722, Line.front, Side.bottom, woodwl);
 				SetWallTextureID( 911, Line.front, Side.bottom, woodwl);
@@ -528,7 +528,7 @@ class LevelCompatibility play
 			case '9D50EBE17CEC78938C7A668DB0768611': // Strain map07
 			{
 				// Make the exit accessible
-				SetLineFlags(1021, 0, 1);
+				SetLineFlags(1021, 0, Line.ML_BLOCKING);
 				break;
 			}
 
@@ -543,6 +543,36 @@ class LevelCompatibility play
 				SetThingZ(404, 168);
 				break;
 			}
+
+			case '6DC9F6CCEAE7A91AEC48EBE506F22BC4': // void.wad MAP01
+			{
+				// Slightly squash the pillars in the starting room with "stimpacks"
+				// floating on them so that they can be obtained.
+				OffsetSectorPlane( 62, Sector.floor, -8);
+				OffsetSectorPlane( 63, Sector.floor, -8);
+				OffsetSectorPlane(118, Sector.floor, -8);
+				OffsetSectorPlane(119, Sector.floor, -8);
+				for (int i = 0; i < 8; ++i)
+				{
+					SetWallYScale(286 + i, Line.front, Side.bottom, 1.090909);
+					SetWallYScale(710 + i, Line.front, Side.bottom, 1.090909);
+				}
+				break;
+			}
+
+			case 'FCCA97FC851F6473EAA069F74247B317': // pg-raw.wad map31
+			{
+				SetLineSectorRef(331, Line.front, 74);
+				SetLineSectorRef(326, Line.front, 74);
+				SetLineSectorRef(497, Line.front, 74);
+				SetLineSectorRef(474, Line.front, 74);
+				SetLineSectorRef(471, Line.front, 74);
+				SetLineSectorRef(327, Line.front, 74);
+				SetLineSectorRef(328, Line.front, 74);
+				SetLineSectorRef(329, Line.front, 74);
+				AddSectorTag(74, 4);
+				SetLineSpecial(357, Transfer_Heights, 4, 2);
+			}
 		}
 	}
 
@@ -553,6 +583,7 @@ class LevelCompatibility play
 	private static native void SetThingZ(int thing, double z);
 	private static native void SetThingFlags(int thing, int flags);
 	private static native void SetVertex(uint vertex, double x, double y);
+	private static native void SetLineSectorRef(uint line, uint side, uint sector);
 	
 	private static void SetWallTexture(int line, int side, int texpart, String texture)
 	{
@@ -608,4 +639,9 @@ class LevelCompatibility play
 	{
 		level.sectors[sectornum].SetLightLevel(newval);
 	}
+
+	private static void SetWallYScale(int line, int side, int texpart, double scale)
+	{
+		level.lines[line].sidedef[side].SetTextureYScale(texpart, 1.090909);
+	}
 }

From 3988e270591ff7eebedc5d424f5e9ffc90fb87c8 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Wed, 11 Apr 2018 19:10:15 +0200
Subject: [PATCH 11/13] - scriptified the last remaining definition (BTSX MAP12
 beta) - Changes to map geometry must force a node rebuild (SetVertex,
 SetLineSectorRef.) - fixed incorrect use of scaling constant in
 SetWallYScale.

---
 src/compatibility.cpp                         |  3 +++
 wadsrc/static/compatibility.txt               | 18 +-----------------
 wadsrc/static/zscript/level_compatibility.txt | 18 +++++++++++++++++-
 3 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/src/compatibility.cpp b/src/compatibility.cpp
index 576154dc0..d8cc2ecfa 100644
--- a/src/compatibility.cpp
+++ b/src/compatibility.cpp
@@ -104,6 +104,7 @@ enum
 
 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
 extern TArray<FMapThing> MapThingsConverted;
+extern bool ForceNodeBuild;
 
 // PUBLIC DATA DEFINITIONS -------------------------------------------------
 
@@ -853,6 +854,7 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetVertex)
 	{
 		level.vertexes[vertex].p = DVector2(x, y);
 	}
+	ForceNodeBuild = true;
 	return 0;
 }
 
@@ -872,6 +874,7 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetLineSectorRef)
 			side->sector = &level.sectors[sectoridx];
 		}
 	}
+	ForceNodeBuild = true;
 	return 0;
 }
 
diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt
index 69de0fa9b..f5ea9710d 100644
--- a/wadsrc/static/compatibility.txt
+++ b/wadsrc/static/compatibility.txt
@@ -194,7 +194,7 @@ B9DFF13207EACAC675C71D82624D0007 // XtheaterIII map01
 
 D0139194F7817BF06F3988DFC47DB38D // Whispers of Satan map29
 {
-	nopassover
+	nopassover
 }
 
 5397C3B7D9B33AAF526D15A81A762828 // daedalus.wad Travel tubes (they are all identical)
@@ -249,19 +249,3 @@ DC96228097DD004C40CCB1DB14A91EAA // unloved.pk3:unlovedmaps.wad map05
 	setslopeoverflow
 	polyobj
 }
-
-
-
-
-712BB4CFBD0753178CA0C6814BE4C288 // map12 BTSX_E1 - patch some rendering glitches that are problematic to detect
-{
-	setsectortag 545 32000
-	setsectortag 1618 32000
-	setlinespecial 2853 Sector_Set3DFloor 32000 4 0 0 0
-	setsectortag 439 32001
-	setsectortag 458 32001
-	setlinespecial 2182 Sector_Set3DFloor 32001 4 0 0 0
-	setsectortag 454 32002
-	setsectortag 910 32002
-	setlinespecial 2410 Sector_Set3DFloor 32002 4 1 0 0
-}
diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
index acfbfda69..32f85b72c 100644
--- a/wadsrc/static/zscript/level_compatibility.txt
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -572,7 +572,23 @@ class LevelCompatibility play
 				SetLineSectorRef(329, Line.front, 74);
 				AddSectorTag(74, 4);
 				SetLineSpecial(357, Transfer_Heights, 4, 2);
+				break;
 			}
+			
+			case '712BB4CFBD0753178CA0C6814BE4C288': // beta version of map12 BTSX_E1 - patch some rendering glitches that are problematic to detect
+			{
+				AddSectorTag(545, 32000);
+				AddSectorTag(1618, 32000);
+				SetLineSpecial(2853, Sector_Set3DFloor, 32000, 4);
+				AddSectorTag(439, 32001);
+				AddSectorTag(458, 32001);
+				SetLineSpecial(2182, Sector_Set3DFloor, 32001, 4);
+				AddSectorTag(454, 32002);
+				AddSectorTag(910, 32002);
+				SetLineSpecial(2410, Sector_Set3DFloor, 32002, 4, 1);
+				break;
+			}
+			
 		}
 	}
 
@@ -642,6 +658,6 @@ class LevelCompatibility play
 
 	private static void SetWallYScale(int line, int side, int texpart, double scale)
 	{
-		level.lines[line].sidedef[side].SetTextureYScale(texpart, 1.090909);
+		level.lines[line].sidedef[side].SetTextureYScale(texpart, scale);
 	}
 }

From 3aea82797ca8764f07712b4a6832fe2c8dbb2b61 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Wed, 11 Apr 2018 19:21:02 +0200
Subject: [PATCH 12/13] - removed the parser for complex compatibility
 settings, now that this can be done via scripting.

---
 src/compatibility.cpp | 420 ------------------------------------------
 1 file changed, 420 deletions(-)

diff --git a/src/compatibility.cpp b/src/compatibility.cpp
index d8cc2ecfa..7bc1c916c 100644
--- a/src/compatibility.cpp
+++ b/src/compatibility.cpp
@@ -179,10 +179,6 @@ static const char *const SectorPlanes[] =
 	"floor", "ceil", NULL
 };
 
-static TArray<int> CompatParams;
-static int ii_compatparams;
-static TArray<FString> TexNames;
-
 // CODE --------------------------------------------------------------------
 
 //==========================================================================
@@ -200,7 +196,6 @@ void ParseCompatibility()
 	unsigned int j;
 
 	BCompatMap.Clear();
-	CompatParams.Clear();
 
 	// The contents of this file are not cumulative, as it should not
 	// be present in user-distributed maps.
@@ -253,205 +248,12 @@ void ParseCompatibility()
 			{
 				flags.CompatFlags[Options[i].WhichSlot] |= Options[i].CompatFlags;
 			}
-			else if (sc.Compare("clearlineflags"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_CLEARFLAGS);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-			}
-			else if (sc.Compare("setlineflags"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETFLAGS);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-			}
-			else if (sc.Compare("setlinespecial"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETSPECIAL);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-
-				sc.MustGetString();
-				CompatParams.Push(P_FindLineSpecial(sc.String, NULL, NULL));
-				for (int i = 0; i < 5; i++)
-				{
-					sc.MustGetNumber();
-					CompatParams.Push(sc.Number);
-				}
-			}
-			else if (sc.Compare("setlinesectorref"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETLINESECTORREF);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetString();
-				CompatParams.Push(sc.MustMatchString(LineSides));
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				flags.CompatFlags[SLOT_BCOMPAT] |= BCOMPATF_REBUILDNODES;
-			}
-			else if (sc.Compare("clearlinespecial"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_CLEARSPECIAL);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-			}
-			else if (sc.Compare("setactivation"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETACTIVATION);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-			}
-			else if (sc.Compare("setsectoroffset"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETSECTOROFFSET);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetString();
-				CompatParams.Push(sc.MustMatchString(SectorPlanes));
-				sc.MustGetFloat();
-				CompatParams.Push(int(sc.Float*65536.));
-			}
-			else if (sc.Compare("setsectorspecial"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETSECTORSPECIAL);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-			}
-			else if (sc.Compare("setwallyscale"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETWALLYSCALE);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetString();
-				CompatParams.Push(sc.MustMatchString(LineSides));
-				sc.MustGetString();
-				CompatParams.Push(sc.MustMatchString(WallTiers));
-				sc.MustGetFloat();
-				CompatParams.Push(int(sc.Float*65536.));
-			}
-			else if (sc.Compare("setwalltexture"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETWALLTEXTURE);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetString();
-				CompatParams.Push(sc.MustMatchString(LineSides));
-				sc.MustGetString();
-				CompatParams.Push(sc.MustMatchString(WallTiers));
-				sc.MustGetString();
-				const FString texName = sc.String;
-				const unsigned int texIndex = TexNames.Find(texName);
-				const unsigned int texCount = TexNames.Size();
-				if (texIndex == texCount)
-				{
-					TexNames.Push(texName);
-				}
-				CompatParams.Push(texIndex);
-			}
-			else if (sc.Compare("setthingz"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETTHINGZ);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetFloat();
-				CompatParams.Push(int(sc.Float*256));	// do not use full fixed here so that it can eventually handle larger levels
-			}
-			else if (sc.Compare("setsectortag"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETTAG);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-			}
-			else if (sc.Compare("setthingflags"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETTHINGFLAGS);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-			}
-			else if (sc.Compare("setvertex"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETVERTEX);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetFloat();
-				CompatParams.Push(int(sc.Float * 256));	// do not use full fixed here so that it can eventually handle larger levels
-				sc.MustGetFloat();
-				CompatParams.Push(int(sc.Float * 256));	// do not use full fixed here so that it can eventually handle larger levels
-				flags.CompatFlags[SLOT_BCOMPAT] |= BCOMPATF_REBUILDNODES;
-			}
-			else if (sc.Compare("setthingskills"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETTHINGSKILLS);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-			}
-			else if (sc.Compare("setsectortexture"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETSECTORTEXTURE);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetString();
-				CompatParams.Push(sc.MustMatchString(SectorPlanes));
-				sc.MustGetString();
-				const FString texName = sc.String;
-				const unsigned int texIndex = TexNames.Find(texName);
-				const unsigned int texCount = TexNames.Size();
-				if (texIndex == texCount)
-				{
-					TexNames.Push(texName);
-				}
-				CompatParams.Push(texIndex);
-			}
-			else if (sc.Compare("setsectorlight"))
-			{
-				if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
-				CompatParams.Push(CP_SETSECTORLIGHT);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-				sc.MustGetNumber();
-				CompatParams.Push(sc.Number);
-			}
 			else
 			{
 				sc.UnGet();
 				break;
 			}
 		}
-		if (flags.ExtCommandIndex != ~0u) 
-		{
-			CompatParams.Push(CP_END);
-		}
 		sc.MustGetStringName("}");
 		for (j = 0; j < md5array.Size(); ++j)
 		{
@@ -475,7 +277,6 @@ FName CheckCompatibility(MapData *map)
 	ii_compatflags = 0;
 	ii_compatflags2 = 0;
 	ib_compatflags = 0;
-	ii_compatparams = -1;
 
 	// When playing Doom IWAD levels force COMPAT_SHORTTEX and COMPATF_LIGHT.
 	// I'm not sure if the IWAD maps actually need COMPATF_LIGHT but it certainly does not hurt.
@@ -516,7 +317,6 @@ FName CheckCompatibility(MapData *map)
 		ii_compatflags |= flags->CompatFlags[SLOT_COMPAT];
 		ii_compatflags2 |= flags->CompatFlags[SLOT_COMPAT2];
 		ib_compatflags |= flags->CompatFlags[SLOT_BCOMPAT];
-		ii_compatparams = flags->ExtCommandIndex;
 	}
 
 	// Reset i_compatflags
@@ -551,226 +351,6 @@ void SetCompatibilityParams(FName checksum)
 			}
 		}
 	}
-
-	if (ii_compatparams != -1)
-	{
-		unsigned i = ii_compatparams;
-
-		while (i < CompatParams.Size() && CompatParams[i] != CP_END)
-		{
-			switch (CompatParams[i])
-			{
-				case CP_CLEARFLAGS:
-				{
-					if ((unsigned)CompatParams[i+1] < level.lines.Size())
-					{
-						line_t *line = &level.lines[CompatParams[i+1]];
-						line->flags &= ~CompatParams[i+2];
-					}
-					i+=3;
-					break;
-				}
-				case CP_SETFLAGS:
-				{
-					if ((unsigned)CompatParams[i+1] < level.lines.Size())
-					{
-						line_t *line = &level.lines[CompatParams[i+1]];
-						line->flags |= CompatParams[i+2];
-					}
-					i+=3;
-					break;
-				}
-				case CP_SETSPECIAL:
-				{
-					if ((unsigned)CompatParams[i+1] < level.lines.Size())
-					{
-						line_t *line = &level.lines[CompatParams[i+1]];
-						line->special = CompatParams[i+2];
-						for(int ii=0;ii<5;ii++)
-						{
-							line->args[ii] = CompatParams[i+ii+3];
-						}
-					}
-					i+=8;
-					break;
-				}
-				case CP_CLEARSPECIAL:
-				{
-					if ((unsigned)CompatParams[i+1] < level.lines.Size())
-					{
-						line_t *line = &level.lines[CompatParams[i+1]];
-						line->special = 0;
-						memset(line->args, 0, sizeof(line->args));
-					}
-					i += 2;
-					break;
-				}
-				case CP_SETACTIVATION:
-				{
-					if ((unsigned)CompatParams[i+1] < level.lines.Size())
-					{
-						line_t *line = &level.lines[CompatParams[i+1]];
-						line->activation = CompatParams[i+2];
-					}
-					i += 3;
-					break;
-				}
-				case CP_SETSECTOROFFSET:
-				{
-					if ((unsigned)CompatParams[i+1] < level.sectors.Size())
-					{
-						sector_t *sec = &level.sectors[CompatParams[i+1]];
-						const double delta = CompatParams[i + 3] / 65536.0;
-						secplane_t& plane = sector_t::floor == CompatParams[i + 2] 
-							? sec->floorplane 
-							: sec->ceilingplane;
-						plane.ChangeHeight(delta);
-						sec->ChangePlaneTexZ(CompatParams[i + 2], delta);
-					}
-					i += 4;
-					break;
-				}
-				case CP_SETSECTORSPECIAL:
-				{
-					const unsigned index = CompatParams[i + 1];
-					if (index < level.sectors.Size())
-					{
-						level.sectors[index].special = CompatParams[i + 2];
-					}
-					i += 3;
-					break;
-				}
-				case CP_SETWALLYSCALE:
-				{
-					if ((unsigned)CompatParams[i+1] < level.lines.Size())
-					{
-						side_t *side = level.lines[CompatParams[i+1]].sidedef[CompatParams[i+2]];
-						if (side != NULL)
-						{
-							side->SetTextureYScale(CompatParams[i+3], CompatParams[i+4] / 65536.);
-						}
-					}
-					i += 5;
-					break;
-				}
-				case CP_SETWALLTEXTURE:
-				{
-					if ((unsigned)CompatParams[i + 1] < level.lines.Size())
-					{
-						side_t *side = level.lines[CompatParams[i + 1]].sidedef[CompatParams[i + 2]];
-						if (side != NULL)
-						{
-							assert(TexNames.Size() > (unsigned int)CompatParams[i + 4]);
-							const FTextureID texID = TexMan.GetTexture(TexNames[CompatParams[i + 4]], ETextureType::Any);
-							side->SetTexture(CompatParams[i + 3], texID);
-						}
-					}
-					i += 5;
-					break;
-				}
-				case CP_SETTHINGZ:
-				{
-					// When this is called, the things haven't been spawned yet so we can alter the position inside the MapThings array.
-					if ((unsigned)CompatParams[i+1] < MapThingsConverted.Size())
-					{
-						MapThingsConverted[CompatParams[i+1]].pos.Z = CompatParams[i+2]/256.;
-					}
-					i += 3;
-					break;
-				}	
-				case CP_SETTAG:
-				{
-					if ((unsigned)CompatParams[i + 1] < level.sectors.Size())
-					{
-						// this assumes that the sector does not have any tags yet!
-						if (CompatParams[i + 2] == 0)
-						{
-							tagManager.RemoveSectorTags(CompatParams[i + 1]);
-						}
-						else
-						{
-							tagManager.AddSectorTag(CompatParams[i + 1], CompatParams[i + 2]);
-						}
-					}
-					i += 3;
-					break;
-				}
-				case CP_SETTHINGFLAGS:
-				{
-					if ((unsigned)CompatParams[i + 1] < MapThingsConverted.Size())
-					{
-						MapThingsConverted[CompatParams[i + 1]].flags = CompatParams[i + 2];
-					}
-					i += 3;
-					break;
-				}
-				case CP_SETVERTEX:
-				{
-					if ((unsigned)CompatParams[i + 1] < level.vertexes.Size())
-					{
-						level.vertexes[CompatParams[i + 1]].p.X = CompatParams[i + 2] / 256.;
-						level.vertexes[CompatParams[i + 1]].p.Y = CompatParams[i + 3] / 256.;
-					}
-					i += 4;
-					break;
-				}
-				case CP_SETTHINGSKILLS:
-				{
-					if ((unsigned)CompatParams[i + 1] < MapThingsConverted.Size())
-					{
-						MapThingsConverted[CompatParams[i + 1]].SkillFilter = CompatParams[i + 2];
-					}
-					i += 3;
-					break;
-				}
-				case CP_SETSECTORTEXTURE:
-				{
-					if ((unsigned)CompatParams[i + 1] < level.sectors.Size())
-					{
-						sector_t *sec = &level.sectors[CompatParams[i+1]];
-						assert (sec != nullptr);
-						secplane_t& plane = sector_t::floor == CompatParams[i + 2] 
-							? sec->floorplane 
-							: sec->ceilingplane;
-						assert(TexNames.Size() > (unsigned int)CompatParams[i + 3]);
-						const FTextureID texID = TexMan.GetTexture(TexNames[CompatParams[i + 3]], ETextureType::Any);
-
-						sec->SetTexture(CompatParams[i + 2], texID);
-					}
-					i += 4;
-					break;
-				}
-				case CP_SETSECTORLIGHT:
-				{
-					if ((unsigned)CompatParams[i + 1] < level.sectors.Size())
-					{
-						sector_t *sec = &level.sectors[CompatParams[i+1]];
-						assert (sec != nullptr);
-
-						sec->SetLightLevel((unsigned)CompatParams[i + 2]);
-					}
-					i += 3;
-					break;
-				}
-				case CP_SETLINESECTORREF:
-				{
-					if ((unsigned)CompatParams[i + 1] < level.lines.Size())
-					{
-						line_t *line = &level.lines[CompatParams[i + 1]];
-						assert(line != nullptr);
-						side_t *side = line->sidedef[CompatParams[i + 2]];
-						if (side != nullptr && (unsigned)CompatParams[i + 3] < level.sectors.Size())
-						{
-							side->sector = &level.sectors[CompatParams[i + 3]];
-						}
-					}
-					i += 4;
-					break;
-				}
-
-			}
-		}
-	}
 }
 
 DEFINE_ACTION_FUNCTION(DLevelCompatibility, OffsetSectorPlane)

From 387827555fc710ed81cc775955f10b96ce945213 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Wed, 11 Apr 2018 23:08:59 +0200
Subject: [PATCH 13/13] - added compatibility handler for Alien Vendetta MAP01
 to properly display the deep water hack and avoid problems with a node
 rebuild.

---
 src/compatibility.cpp                         | 10 +++--
 wadsrc/static/zscript/level_compatibility.txt | 40 ++++++++++++++++++-
 2 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/src/compatibility.cpp b/src/compatibility.cpp
index 7bc1c916c..74b0354d8 100644
--- a/src/compatibility.cpp
+++ b/src/compatibility.cpp
@@ -449,10 +449,11 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetLineSectorRef)
 		&& lineidx < level.lines.Size()
 		&& sectoridx < level.sectors.Size())
 	{
-		if (side_t *side = level.lines[lineidx].sidedef[sideidx])
-		{
-			side->sector = &level.sectors[sectoridx];
-		}
+		line_t *line = &level.lines[lineidx];
+		side_t *side = line->sidedef[sideidx];
+		side->sector = &level.sectors[sectoridx];
+		if (sideidx == 0) line->frontsector = side->sector;
+		else line->backsector = side->sector;
 	}
 	ForceNodeBuild = true;
 	return 0;
@@ -505,3 +506,4 @@ CCMD (hiddencompatflags)
 {
 	Printf("%08x %08x %08x\n", ii_compatflags, ii_compatflags2, ib_compatflags);
 }
+
diff --git a/wadsrc/static/zscript/level_compatibility.txt b/wadsrc/static/zscript/level_compatibility.txt
index 32f85b72c..773f10a22 100644
--- a/wadsrc/static/zscript/level_compatibility.txt
+++ b/wadsrc/static/zscript/level_compatibility.txt
@@ -571,7 +571,7 @@ class LevelCompatibility play
 				SetLineSectorRef(328, Line.front, 74);
 				SetLineSectorRef(329, Line.front, 74);
 				AddSectorTag(74, 4);
-				SetLineSpecial(357, Transfer_Heights, 4, 2);
+				SetLineSpecial(357, Transfer_Heights, 6);
 				break;
 			}
 			
@@ -589,6 +589,44 @@ class LevelCompatibility play
 				break;
 			}
 			
+			case '5A24FC83A3F9A2D6D54AF04E2E96684F': // AV.WAD MAP01
+			{
+				SetLineSectorRef(225, Line.back, 36);
+				SetLineSectorRef(222, Line.back, 36);
+				SetLineSectorRef(231, Line.back, 36);
+
+				SetLineSectorRef(223, Line.back, 36);
+				SetLineSectorRef(224, Line.back, 36);
+				SetLineSectorRef(227, Line.back, 36);
+
+				SetLineSectorRef(229, Line.back, 39);
+				SetLineSectorRef(233, Line.back, 39);
+
+				TextureID nukage = TexMan.CheckForTexture("NUKAGE1", TexMan.Type_Flat);
+				SetWallTexture(222, Line.front, Side.bottom, nukage);
+				SetWallTexture(223, Line.front, Side.bottom, nukage);
+				SetWallTexture(224, Line.front, Side.bottom, nukage);
+				SetWallTexture(225, Line.front, Side.bottom, nukage);
+				SetWallTexture(227, Line.front, Side.bottom, nukage);
+				SetWallTexture(231, Line.front, Side.bottom, nukage);
+				SetWallTexture(229, Line.front, Side.bottom, nukage);
+				SetWallTexture(233, Line.front, Side.bottom, nukage);
+
+				for(int i = 0; i < 8; i++)
+				{
+					SetLineSectorRef(i+234, Line.back, 37);
+					SetLineSectorRef(i+243, Line.back, 37);
+					SetWallTexture(i+234, Line.back, Side.bottom, nukage);
+					SetWallTexture(i+243, Line.back, Side.bottom, nukage);
+				}
+
+				SetLineSpecial(336, Transfer_Heights, 32000, 6);
+				AddSectorTag(40, 32000);
+				AddSectorTag(38, 32000);
+				AddSectorTag(37, 32000);
+				AddSectorTag(34, 32000);
+				break;
+			}
 		}
 	}