diff --git a/extras/conf/udb/Includes/SRB222_common.cfg b/extras/conf/udb/Includes/SRB222_common.cfg
index d5cf5a405a41abea2cbf2d7321b42b805612a55b..d15fbcdcbdb9c73a0656305f6aed1104e33747b8 100644
--- a/extras/conf/udb/Includes/SRB222_common.cfg
+++ b/extras/conf/udb/Includes/SRB222_common.cfg
@@ -258,6 +258,9 @@ mapformat_udmf
 		include("SRB222_sectors.cfg", "gen_sectortypes");
 	}
 
+	damagetypes = "Generic Water Fire Electric Spike DeathPitTilt DeathPitNoTilt Instakill SpecialStage";
+
+
 	// LINEDEF FLAGS
 	linedefflags
 	{
diff --git a/src/deh_lua.c b/src/deh_lua.c
index 56d2ec1e92deda284ff322ad07cb11de5563ee23..e313c588880280b4b85b63750822e28c1f0be512 100644
--- a/src/deh_lua.c
+++ b/src/deh_lua.c
@@ -330,18 +330,18 @@ static inline int lib_getenum(lua_State *L)
 	}
 	else if (fastncmp("ML_", word, 3)) {
 		p = word+3;
-		for (i = 0; i < 16; i++)
-			if (ML_LIST[i] && fastcmp(p, ML_LIST[i])) {
+		for (i = 0; ML_LIST[i]; i++)
+			if (fastcmp(p, ML_LIST[i])) {
 				lua_pushinteger(L, ((lua_Integer)1<<i));
 				return 1;
 			}
 		if (mathlib) return luaL_error(L, "linedef flag '%s' could not be found.\n", word);
 		return 0;
 	}
-	else if (fastncmp("MSF_", word, 3)) {
+	else if (fastncmp("MSF_", word, 4)) {
 		p = word + 4;
-		for (i = 0; i < 7; i++)
-			if (MSF_LIST[i] && fastcmp(p, MSF_LIST[i])) {
+		for (i = 0; MSF_LIST[i]; i++)
+			if (fastcmp(p, MSF_LIST[i])) {
 				lua_pushinteger(L, ((lua_Integer)1 << i));
 				return 1;
 			}
@@ -353,16 +353,26 @@ static inline int lib_getenum(lua_State *L)
 		if (mathlib) return luaL_error(L, "sector flag '%s' could not be found.\n", word);
 		return 0;
 	}
-	else if (fastncmp("SSF_", word, 3)) {
+	else if (fastncmp("SSF_", word, 4)) {
 		p = word + 4;
-		for (i = 0; i < 19; i++)
-			if (SSF_LIST[i] && fastcmp(p, SSF_LIST[i])) {
+		for (i = 0; SSF_LIST[i]; i++)
+			if (fastcmp(p, SSF_LIST[i])) {
 				lua_pushinteger(L, ((lua_Integer)1 << i));
 				return 1;
 			}
 		if (mathlib) return luaL_error(L, "sector special flag '%s' could not be found.\n", word);
 		return 0;
 	}
+	else if (fastncmp("SD_", word, 3)) {
+		p = word + 3;
+		for (i = 0; SD_LIST[i]; i++)
+			if (fastcmp(p, SD_LIST[i])) {
+				lua_pushinteger(L, i);
+				return 1;
+			}
+		if (mathlib) return luaL_error(L, "sector damagetype '%s' could not be found.\n", word);
+		return 0;
+	}
 	else if (fastncmp("S_",word,2)) {
 		p = word+2;
 		for (i = 0; i < NUMSTATEFREESLOTS; i++) {
diff --git a/src/deh_tables.c b/src/deh_tables.c
index 26fa74c902c352cd03cd1a6595c9cd14355c5c2a..1409fae5810522975e3e425c00d8ac68704dccda 100644
--- a/src/deh_tables.c
+++ b/src/deh_tables.c
@@ -4452,7 +4452,7 @@ const char *const GAMETYPERULE_LIST[] = {
 };
 
 // Linedef flags
-const char *const ML_LIST[16] = {
+const char *const ML_LIST[] = {
 	"IMPASSIBLE",
 	"BLOCKMONSTERS",
 	"TWOSIDED",
@@ -4464,15 +4464,16 @@ const char *const ML_LIST[16] = {
 	"EFFECT3",
 	"EFFECT4",
 	"EFFECT5",
-	"NOSONIC",
-	"NOTAILS",
-	"NOKNUX",
+	"NETONLY",
+	"NONET",
+	"EFFECT6",
 	"BOUNCY",
-	"TFERLINE"
+	"TFERLINE",
+	NULL
 };
 
 // Sector flags
-const char *const MSF_LIST[7] = {
+const char *const MSF_LIST[] = {
 	"FLIPSPECIAL_FLOOR",
 	"FLIPSPECIAL_CEILING",
 	"TRIGGERSPECIAL_TOUCH",
@@ -4480,10 +4481,11 @@ const char *const MSF_LIST[7] = {
 	"GRAVITYFLIP",
 	"HEATWAVE",
 	"NOCLIPCAMERA",
+	NULL
 };
 
 // Sector special flags
-const char* const SSF_LIST[19] = {
+const char *const SSF_LIST[] = {
 	"OUTERSPACE",
 	"DOUBLESTEPUP",
 	"WINDCURRENT",
@@ -4502,6 +4504,22 @@ const char* const SSF_LIST[19] = {
 	"ZOOMTUBEEND",
 	"FINISHLINE",
 	"ROPEHANG",
+	NULL
+};
+
+// Sector damagetypes
+const char *const SD_LIST[] = {
+	"NONE",
+	"GENERIC",
+	"WATER",
+	"FIRE",
+	"ELECTRIC",
+	"SPIKE",
+	"DEATHPITTILT",
+	"DEATHPITNOTILT",
+	"INSTAKILL",
+	"SPECIALSTAGE",
+	NULL
 };
 
 const char *COLOR_ENUMS[] = {
diff --git a/src/deh_tables.h b/src/deh_tables.h
index 35f58c88224e001a7832f9e921d27c9cec316292..3fbc6357b64877e3ebaf664a1a8e3c58b3e14020 100644
--- a/src/deh_tables.h
+++ b/src/deh_tables.h
@@ -64,9 +64,10 @@ extern const char *const MOBJEFLAG_LIST[];
 extern const char *const MAPTHINGFLAG_LIST[4];
 extern const char *const PLAYERFLAG_LIST[];
 extern const char *const GAMETYPERULE_LIST[];
-extern const char *const ML_LIST[16]; // Linedef flags
-extern const char* const MSF_LIST[7]; // Sector flags
-extern const char* const SSF_LIST[19]; // Sector special flags
+extern const char *const ML_LIST[]; // Linedef flags
+extern const char *const MSF_LIST[]; // Sector flags
+extern const char *const SSF_LIST[]; // Sector special flags
+extern const char *const SD_LIST[]; // Sector damagetype
 extern const char *COLOR_ENUMS[];
 extern const char *const POWERS_LIST[];
 extern const char *const HUDITEMS_LIST[];
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index 8ab8c7e83e594f3350f11ac3f861480e8a718e55..b18f4a44f3b7858271d63dc21cdfb9e35cc68785 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -51,6 +51,7 @@ enum sector_e {
 	sector_cslope,
 	sector_flags,
 	sector_specialflags,
+	sector_damagetype,
 	sector_friction,
 	sector_gravity,
 };
@@ -78,6 +79,7 @@ static const char *const sector_opt[] = {
 	"c_slope",
 	"flags",
 	"specialflags",
+	"damagetype",
 	"friction",
 	"gravity",
 	NULL};
@@ -663,6 +665,9 @@ static int sector_get(lua_State *L)
 	case sector_specialflags: // specialflags
 		lua_pushinteger(L, sector->specialflags);
 		return 1;
+	case sector_damagetype: // damagetype
+		lua_pushinteger(L, (UINT8)sector->damagetype);
+		return 1;
 	case sector_friction: // friction
 		lua_pushinteger(L, sector->friction);
 		return 1;
@@ -763,6 +768,9 @@ static int sector_set(lua_State *L)
 	case sector_specialflags:
 		sector->specialflags = luaL_checkinteger(L, 3);
 		break;
+	case sector_damagetype:
+		sector->damagetype = (UINT8)luaL_checkinteger(L, 3);
+		break;
 	case sector_gravity:
 		sector->gravity = luaL_checkfixed(L, 3);
 		break;
diff --git a/src/p_map.c b/src/p_map.c
index beae1a8ea614965f671206f04ed482479449a969..c3271c10e02e2bc337b68a7f91e07059c913fc51 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -3594,7 +3594,7 @@ static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
 		if (!(rover->flags & FF_SWIMMABLE))
 			continue;
 
-		if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 3)
+		if (rover->master->frontsector->damagetype != SD_FIRE)
 			continue;
 
 		if (rover->master->flags & ML_BLOCKMONSTERS)
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 4b31307efdacc6503d7db8c9031a5604c9051575..004575a7964da5a28fa789368b95dfd8308f0869 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -2325,8 +2325,8 @@ boolean P_CheckDeathPitCollide(mobj_t *mo)
 		&& ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_FLOOR))
 	|| (mo->z + mo->height >= mo->subsector->sector->ceilingheight
 		&& ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_CEILING)))
-	&& (GETSECSPECIAL(mo->subsector->sector->special, 1) == 6
-	|| GETSECSPECIAL(mo->subsector->sector->special, 1) == 7))
+	&& (mo->subsector->sector->damagetype == SD_DEATHPITTILT
+	|| mo->subsector->sector->damagetype == SD_DEATHPITNOTILT))
 		return true;
 
 	return false;
@@ -2334,7 +2334,7 @@ boolean P_CheckDeathPitCollide(mobj_t *mo)
 
 boolean P_CheckSolidLava(ffloor_t *rover)
 {
-	if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3
+	if (rover->flags & FF_SWIMMABLE && rover->master->frontsector->damagetype == SD_FIRE
 		&& !(rover->master->flags & ML_BLOCKMONSTERS))
 			return true;
 
@@ -3305,7 +3305,7 @@ void P_MobjCheckWater(mobj_t *mobj)
 
 		if (mobj->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))
 		{
-			if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 3)
+			if (rover->master->frontsector->damagetype == SD_FIRE)
 				mobj->eflags |= MFE_TOUCHLAVA;
 
 			if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY))
@@ -4097,7 +4097,7 @@ static void P_KillRingsInLava(mobj_t *mo)
 				if (!(rover->flags & FF_EXISTS)) continue; // fof must be real
 
 				if (!(rover->flags & FF_SWIMMABLE // fof must be water
-					&& GETSECSPECIAL(rover->master->frontsector->special, 1) == 3)) // fof must be lava water
+					&& rover->master->frontsector->damagetype == SD_FIRE)) // fof must be lava water
 					continue;
 
 				// find heights of FOF
@@ -10985,8 +10985,8 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
 
 	if (mobj->floorz != starting_floorz)
 		mobj->precipflags |= PCF_FOF;
-	else if (GETSECSPECIAL(mobj->subsector->sector->special, 1) == 7
-	 || GETSECSPECIAL(mobj->subsector->sector->special, 1) == 6
+	else if (mobj->subsector->sector->damagetype == SD_DEATHPITNOTILT
+	 || mobj->subsector->sector->damagetype == SD_DEATHPITTILT
 	 || mobj->subsector->sector->floorpic == skyflatnum)
 		mobj->precipflags |= PCF_PIT;
 
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 1923fa57650685dad985cd8f07b5d227d40f0dcd..1baa34582ec6a8580aa0ef7b128b61d7896bd347 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -854,7 +854,11 @@ static void P_NetUnArchiveWaypoints(void)
 #define SD_CEILLIGHT 0x10
 #define SD_FLAG      0x20
 #define SD_SPECIALFLAG 0x40
-#define SD_GRAVITY   0x80
+#define SD_DIFF4     0x80
+
+//diff4 flags
+#define SD_DAMAGETYPE 0x01
+#define SD_GRAVITY   0x02
 
 #define LD_FLAG     0x01
 #define LD_SPECIAL  0x02
@@ -993,11 +997,11 @@ static void ArchiveSectors(void)
 	size_t i, j;
 	const sector_t *ss = sectors;
 	const sector_t *spawnss = spawnsectors;
-	UINT8 diff, diff2, diff3;
+	UINT8 diff, diff2, diff3, diff4;
 
 	for (i = 0; i < numsectors; i++, ss++, spawnss++)
 	{
-		diff = diff2 = diff3 = 0;
+		diff = diff2 = diff3 = diff4 = 0;
 		if (ss->floorheight != spawnss->floorheight)
 			diff |= SD_FLOORHT;
 		if (ss->ceilingheight != spawnss->ceilingheight)
@@ -1044,12 +1048,17 @@ static void ArchiveSectors(void)
 			diff3 |= SD_FLAG;
 		if (ss->specialflags != spawnss->specialflags)
 			diff3 |= SD_SPECIALFLAG;
+		if (ss->damagetype != spawnss->damagetype)
+			diff4 |= SD_DAMAGETYPE;
 		if (ss->gravity != spawnss->gravity)
-			diff3 |= SD_GRAVITY;
+			diff4 |= SD_GRAVITY;
 
 		if (ss->ffloors && CheckFFloorDiff(ss))
 			diff |= SD_FFLOORS;
 
+		if (diff4)
+			diff3 |= SD_DIFF4;
+
 		if (diff3)
 			diff2 |= SD_DIFF3;
 
@@ -1064,6 +1073,8 @@ static void ArchiveSectors(void)
 				WRITEUINT8(save_p, diff2);
 			if (diff2 & SD_DIFF3)
 				WRITEUINT8(save_p, diff3);
+			if (diff3 & SD_DIFF4)
+				WRITEUINT8(save_p, diff4);
 			if (diff & SD_FLOORHT)
 				WRITEFIXED(save_p, ss->floorheight);
 			if (diff & SD_CEILHT)
@@ -1114,7 +1125,9 @@ static void ArchiveSectors(void)
 				WRITEUINT32(save_p, ss->flags);
 			if (diff3 & SD_SPECIALFLAG)
 				WRITEUINT32(save_p, ss->specialflags);
-			if (diff3 & SD_GRAVITY)
+			if (diff4 & SD_DAMAGETYPE)
+				WRITEUINT8(save_p, ss->damagetype);
+			if (diff4 & SD_GRAVITY)
 				WRITEFIXED(save_p, ss->gravity);
 			if (diff & SD_FFLOORS)
 				ArchiveFFloors(ss);
@@ -1127,7 +1140,7 @@ static void ArchiveSectors(void)
 static void UnArchiveSectors(void)
 {
 	UINT16 i, j;
-	UINT8 diff, diff2, diff3;
+	UINT8 diff, diff2, diff3, diff4;
 	for (;;)
 	{
 		i = READUINT16(save_p);
@@ -1147,6 +1160,10 @@ static void UnArchiveSectors(void)
 			diff3 = READUINT8(save_p);
 		else
 			diff3 = 0;
+		if (diff3 & SD_DIFF4)
+			diff4 = READUINT8(save_p);
+		else
+			diff4 = 0;
 
 		if (diff & SD_FLOORHT)
 			sectors[i].floorheight = READFIXED(save_p);
@@ -1224,7 +1241,9 @@ static void UnArchiveSectors(void)
 		}
 		if (diff3 & SD_SPECIALFLAG)
 			sectors[i].specialflags = READUINT32(save_p);
-		if (diff3 & SD_GRAVITY)
+		if (diff4 & SD_DAMAGETYPE)
+			sectors[i].damagetype = READUINT8(save_p);
+		if (diff4 & SD_GRAVITY)
 			sectors[i].gravity = READFIXED(save_p);
 
 		if (diff & SD_FFLOORS)
diff --git a/src/p_setup.c b/src/p_setup.c
index 17fd5bb6337afb3482e80ddaa579da453e5a1c2d..4efbc4e4bc154d29ab071bc8a0ea26506d2ea3cf 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1049,6 +1049,8 @@ static void P_LoadSectors(UINT8 *data)
 		ss->gravity = FRACUNIT;
 
 		ss->flags = MSF_FLIPSPECIAL_FLOOR;
+		ss->specialflags = 0;
+		ss->damagetype = SD_NONE;
 
 		P_InitializeSector(ss);
 	}
@@ -1721,6 +1723,27 @@ static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val)
 		sectors[i].friction = atol(val);
 	else if (fastcmp(param, "gravity"))
 		sectors[i].gravity = FLOAT_TO_FIXED(atof(val));
+	else if (fastcmp(param, "damagetype"))
+	{
+		if (fastcmp(val, "Generic"))
+			sectors[i].damagetype = SD_GENERIC;
+		if (fastcmp(val, "Water"))
+			sectors[i].damagetype = SD_WATER;
+		if (fastcmp(val, "Fire"))
+			sectors[i].damagetype = SD_FIRE;
+		if (fastcmp(val, "Electric"))
+			sectors[i].damagetype = SD_ELECTRIC;
+		if (fastcmp(val, "Spike"))
+			sectors[i].damagetype = SD_SPIKE;
+		if (fastcmp(val, "DeathPitTilt"))
+			sectors[i].damagetype = SD_DEATHPITTILT;
+		if (fastcmp(val, "DeathPitNoTilt"))
+			sectors[i].damagetype = SD_DEATHPITNOTILT;
+		if (fastcmp(val, "Instakill"))
+			sectors[i].damagetype = SD_INSTAKILL;
+		if (fastcmp(val, "SpecialStage"))
+			sectors[i].damagetype = SD_SPECIALSTAGE;
+	}
 }
 
 static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val)
@@ -2000,6 +2023,8 @@ static void P_LoadTextmap(void)
 		sc->gravity = FRACUNIT;
 
 		sc->flags = MSF_FLIPSPECIAL_FLOOR;
+		sc->specialflags = 0;
+		sc->damagetype = SD_NONE;
 
 		textmap_colormap.used = false;
 		textmap_colormap.lightcolor = 0;
@@ -5059,9 +5084,35 @@ static void P_ConvertBinaryMap(void)
 
 	for (i = 0; i < numsectors; i++)
 	{
-
 		switch(GETSECSPECIAL(sectors[i].special, 1))
 		{
+			case 1: //Damage
+				sectors[i].damagetype = SD_GENERIC;
+				break;
+			case 2: //Damage (Water)
+				sectors[i].damagetype = SD_WATER;
+				break;
+			case 3: //Damage (Fire)
+				sectors[i].damagetype = SD_FIRE;
+				break;
+			case 4: //Damage (Electric)
+				sectors[i].damagetype = SD_ELECTRIC;
+				break;
+			case 5: //Spikes
+				sectors[i].damagetype = SD_SPIKE;
+				break;
+			case 6: //Death pit (camera tilt)
+				sectors[i].damagetype = SD_DEATHPITTILT;
+				break;
+			case 7: //Death pit (no camera tilt)
+				sectors[i].damagetype = SD_DEATHPITNOTILT;
+				break;
+			case 8: //Instakill
+				sectors[i].damagetype = SD_INSTAKILL;
+				break;
+			case 11: //Special stage damage
+				sectors[i].damagetype = SD_SPECIALSTAGE;
+				break;
 			case 12: //Space countdown
 				sectors[i].specialflags |= SSF_OUTERSPACE;
 				break;
diff --git a/src/p_spec.c b/src/p_spec.c
index 2e48219722906be5dc84ccf08654cb69c84f99b4..95c3a51188be54866ebdfa0244dc8ef01e24e9ff 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -4917,7 +4917,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
 	mtag_t sectag = Tag_FGet(&sector->tags);
 	boolean isTouching;
 
-	if (!sector->special && sector->specialflags == 0)
+	if (!sector->special && sector->specialflags == 0 && sector->damagetype == SD_NONE)
 		return;
 
 	// Ignore spectators
@@ -4995,33 +4995,30 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
 	if ((sector->specialflags & SSF_ROPEHANG) && isTouching)
 		P_ProcessRopeHang(player, sectag);
 
-	section1 = GETSECSPECIAL(sector->special, 1);
-	section2 = GETSECSPECIAL(sector->special, 2);
-
-	switch (section1)
+	switch (sector->damagetype)
 	{
-		case 1: // Damage (Generic)
+		case SD_GENERIC:
 			if (isTouching)
 				P_DamageMobj(player->mo, NULL, NULL, 1, 0);
 			break;
-		case 2: // Damage (Water)
+		case SD_WATER:
 			if (isTouching && (player->powers[pw_underwater] || player->powers[pw_carry] == CR_NIGHTSMODE))
 				P_DamageMobj(player->mo, NULL, NULL, 1, DMG_WATER);
 			break;
-		case 3: // Damage (Fire)
+		case SD_FIRE:
 			if (isTouching)
 				P_DamageMobj(player->mo, NULL, NULL, 1, DMG_FIRE);
 			break;
-		case 4: // Damage (Electrical)
+		case SD_ELECTRIC:
 			if (isTouching)
 				P_DamageMobj(player->mo, NULL, NULL, 1, DMG_ELECTRIC);
 			break;
-		case 5: // Spikes
+		case SD_SPIKE:
 			if (isTouching)
 				P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPIKE);
 			break;
-		case 6: // Death Pit (Camera Mod)
-		case 7: // Death Pit (No Camera Mod)
+		case SD_DEATHPITTILT:
+		case SD_DEATHPITNOTILT:
 			if (!isTouching)
 				break;
 			if (player->quittime)
@@ -5029,12 +5026,33 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
 			else
 				P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT);
 			break;
-		case 8: // Instant Kill
+		case SD_INSTAKILL:
 			if (player->quittime)
 				G_MovePlayerToSpawnOrStarpost(player - players);
 			else
 				P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL);
 			break;
+		case SD_SPECIALSTAGE:
+			if (!isTouching)
+				break;
+
+			if (player->exiting || player->bot) // Don't do anything for bots or players who have just finished
+				break;
+
+			if (!(player->powers[pw_shield] || player->spheres > 0)) // Don't do anything if no shield or spheres anyway
+				break;
+
+			P_SpecialStageDamage(player, NULL, NULL);
+			break;
+		default:
+			break;
+	}
+
+	section1 = GETSECSPECIAL(sector->special, 1);
+	section2 = GETSECSPECIAL(sector->special, 2);
+
+	switch (section1)
+	{
 		case 9: // Ring Drainer (Floor Touch)
 			if (!isTouching)
 				break;
@@ -5048,18 +5066,6 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
 				S_StartSound(player->mo, sfx_antiri);
 			}
 			break;
-		case 11: // Special Stage Damage
-			if (!isTouching)
-				break;
-
-			if (player->exiting || player->bot) // Don't do anything for bots or players who have just finished
-				break;
-
-			if (!(player->powers[pw_shield] || player->spheres > 0)) // Don't do anything if no shield or spheres anyway
-				break;
-
-			P_SpecialStageDamage(player, NULL, NULL);
-			break;
 	}
 
 	switch (section2)
@@ -5100,7 +5106,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector)
 
 	for (rover = sector->ffloors; rover; rover = rover->next)
 	{
-		if (!rover->master->frontsector->special && rover->master->frontsector->specialflags == 0)
+		if (!rover->master->frontsector->special && rover->master->frontsector->specialflags == 0 && rover->master->frontsector->damagetype == SD_NONE)
 			continue;
 
 		if (!(rover->flags & FF_EXISTS))
@@ -5134,7 +5140,7 @@ static void P_PlayerOnSpecialPolyobj(player_t *player)
 
 		polysec = po->lines[0]->backsector;
 
-		if (!polysec->special && polysec->specialflags == 0)
+		if (!polysec->special && polysec->specialflags == 0 && polysec->damagetype == SD_NONE)
 			continue;
 
 		touching = (polysec->flags & MSF_TRIGGERSPECIAL_TOUCH) && P_MobjTouchingPolyobj(po, player->mo);
diff --git a/src/p_user.c b/src/p_user.c
index 1006e21ed36b3202da284479a3186b9ce57ae0af..7360d2ef91724594c3e50afdef94df4937f63f6b 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -10258,7 +10258,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
 		thiscam->momx = FixedMul(x - thiscam->x, camspeed);
 		thiscam->momy = FixedMul(y - thiscam->y, camspeed);
 
-		if (GETSECSPECIAL(thiscam->subsector->sector->special, 1) == 6
+		if (thiscam->subsector->sector->damagetype == SD_DEATHPITTILT
 			&& thiscam->z < thiscam->subsector->sector->floorheight + 256*FRACUNIT
 			&& FixedMul(z - thiscam->z, camspeed) < 0)
 		{
@@ -12230,7 +12230,7 @@ static boolean P_MobjAboveLava(mobj_t *mobj)
 
 		for (rover = sector->ffloors; rover; rover = rover->next)
 		{
-			if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || GETSECSPECIAL(rover->master->frontsector->special, 1) != 3)
+			if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->master->frontsector->damagetype != SD_FIRE)
 				continue;
 
 			if (mobj->eflags & MFE_VERTICALFLIP)
diff --git a/src/r_defs.h b/src/r_defs.h
index 2b1cbfa58c0d6d6dedf0748b4933dd1100f701c4..4180af8009c2b5430182b6170e64d85372415e06 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -312,6 +312,20 @@ typedef enum
 	SSF_ROPEHANG = 1<<18,
 } sectorspecialflags_t;
 
+typedef enum
+{
+	SD_NONE = 0,
+	SD_GENERIC = 1,
+	SD_WATER = 2,
+	SD_FIRE = 3,
+	SD_ELECTRIC = 4,
+	SD_SPIKE = 5,
+	SD_DEATHPITTILT = 6,
+	SD_DEATHPITNOTILT = 7,
+	SD_INSTAKILL = 8,
+	SD_SPECIALSTAGE = 9,
+} sectordamage_t;
+
 typedef enum
 {
 	CRUMBLE_NONE, // No crumble thinker
@@ -394,6 +408,7 @@ typedef struct sector_s
 	fixed_t *gravityptr; // For binary format: Read gravity from floor height of master sector
 	sectorflags_t flags;
 	sectorspecialflags_t specialflags;
+	UINT8 damagetype;
 
 	INT32 friction;