diff --git a/readme.txt b/readme.txt
index 8a09f0bc5e54edf4b92518742cd5223114d9c3be..c1898d491f0291bbfad2bd09b8b2cbc7b673e9ee 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
-Here it is! SRB2 v2.1.12 source code!
+Here it is! SRB2 v2.1.14 source code!
 (why do we keep the version number up to date
 	when everything else in this file is hilariously old?
 	- Inuyasha)
diff --git a/src/command.c b/src/command.c
index 09588eb84b9762a8b814ff8b7e25cd243596d5a4..e10787f1b8aec79bf652fd2e87297434ed965801 100644
--- a/src/command.c
+++ b/src/command.c
@@ -379,11 +379,13 @@ void COM_AddCommand(const char *name, com_func_t func)
 	{
 		if (!stricmp(name, cmd->name)) //case insensitive now that we have lower and uppercase!
 		{
+#ifdef HAVE_BLUA
 			// don't I_Error for Lua commands
 			// Lua commands can replace game commands, and they have priority.
 			// BUT, if for some reason we screwed up and made two console commands with the same name,
 			// it's good to have this here so we find out.
 			if (cmd->function != COM_Lua_f)
+#endif
 				I_Error("Command %s already exists\n", name);
 
 			return;
@@ -397,6 +399,7 @@ void COM_AddCommand(const char *name, com_func_t func)
 	com_commands = cmd;
 }
 
+#ifdef HAVE_BLUA
 /** Adds a console command for Lua.
   * No I_Errors allowed; return a negative code instead.
   *
@@ -429,6 +432,7 @@ int COM_AddLuaCommand(const char *name)
 	com_commands = cmd;
 	return 0;
 }
+#endif
 
 /** Tests if a command exists.
   *
@@ -1284,6 +1288,8 @@ void CV_LoadNetVars(UINT8 **p)
 	serverloading = false;
 }
 
+static void CV_SetCVar(consvar_t *var, const char *value, boolean stealth);
+
 void CV_ResetCheatNetVars(void)
 {
 	consvar_t *cvar;
@@ -1291,7 +1297,7 @@ void CV_ResetCheatNetVars(void)
 	// Stealthset everything back to default.
 	for (cvar = consvar_vars; cvar; cvar = cvar->next)
 		if (cvar->flags & CV_CHEAT)
-			Setvalue(cvar, cvar->defaultvalue, true);
+			CV_SetCVar(cvar, cvar->defaultvalue, true);
 }
 
 // Returns true if the variable's current value is its default value
@@ -1428,11 +1434,7 @@ void CV_AddValue(consvar_t *var, INT32 increment)
 	INT32 newvalue, max;
 
 	// count pointlimit better
-	if (var == &cv_pointlimit && (gametype == GT_MATCH
-#ifdef CHAOSISNOTDEADYET
-		|| gametype == GT_CHAOS
-#endif
-		))
+	if (var == &cv_pointlimit && (gametype == GT_MATCH))
 		increment *= 50;
 	newvalue = var->value + increment;
 
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index e24a1426ab5929fc716116101492a4a76eca197c..c0179ca1be99cff5fb94b2a15b73a81269c02719 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -823,7 +823,7 @@ static inline void resynch_read_ctf(resynchend_pak *p)
 	{
 		if (!playeringame[p->flagplayer[1]])
 			 I_Error("Invalid blue flag player %d who isn't in the game!", (INT32)p->flagplayer[1]);
-		players[p->flagplayer[1]].gotflag = GF_REDFLAG;
+		players[p->flagplayer[1]].gotflag = GF_BLUEFLAG;
 		if (blueflag)
 		{
 			P_RemoveMobj(blueflag);
diff --git a/src/d_main.c b/src/d_main.c
index 4cea94a8178c4f34a35a9622bcaf704660f48210..95808b274ff111cb9146870f8530e5fe48686114 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -90,6 +90,9 @@ int	snprintf(char *str, size_t n, const char *fmt, ...);
 #include "hardware/hw3sound.h"
 #endif
 
+// platform independant focus loss
+UINT8 window_notinfocus = false;
+
 //
 // DEMO LOOP
 //
@@ -437,6 +440,17 @@ static void D_Display(void)
 		CON_Drawer();
 
 	M_Drawer(); // menu is drawn even on top of everything
+
+	// focus lost notification goes on top of everything, even the former everything
+	if (window_notinfocus)
+	{
+		M_DrawTextBox((BASEVIDWIDTH/2) - (60), (BASEVIDHEIGHT/2) - (16), 13, 2);
+		if (gamestate == GS_LEVEL && (P_AutoPause() || paused))
+			V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), V_YELLOWMAP, "Game Paused");
+		else
+			V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2) - (4), V_YELLOWMAP, "Focus Lost");
+	}
+
 	NetUpdate(); // send out any new accumulation
 
 	// It's safe to end the game now.
@@ -635,6 +649,7 @@ void D_AdvanceDemo(void)
 //
 void D_StartTitle(void)
 {
+	INT32 i;
 	if (netgame)
 	{
 		if (gametype == GT_COOP)
@@ -661,6 +676,16 @@ void D_StartTitle(void)
 	SV_StopServer();
 	SV_ResetServer();
 
+	for (i = 0; i < MAXPLAYERS; i++)
+		CL_ClearPlayer(i);
+
+	splitscreen = false;
+	SplitScreen_OnChange();
+	botingame = false;
+	botskin = 0;
+	cv_debug = 0;
+	emeralds = 0;
+
 	// In case someone exits out at the same time they start a time attack run,
 	// reset modeattacking
 	modeattacking = ATTACKING_NONE;
@@ -803,7 +828,7 @@ static void IdentifyVersion(void)
 	D_AddFile(va(pandf,srb2waddir,"rings.dta"));
 
 	// Add our crappy patches to fix our bugs
-	D_AddFile(va(pandf,srb2waddir,"patch.dta"));
+	// D_AddFile(va(pandf,srb2waddir,"patch.dta"));
 
 #if !defined (HAVE_SDL) || defined (HAVE_MIXER)
 	{
@@ -1087,19 +1112,19 @@ void D_SRB2Main(void)
 #endif
 	D_CleanFile();
 
-#if 1 // md5s last updated 11/10/14
+#if 1 // md5s last updated 12/14/14
 
 	// Check MD5s of autoloaded files
-	W_VerifyFileMD5(0, "ac309fb3c7d4b5b685e2cd26beccf0e8"); // srb2.srb/srb2.wad
-	W_VerifyFileMD5(1, "f39b6c849295e3c81875726e8cc0e2c7"); // zones.dta
+	W_VerifyFileMD5(0, "c1b9577687f8a795104aef4600720ea7"); // srb2.srb/srb2.wad
+	W_VerifyFileMD5(1, "303838c6c534d9540288360fa49cca60"); // zones.dta
 	W_VerifyFileMD5(2, "cfca0f1c73023cbbd8f844f45480f799"); // player.dta
 	W_VerifyFileMD5(3, "85901ad4bf94637e5753d2ac2c03ea26"); // rings.dta
-	W_VerifyFileMD5(4, "a45cc59d13dce924f2112b3e4201d0ae"); // patch.dta
+	//W_VerifyFileMD5(4, "0c66790502e648bfce90fdc5bb15722e"); // patch.dta
 	// don't check music.dta because people like to modify it, and it doesn't matter if they do
 	// ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for.
 #endif
 
-	mainwads = 5; // there are 5 wads not to unload
+	mainwads = 4; // there are 5 wads not to unload
 
 	cht_Init();
 
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 377da84338a737d101bb71fb90e0b2e6e36b6b5f..266161c7ce11fc522c1970e72180a27b3248f5fc 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -277,21 +277,6 @@ consvar_t cv_matchboxes = {"matchboxes", "Normal", CV_NETVAR|CV_CHEAT, matchboxe
 consvar_t cv_specialrings = {"specialrings", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_powerstones = {"powerstones", "On", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 
-#ifdef CHAOSISNOTDEADYET
-consvar_t cv_chaos_bluecrawla = {"chaos_bluecrawla", "8", CV_NETVAR, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_chaos_redcrawla = {"chaos_redcrawla", "8", CV_NETVAR, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_chaos_crawlacommander = {"chaos_crawlacommander", "2", CV_NETVAR, chances_cons_t,
-	NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_chaos_jettysynbomber = {"chaos_jettysynbomber", "5", CV_NETVAR, chances_cons_t,
-	NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_chaos_jettysyngunner = {"chaos_jettysyngunner", "2", CV_NETVAR, chances_cons_t,
-	NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_chaos_eggmobile1 = {"chaos_eggmobile1", "2", CV_NETVAR, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_chaos_eggmobile2 = {"chaos_eggmobile2", "2", CV_NETVAR, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_chaos_skim = {"chaos_skim", "5", CV_NETVAR, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_chaos_spawnrate = {"chaos_spawnrate", "30",CV_NETVAR, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL};
-#endif
-
 consvar_t cv_recycler =      {"tv_recycler",      "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_teleporters =   {"tv_teleporter",    "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_superring =     {"tv_superring",     "5", CV_NETVAR|CV_CHEAT, chances_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -498,18 +483,6 @@ void D_RegisterServerCommands(void)
 	CV_RegisterVar(&cv_competitionboxes);
 	CV_RegisterVar(&cv_matchboxes);
 
-#ifdef CHAOSISNOTDEADYET
-	CV_RegisterVar(&cv_chaos_bluecrawla);
-	CV_RegisterVar(&cv_chaos_redcrawla);
-	CV_RegisterVar(&cv_chaos_crawlacommander);
-	CV_RegisterVar(&cv_chaos_jettysynbomber);
-	CV_RegisterVar(&cv_chaos_jettysyngunner);
-	CV_RegisterVar(&cv_chaos_eggmobile1);
-	CV_RegisterVar(&cv_chaos_eggmobile2);
-	CV_RegisterVar(&cv_chaos_skim);
-	CV_RegisterVar(&cv_chaos_spawnrate);
-#endif
-
 	CV_RegisterVar(&cv_recycler);
 	CV_RegisterVar(&cv_teleporters);
 	CV_RegisterVar(&cv_superring);
@@ -699,6 +672,8 @@ void D_RegisterClientCommands(void)
 	CV_RegisterVar(&cv_invertmouse2);
 	CV_RegisterVar(&cv_mousesens);
 	CV_RegisterVar(&cv_mousesens2);
+	CV_RegisterVar(&cv_mouseysens);
+	CV_RegisterVar(&cv_mouseysens2);
 	CV_RegisterVar(&cv_mousemove);
 	CV_RegisterVar(&cv_mousemove2);
 
@@ -734,9 +709,6 @@ void D_RegisterClientCommands(void)
 	CV_RegisterVar(&cv_scr_width);
 	CV_RegisterVar(&cv_scr_height);
 
-	// p_fab.c
-	CV_RegisterVar(&cv_translucency);
-
 	CV_RegisterVar(&cv_soundtest);
 
 	// ingame object placing
@@ -3374,18 +3346,6 @@ void D_GameTypeChanged(INT32 lastgametype)
 
 		switch (gametype)
 		{
-#ifdef CHAOSISNOTDEADYET
-			case GT_CHAOS:
-				if (!cv_timelimit.changed && !cv_pointlimit.changed) // user hasn't changed limits
-				{
-					// default settings for chaos: timelimit 2 mins, no pointlimit
-					CV_SetValue(&cv_pointlimit, 0);
-					CV_SetValue(&cv_timelimit, 2);
-				}
-				if (!cv_itemrespawntime.changed)
-					CV_SetValue(&cv_itemrespawntime, 90); // respawn sparingly in chaos
-				break;
-#endif
 			case GT_MATCH:
 			case GT_TEAMMATCH:
 				if (!cv_timelimit.changed && !cv_pointlimit.changed) // user hasn't changed limits
@@ -3905,14 +3865,18 @@ static void Command_Cheats_f(void)
 {
 	if (COM_CheckParm("off"))
 	{
-		CV_ResetCheatNetVars();
+		if (!(server || (adminplayer == consoleplayer)))
+			CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
+		else
+			CV_ResetCheatNetVars();
 		return;
 	}
 
 	if (CV_CheatsEnabled())
 	{
 		CONS_Printf(M_GetText("At least one CHEAT-marked variable has been changed -- Cheats are enabled.\n"));
-		CONS_Printf(M_GetText("Type CHEATS OFF to reset all cheat variables to default.\n"));
+		if (server || (adminplayer == consoleplayer))
+			CONS_Printf(M_GetText("Type CHEATS OFF to reset all cheat variables to default.\n"));
 	}
 	else
 		CONS_Printf(M_GetText("No CHEAT-marked variables are changed -- Cheats are disabled.\n"));
diff --git a/src/d_netcmd.h b/src/d_netcmd.h
index c1cc27ceafa942731cac82cdbf0989296e52704f..31a7cf81864bd7872e2752ea6c264cbba6c43303 100644
--- a/src/d_netcmd.h
+++ b/src/d_netcmd.h
@@ -44,6 +44,7 @@ extern consvar_t cv_invertmouse2;
 extern consvar_t cv_alwaysfreelook2;
 extern consvar_t cv_mousemove2;
 extern consvar_t cv_mousesens2;
+extern consvar_t cv_mouseysens2;
 
 // normally in p_mobj but the .h is not read
 extern consvar_t cv_itemrespawntime;
@@ -80,7 +81,6 @@ extern consvar_t cv_useranalog, cv_useranalog2;
 extern consvar_t cv_analog, cv_analog2;
 
 extern consvar_t cv_netstat;
-extern consvar_t cv_translucency;
 extern consvar_t cv_splats;
 
 extern consvar_t cv_countdowntime;
@@ -113,12 +113,6 @@ extern consvar_t cv_ringslinger, cv_soundtest;
 
 extern consvar_t cv_specialrings, cv_powerstones, cv_matchboxes, cv_competitionboxes;
 
-#ifdef CHAOSISNOTDEADYET
-extern consvar_t cv_chaos_spawnrate, cv_chaos_bluecrawla, cv_chaos_redcrawla;
-extern consvar_t cv_chaos_crawlacommander, cv_chaos_jettysynbomber, cv_chaos_jettysyngunner;
-extern consvar_t cv_chaos_eggmobile1, cv_chaos_eggmobile2, cv_chaos_skim;
-#endif
-
 #ifdef NEWPING
 extern consvar_t cv_maxping;
 #endif
diff --git a/src/dehacked.c b/src/dehacked.c
index ccb7248e3fd1533f0289eb62c4163cf5e555b8b9..2dc9d742e07b8ee7cba9987d0798d9e975a051ca 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -5052,7 +5052,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_ARROWDOWN",
 
 	// Trapgoyle Demon fire
-	"S_DEMONFIRE",
+	"S_DEMONFIRE1",
+	"S_DEMONFIRE2",
+	"S_DEMONFIRE3",
+	"S_DEMONFIRE4",
+	"S_DEMONFIRE5",
+	"S_DEMONFIRE6",
 
 	"S_GFZFLOWERA",
 	"S_GFZFLOWERA2",
@@ -7062,7 +7067,6 @@ static const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for s
 	"MT_NIGHTOPIANHELPER", // the actual helper object that orbits you
 
 	// Utility Objects
-	"MT_CHAOSSPAWNER",
 	"MT_TELEPORTMAN",
 	"MT_ALTVIEWMAN",
 	"MT_CRUMBLEOBJ", // Sound generator for crumbling platform
@@ -7453,6 +7457,17 @@ struct {
 	{"FF_FULLBRIGHT",FF_FULLBRIGHT},
 	{"FF_TRANSMASK",FF_TRANSMASK},
 	{"FF_TRANSSHIFT",FF_TRANSSHIFT},
+	// new preshifted translucency (used in source)
+	{"FF_TRANS10",FF_TRANS10},
+	{"FF_TRANS20",FF_TRANS20},
+	{"FF_TRANS30",FF_TRANS30},
+	{"FF_TRANS40",FF_TRANS40},
+	{"FF_TRANS50",FF_TRANS50},
+	{"FF_TRANS60",FF_TRANS60},
+	{"FF_TRANS70",FF_TRANS70},
+	{"FF_TRANS80",FF_TRANS80},
+	{"FF_TRANS90",FF_TRANS90},
+	// compatibility
 	// Transparency for SOCs is pre-shifted
 	{"TR_TRANS10",tr_trans10<<FF_TRANSSHIFT},
 	{"TR_TRANS20",tr_trans20<<FF_TRANSSHIFT},
@@ -8047,7 +8062,7 @@ static fixed_t find_const(const char **rword)
 		return r;
 	}
 	if (!*(word+1) && // Turn a single A-z symbol into numbers, like sprite frames.
-	 (*word >= 'A' && *word <= 'Z') || (*word >= 'a' && *word <= 'z')) {
+	 ((*word >= 'A' && *word <= 'Z') || (*word >= 'a' && *word <= 'z'))) {
 		r = R_Char2Frame(*word);
 		free(word);
 		return r;
diff --git a/src/doomdef.h b/src/doomdef.h
index c4896a764d7937035552a5096ef2a0f4168e05e9..d14cd5ddbb452465964d6f9ecb8a16f52a4d6458 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -144,8 +144,8 @@ extern FILE *logstream;
 #define VERSIONSTRING "Trunk"
 #else
 #define VERSION    201 // Game version
-#define SUBVERSION 12  // more precise version number
-#define VERSIONSTRING "v2.1.12"
+#define SUBVERSION 14  // more precise version number
+#define VERSIONSTRING "v2.1.14"
 // Hey! If you change this, add 1 to the MODVERSION below!
 // Otherwise we can't force updates!
 #endif
@@ -203,7 +203,7 @@ extern FILE *logstream;
 // it's only for detection of the version the player is using so the MS can alert them of an update.
 // Only set it higher, not lower, obviously.
 // Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1".
-#define MODVERSION 17
+#define MODVERSION 19
 
 
 
@@ -449,10 +449,6 @@ extern const char *compdate, *comptime, *comprevision;
 ///	Dumps the contents of a network save game upon consistency failure for debugging.
 //#define DUMPCONSISTENCY
 
-///	Pre-1.08 Chaos gametype code
-///	\note	Code severely out of date, does not take new enemies/bosses into account.
-//#define CHAOSISNOTDEADYET
-
 ///	Polyobject fake flat code
 #define POLYOBJECTS_PLANES
 
diff --git a/src/doomstat.h b/src/doomstat.h
index b05b3833c61767cfd16c32c2d7b5ec7011a1fed4..44cf6feaabc586a449c1b55ea729a5c0ec401ef2 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -103,6 +103,7 @@ extern boolean digital_disabled;
 
 extern boolean menuactive; // Menu overlaid?
 extern UINT8 paused; // Game paused?
+extern UINT8 window_notinfocus; // are we in focus? (backend independant -- handles auto pausing and display of "focus lost" message)
 
 extern boolean nodrawers;
 extern boolean noblit;
diff --git a/src/g_game.c b/src/g_game.c
index 50f30dfcab60091dadfed6b18197df9b33e4f253..c59f23c0787f23de3a7cfe58c1393a638d4b9e4d 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -967,7 +967,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics)
 
 	// why build a ticcmd if we're paused?
 	// Or, for that matter, if we're being reborn.
-	if (paused || P_MenuActivePause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN))
+	if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN))
 	{
 		cmd->angleturn = (INT16)(localangle >> 16);
 		cmd->aiming = G_ClipAimingPitch(&localaiming);
@@ -1257,7 +1257,7 @@ void G_BuildTiccmd2(ticcmd_t *cmd, INT32 realtics)
 
 	//why build a ticcmd if we're paused?
 	// Or, for that matter, if we're being reborn.
-	if (paused || P_MenuActivePause() || player->playerstate == PST_REBORN)
+	if (paused || P_AutoPause() || player->playerstate == PST_REBORN)
 	{
 		cmd->angleturn = (INT16)(localangle2 >> 16);
 		cmd->aiming = G_ClipAimingPitch(&localaiming2);
@@ -2299,11 +2299,7 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost)
 	// -- DM/Tag/CTF-spectator/etc --
 	// Order: DM->CTF->Coop
 	else if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF
-	 || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT))
-#ifdef CHAOSISNOTDEADYET
-	 || gametype == GT_CHAOS
-#endif
-	)
+	 || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT)))
 	{
 		if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start
 		&& !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start
@@ -2709,9 +2705,6 @@ INT16 G_TOLFlag(INT32 pgametype)
 	if (pgametype == GT_RACE)         return TOL_RACE;
 	if (pgametype == GT_MATCH)        return TOL_MATCH;
 	if (pgametype == GT_TEAMMATCH)    return TOL_MATCH;
-#ifdef CHAOSISNOTDEADYET
-	if (pgametype == GT_CHAOS)        return TOL_CHAOS;
-#endif
 	if (pgametype == GT_TAG)          return TOL_TAG;
 	if (pgametype == GT_HIDEANDSEEK)  return TOL_TAG;
 	if (pgametype == GT_CTF)          return TOL_CTF;
diff --git a/src/g_input.c b/src/g_input.c
index f8170dd3afae9b44463916af8109188d7df253c6..f12ddb7114c4b935e79877de7195ee248c47f6c2 100644
--- a/src/g_input.c
+++ b/src/g_input.c
@@ -28,6 +28,8 @@ static CV_PossibleValue_t onecontrolperkey_cons_t[] = {{1, "One"}, {2, "Several"
 // mouse values are used once
 consvar_t cv_mousesens = {"mousesens", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_mousesens2 = {"mousesens2", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_mouseysens = {"mouseysens", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_mouseysens2 = {"mouseysens2", "35", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_controlperkey = {"controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 
 INT32 mousex, mousey;
@@ -99,7 +101,7 @@ void G_MapEventsToControls(event_t *ev)
 		case ev_mouse: // buttons are virtual keys
 			mousex = (INT32)(ev->data2*((cv_mousesens.value*cv_mousesens.value)/110.0f + 0.1f));
 			mousey = (INT32)(ev->data3*((cv_mousesens.value*cv_mousesens.value)/110.0f + 0.1f));
-			mlooky = mousey;
+			mlooky = (INT32)(ev->data3*((cv_mouseysens.value*cv_mousesens.value)/110.0f + 0.1f));
 			break;
 
 		case ev_joystick: // buttons are virtual keys
@@ -121,7 +123,7 @@ void G_MapEventsToControls(event_t *ev)
 		case ev_mouse2: // buttons are virtual keys
 			mouse2x = (INT32)(ev->data2*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f));
 			mouse2y = (INT32)(ev->data3*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f));
-			mlook2y = mouse2y;
+			mlook2y = (INT32)(ev->data3*((cv_mouseysens2.value*cv_mousesens2.value)/110.0f + 0.1f));
 			break;
 
 		default:
diff --git a/src/g_input.h b/src/g_input.h
index 699542a8a4cd08f664ad8dda51c2d0eba64db4e4..eca40591fa100680638867b12c81e4e886b375f3 100644
--- a/src/g_input.h
+++ b/src/g_input.h
@@ -125,7 +125,7 @@ typedef enum
 } gamecontrols_e;
 
 // mouse values are used once
-extern consvar_t cv_mousesens;
+extern consvar_t cv_mousesens, cv_mouseysens;
 
 extern INT32 mousex, mousey;
 extern INT32 mlooky; //mousey with mlookSensitivity
diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c
index ee68edd41be09cc1922b9faec951c4087d1b5120..fb369387f424764d88a76ffefa3e9c92506f06e6 100644
--- a/src/hardware/hw_light.c
+++ b/src/hardware/hw_light.c
@@ -278,6 +278,7 @@ light_t *t_lspr[NUMSPRITES] =
 	&lspr[SMALLREDBALL_L], // SPR_TRLS
 	&lspr[NOLIGHT],     // SPR_CBLL
 	&lspr[NOLIGHT],     // SPR_AROW
+	&lspr[NOLIGHT],     // SPR_CFIR
 
 	// Greenflower Scenery
 	&lspr[NOLIGHT],     // SPR_FWR1
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index ae940d96c6ec0b6d409bfb9670c000be2d2757d0..9d7101db80c8f7a73ba938c806eef5c0e2792aec 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -3796,7 +3796,9 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
 		}*/
 
 		// shadow is always half as translucent as the sprite itself
-		if (spr->mobj->flags2 & MF2_SHADOW)
+		if (!cv_translucency.value)
+			; // translucency disabled
+		else if (spr->mobj->flags2 & MF2_SHADOW)
 			sSurf.FlatColor.s.alpha = 0x20;
 		else if (spr->mobj->frame & FF_TRANSMASK)
 		{
diff --git a/src/hardware/r_opengl/ogl_win.c b/src/hardware/r_opengl/ogl_win.c
index 5cc075ceae75bb13b50fba1e0bed4e541aa6c922..eb9a31a7d7f1e909d72e88cc5bc3c166471b73ab 100644
--- a/src/hardware/r_opengl/ogl_win.c
+++ b/src/hardware/r_opengl/ogl_win.c
@@ -39,7 +39,7 @@
 #ifdef DEBUG_TO_FILE
 static unsigned long nb_frames = 0;
 static clock_t my_clock;
-FILE *logstream;
+FILE *gllogstream;
 #endif
 
 static  HDC     hDC           = NULL;       // the window's device context
@@ -81,8 +81,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module
 			// Initialize once for each new process.
 			// Return FALSE to fail DLL load.
 #ifdef DEBUG_TO_FILE
-			logstream = fopen("ogllog.txt", "wt");
-			if (logstream == NULL)
+			gllogstream = fopen("ogllog.txt", "wt");
+			if (gllogstream == NULL)
 				return FALSE;
 #endif
 			DisableThreadLibraryCalls(hinstDLL);
@@ -99,10 +99,10 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module
 		case DLL_PROCESS_DETACH:
 			// Perform any necessary cleanup.
 #ifdef DEBUG_TO_FILE
-			if (logstream)
+			if (gllogstream)
 			{
-				fclose(logstream);
-				logstream  = NULL;
+				fclose(gllogstream);
+				gllogstream  = NULL;
 			}
 #endif
 			break;
diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index 028bc9889eccb920eb4eca47cfce7c764649101e..76543e259806659a0c95652149c4e2979a2ec729 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -168,7 +168,6 @@ static boolean gl13 = false; // whether we can use opengl 1.3 functions
 //                  : else do nothing
 // Returns          :
 // -----------------+
-#if !(defined (HAVE_SDL) && defined (STATIC3DS))
 FUNCPRINTF void DBG_Printf(const char *lpFmt, ...)
 {
 #ifdef DEBUG_TO_FILE
@@ -178,13 +177,12 @@ FUNCPRINTF void DBG_Printf(const char *lpFmt, ...)
 	va_start (arglist, lpFmt);
 	vsnprintf (str, 4096, lpFmt, arglist);
 	va_end   (arglist);
-	if (logstream)
-		fwrite(str, strlen(str), 1, logstream);
+	if (gllogstream)
+		fwrite(str, strlen(str), 1, gllogstream);
 #else
 	(void)lpFmt;
 #endif
 }
-#endif
 
 #ifdef STATIC_OPENGL
 /* 1.0 functions */
@@ -673,7 +671,7 @@ static void GLProject(GLdouble objX, GLdouble objY, GLdouble objZ,
 // -----------------+
 void SetModelView(GLint w, GLint h)
 {
-	DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h);
+//	DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h);
 
 	screen_width = w;
 	screen_height = h;
@@ -714,7 +712,7 @@ void SetStates(void)
 	GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};
 #endif
 
-	DBG_Printf("SetStates()\n");
+//	DBG_Printf("SetStates()\n");
 
 	// Hurdler: not necessary, is it?
 	pglShadeModel(GL_SMOOTH);      // iterate vertice colors
diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h
index f4d4f77e00bbf4f38ff2bccac7bee579af7e9001..7ffefbb5881405bcf5a541c0f3218164a91cd581 100644
--- a/src/hardware/r_opengl/r_opengl.h
+++ b/src/hardware/r_opengl/r_opengl.h
@@ -57,9 +57,19 @@
 
 #undef DEBUG_TO_FILE            // maybe defined in previous *.h
 #define DEBUG_TO_FILE           // output debugging msgs to ogllog.txt
-#if defined ( HAVE_SDL ) && !defined ( LOGMESSAGES )
+
+// todo: find some way of getting SDL to log to ogllog.txt, without
+// interfering with r_opengl.dll
+#ifdef HAVE_SDL
 #undef DEBUG_TO_FILE
 #endif
+//#if defined(HAVE_SDL) && !defined(_DEBUG)
+//#undef DEBUG_TO_FILE
+//#endif
+
+#ifdef DEBUG_TO_FILE
+extern FILE             *gllogstream;
+#endif
 
 #ifndef DRIVER_STRING
 //    #define USE_PALETTED_TEXTURE
@@ -117,9 +127,6 @@ extern PFNglGetString pglGetString;
 
 extern const GLubyte    *gl_extensions;
 extern RGBA_t           myPaletteData[];
-#ifndef HAVE_SDL
-extern FILE             *logstream;
-#endif
 extern GLint            screen_width;
 extern GLint            screen_height;
 extern GLbyte           screen_depth;
diff --git a/src/info.c b/src/info.c
index c8f754b54d44acefbbe4ce0e90c73a1983fe8d51..fb30258c31b2ab85a813a3cc9d21d29df3bd58d3 100644
--- a/src/info.c
+++ b/src/info.c
@@ -37,23 +37,23 @@ char sprnames[NUMSPRITES + 1][5] =
 	"STEM","SPIK","SFLM","USPK","STPT","BMNE","SRBX","RRBX","BRBX","SHTV",
 	"PINV","YLTV","BLTV","BKTV","WHTV","GRTV","ELTV","EGGB","MIXU","RECY",
 	"QUES","GBTV","PRUP","PTTV","MTEX","MISL","TORP","ENRG","MINE","JBUL",
-	"TRLS","CBLL","AROW","FWR1","FWR2","FWR3","FWR4","BUS1","BUS2","THZP",
-	"ALRM","GARG","SEWE","DRIP","CRL1","CRL2","CRL3","BCRY","CHAN","FLAM",
-	"ESTA","SMCH","BMCH","SMCE","BMCE","BTBL","STBL","CACT","FLME","DFLM",
-	"XMS1","XMS2","XMS3","BSZ1","BSZ2","BSZ3","BSZ4","BSZ5","BSZ6","BSZ7",
-	"BSZ8","STLG","DBAL","RCRY","ARMA","ARMF","ARMB","WIND","MAGN","ELEM",
-	"FORC","PITY","IVSP","SSPK","GOAL","BIRD","BUNY","MOUS","CHIC","COWZ",
-	"RBRD","SPRY","SPRR","SPRB","YSPR","RSPR","RAIN","SNO1","SPLH","SPLA",
-	"SMOK","BUBP","BUBO","BUBN","BUBM","POPP","TFOG","SEED","PRTL","SCOR",
-	"DRWN","TTAG","GFLG","RRNG","RNGB","RNGR","RNGI","RNGA","RNGE","RNGS",
-	"RNGG","PIKB","PIKR","PIKA","PIKE","PIKS","PIKG","TAUT","TGRE","TSCR",
-	"COIN","CPRK","GOOM","BGOM","FFWR","FBLL","SHLL","PUMA","HAMM","KOOP",
-	"BFLM","MAXE","MUS1","MUS2","TOAD","NDRN","SUPE","SUPZ","NDRL","NSPK",
-	"NBMP","HOOP","NSCR","NPRU","CAPS","SUPT","SPRK","BOM1","BOM2","BOM3",
-	"BOM4","ROIA","ROIB","ROIC","ROID","ROIE","ROIF","ROIG","ROIH","ROII",
-	"ROIJ","ROIK","ROIL","ROIM","ROIN","ROIO","ROIP","BBAL","GWLG","GWLR",
-	"SRBA","SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI","SRBJ",
-	"SRBK","SRBL","SRBM","SRBN","SRBO",
+	"TRLS","CBLL","AROW","CFIR","FWR1","FWR2","FWR3","FWR4","BUS1","BUS2",
+	"THZP","ALRM","GARG","SEWE","DRIP","CRL1","CRL2","CRL3","BCRY","CHAN",
+	"FLAM","ESTA","SMCH","BMCH","SMCE","BMCE","BTBL","STBL","CACT","FLME",
+	"DFLM","XMS1","XMS2","XMS3","BSZ1","BSZ2","BSZ3","BSZ4","BSZ5","BSZ6",
+	"BSZ7","BSZ8","STLG","DBAL","RCRY","ARMA","ARMF","ARMB","WIND","MAGN",
+	"ELEM","FORC","PITY","IVSP","SSPK","GOAL","BIRD","BUNY","MOUS","CHIC",
+	"COWZ","RBRD","SPRY","SPRR","SPRB","YSPR","RSPR","RAIN","SNO1","SPLH",
+	"SPLA","SMOK","BUBP","BUBO","BUBN","BUBM","POPP","TFOG","SEED","PRTL",
+	"SCOR","DRWN","TTAG","GFLG","RRNG","RNGB","RNGR","RNGI","RNGA","RNGE",
+	"RNGS","RNGG","PIKB","PIKR","PIKA","PIKE","PIKS","PIKG","TAUT","TGRE",
+	"TSCR","COIN","CPRK","GOOM","BGOM","FFWR","FBLL","SHLL","PUMA","HAMM",
+	"KOOP","BFLM","MAXE","MUS1","MUS2","TOAD","NDRN","SUPE","SUPZ","NDRL",
+	"NSPK","NBMP","HOOP","NSCR","NPRU","CAPS","SUPT","SPRK","BOM1","BOM2",
+	"BOM3","BOM4","ROIA","ROIB","ROIC","ROID","ROIE","ROIF","ROIG","ROIH",
+	"ROII","ROIJ","ROIK","ROIL","ROIM","ROIN","ROIO","ROIP","BBAL","GWLG",
+	"GWLR","SRBA","SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI",
+	"SRBJ","SRBK","SRBL","SRBM","SRBN","SRBO",
 };
 
 // Doesn't work with g++, needs actionf_p1 (don't modify this comment)
@@ -61,6 +61,9 @@ state_t states[NUMSTATES] =
 {
 	// frame is masked through FF_FRAMEMASK
 	// FF_FULLBRIGHT (0x8000) activates the fullbright colormap
+	// use FF_TRANS10 - FF_TRANS90 for easy translucency
+	// (or tr_trans10<<FF_TRANSSHIFT if you want to make it hard on yourself)
+
 	// Keep this comment directly above S_NULL.
 	{SPR_NULL, 0,  1, {NULL}, 0, 0, S_NULL}, // S_NULL
 	{SPR_UNKN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_UNKNOWN
@@ -75,7 +78,7 @@ state_t states[NUMSTATES] =
 	{SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 6, 0, S_NULL}, // S_RAISESTATE
 
 	// Thok
-	{SPR_THOK, 0, 8, {NULL}, 0, 0, S_NULL}, // S_THOK
+	{SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL}, // S_THOK
 
 	// Player
 	{SPR_PLAY,     0, 105, {NULL},   0, 0, S_PLAY_TAP1},        // S_PLAY_STND
@@ -235,15 +238,15 @@ state_t states[NUMSTATES] =
 	// THZ Turret
 	{SPR_TRET, FF_FULLBRIGHT, 105, {A_TurretStop}, 0, 0, S_TURRETFIRE},   // S_TURRET
 	{SPR_TRET, FF_FULLBRIGHT, 105, {A_TurretFire}, 0, 0, S_TURRET},       // S_TURRETFIRE
-	{SPR_TRET, FF_FULLBRIGHT+1, 7, {A_Pain}, 0, 0, S_TURRETSHOCK2},       // S_TURRETSHOCK1
-	{SPR_TRET, FF_FULLBRIGHT+2, 7, {NULL}, 0, 0, S_TURRETSHOCK3},         // S_TURRETSHOCK2
-	{SPR_TRET, FF_FULLBRIGHT+3, 7, {NULL}, 0, 0, S_TURRETSHOCK4},         // S_TURRETSHOCK3
-	{SPR_TRET, FF_FULLBRIGHT+4, 7, {NULL}, 0, 0, S_TURRETSHOCK5},         // S_TURRETSHOCK4
-	{SPR_TRET, FF_FULLBRIGHT+1, 7, {NULL}, 0, 0, S_TURRETSHOCK6},         // S_TURRETSHOCK5
-	{SPR_TRET, FF_FULLBRIGHT+2, 7, {A_Pain}, 0, 0, S_TURRETSHOCK7},       // S_TURRETSHOCK6
-	{SPR_TRET, FF_FULLBRIGHT+3, 7, {NULL}, 0, 0, S_TURRETSHOCK8},         // S_TURRETSHOCK7
-	{SPR_TRET, FF_FULLBRIGHT+4, 7, {NULL}, 0, 0, S_TURRETSHOCK9},         // S_TURRETSHOCK8
-	{SPR_TRET, FF_FULLBRIGHT+4, 7, {A_LinedefExecute}, 32000, 0, S_XPLD1}, // S_TURRETSHOCK9
+	{SPR_TRET, FF_FULLBRIGHT|1, 7, {A_Pain}, 0, 0, S_TURRETSHOCK2},       // S_TURRETSHOCK1
+	{SPR_TRET, FF_FULLBRIGHT|2, 7, {NULL}, 0, 0, S_TURRETSHOCK3},         // S_TURRETSHOCK2
+	{SPR_TRET, FF_FULLBRIGHT|3, 7, {NULL}, 0, 0, S_TURRETSHOCK4},         // S_TURRETSHOCK3
+	{SPR_TRET, FF_FULLBRIGHT|4, 7, {NULL}, 0, 0, S_TURRETSHOCK5},         // S_TURRETSHOCK4
+	{SPR_TRET, FF_FULLBRIGHT|1, 7, {NULL}, 0, 0, S_TURRETSHOCK6},         // S_TURRETSHOCK5
+	{SPR_TRET, FF_FULLBRIGHT|2, 7, {A_Pain}, 0, 0, S_TURRETSHOCK7},       // S_TURRETSHOCK6
+	{SPR_TRET, FF_FULLBRIGHT|3, 7, {NULL}, 0, 0, S_TURRETSHOCK8},         // S_TURRETSHOCK7
+	{SPR_TRET, FF_FULLBRIGHT|4, 7, {NULL}, 0, 0, S_TURRETSHOCK9},         // S_TURRETSHOCK8
+	{SPR_TRET, FF_FULLBRIGHT|4, 7, {A_LinedefExecute}, 32000, 0, S_XPLD1}, // S_TURRETSHOCK9
 
 	{SPR_TURR, 0, 1, {A_Look}, 1, 0, S_TURRETPOPDOWN8},          // S_TURRETLOOK
 	{SPR_TURR, 0, 0, {A_FaceTarget}, 0, 0, S_TURRETPOPUP1},  // S_TURRETSEE
@@ -415,20 +418,20 @@ state_t states[NUMSTATES] =
 
 	// Boss Explosion
 	{SPR_BOM2, FF_FULLBRIGHT,   5, {NULL}, 0, 0, S_BPLD2}, // S_BPLD1
-	{SPR_BOM2, FF_FULLBRIGHT+1, 5, {NULL}, 0, 0, S_BPLD3}, // S_BPLD2
-	{SPR_BOM2, FF_FULLBRIGHT+2, 5, {NULL}, 0, 0, S_BPLD4}, // S_BPLD3
-	{SPR_BOM2, FF_FULLBRIGHT+3, 5, {NULL}, 0, 0, S_BPLD5}, // S_BPLD4
-	{SPR_BOM2, FF_FULLBRIGHT+4, 5, {NULL}, 0, 0, S_BPLD6}, // S_BPLD5
-	{SPR_BOM2, FF_FULLBRIGHT+5, 5, {NULL}, 0, 0, S_BPLD7}, // S_BPLD6
-	{SPR_BOM2, FF_FULLBRIGHT+6, 5, {NULL}, 0, 0, S_NULL},  // S_BPLD7
+	{SPR_BOM2, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_BPLD3}, // S_BPLD2
+	{SPR_BOM2, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_BPLD4}, // S_BPLD3
+	{SPR_BOM2, FF_FULLBRIGHT|3, 5, {NULL}, 0, 0, S_BPLD5}, // S_BPLD4
+	{SPR_BOM2, FF_FULLBRIGHT|4, 5, {NULL}, 0, 0, S_BPLD6}, // S_BPLD5
+	{SPR_BOM2, FF_FULLBRIGHT|5, 5, {NULL}, 0, 0, S_BPLD7}, // S_BPLD6
+	{SPR_BOM2, FF_FULLBRIGHT|6, 5, {NULL}, 0, 0, S_NULL},  // S_BPLD7
 
 	// S3&K Boss Explosion
 	{SPR_BOM3, FF_FULLBRIGHT,   1, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION2}, // S_SONIC3KBOSSEXPLOSION1
-	{SPR_BOM3, FF_FULLBRIGHT+1, 1, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION3}, // S_SONIC3KBOSSEXPLOSION2
-	{SPR_BOM3, FF_FULLBRIGHT+2, 2, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION4}, // S_SONIC3KBOSSEXPLOSION3
-	{SPR_BOM3, FF_FULLBRIGHT+3, 2, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION5}, // S_SONIC3KBOSSEXPLOSION4
-	{SPR_BOM3, FF_FULLBRIGHT+4, 3, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION6}, // S_SONIC3KBOSSEXPLOSION5
-	{SPR_BOM3, FF_FULLBRIGHT+5, 4, {NULL}, 0, 0, S_NULL}, // S_SONIC3KBOSSEXPLOSION6
+	{SPR_BOM3, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION3}, // S_SONIC3KBOSSEXPLOSION2
+	{SPR_BOM3, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION4}, // S_SONIC3KBOSSEXPLOSION3
+	{SPR_BOM3, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION5}, // S_SONIC3KBOSSEXPLOSION4
+	{SPR_BOM3, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_SONIC3KBOSSEXPLOSION6}, // S_SONIC3KBOSSEXPLOSION5
+	{SPR_BOM3, FF_FULLBRIGHT|5, 4, {NULL}, 0, 0, S_NULL}, // S_SONIC3KBOSSEXPLOSION6
 
 	{SPR_JETF, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_JETFUME2}, // S_JETFUME1
 	{SPR_NULL, 0,             1, {NULL}, 0, 0, S_JETFUME1}, // S_JETFUME2
@@ -638,7 +641,7 @@ state_t states[NUMSTATES] =
 
 	// Boss 4 Jet flame
 	{SPR_EFIR, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_JETFLAME2}, // S_JETFLAME1
-	{SPR_EFIR, FF_FULLBRIGHT+1, 1, {NULL}, 0, 0, S_JETFLAME1}, // S_JETFLAME2
+	{SPR_EFIR, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_JETFLAME1}, // S_JETFLAME2
 
 	{SPR_BRAK, 0, 1, {A_SetReactionTime}, 0, 0, S_BLACKEGG_STND2}, // S_BLACKEGG_STND
 	{SPR_BRAK, 0, 7, {A_Look}, 1, 0, S_BLACKEGG_STND2}, // S_BLACKEGG_STND2
@@ -713,13 +716,13 @@ state_t states[NUMSTATES] =
 
 	{SPR_NULL, 0, 1, {A_CapeChase}, (160 - 20) << 16, 0, S_BLACKEGG_HELPER}, // S_BLACKEGG_HELPER
 
-	{SPR_BGOO, 0, 2, {NULL}, 0, 0, S_BLACKEGG_GOOP2}, // S_BLACKEGG_GOOP1
-	{SPR_BGOO, 1, 2, {NULL}, 0, 0, S_BLACKEGG_GOOP1}, // S_BLACKEGG_GOOP2
-	{SPR_BGOO, 2, 6*TICRATE, {A_GoopSplat}, 0, 0, S_BLACKEGG_GOOP4}, // S_BLACKEGG_GOOP3
-	{SPR_BGOO, 2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP5}, // S_BLACKEGG_GOOP4
-	{SPR_BGOO, 2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP6}, // S_BLACKEGG_GOOP5
-	{SPR_BGOO, 2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP7}, // S_BLACKEGG_GOOP6
-	{SPR_BGOO, 2, 4, {NULL}, 0, 0, S_NULL}, // S_BLACKEGG_GOOP7
+	{SPR_BGOO, FF_TRANS50  , 2, {NULL}, 0, 0, S_BLACKEGG_GOOP2}, // S_BLACKEGG_GOOP1
+	{SPR_BGOO, FF_TRANS50|1, 2, {NULL}, 0, 0, S_BLACKEGG_GOOP1}, // S_BLACKEGG_GOOP2
+	{SPR_BGOO, FF_TRANS50|2, 6*TICRATE, {A_GoopSplat}, 0, 0, S_BLACKEGG_GOOP4}, // S_BLACKEGG_GOOP3
+	{SPR_BGOO, FF_TRANS60|2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP5}, // S_BLACKEGG_GOOP4
+	{SPR_BGOO, FF_TRANS70|2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP6}, // S_BLACKEGG_GOOP5
+	{SPR_BGOO, FF_TRANS80|2, 4, {NULL}, 0, 0, S_BLACKEGG_GOOP7}, // S_BLACKEGG_GOOP6
+	{SPR_BGOO, FF_TRANS90|2, 4, {NULL}, 0, 0, S_NULL}, // S_BLACKEGG_GOOP7
 
 	{SPR_BMSL, 0, 1, {NULL}, 0, 0, S_BLACKEGG_MISSILE}, // S_BLACKEGG_MISSILE
 
@@ -773,12 +776,12 @@ state_t states[NUMSTATES] =
 	{SPR_RCKT, 2 + FF_FULLBRIGHT, 6, {A_NapalmScatter}, MT_CYBRAKDEMON_NAPALM_FLAMES + (6<<16), 32 + (16<<16), S_CYBRAKDEMONMISSILE_EXPLODE3}, // S_CYBRAKDEMONMISSILE_EXPLODE2
 	{SPR_RCKT, 3 + FF_FULLBRIGHT, 4, {NULL}, 0, 0, S_NULL}, // S_CYBRAKDEMONMISSILE_EXPLODE3
 
-	{SPR_FLME, 0 + FF_FULLBRIGHT, 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY2}, // S_CYBRAKDEMONFLAMESHOT_FLY1
-	{SPR_FLME, 1 + FF_FULLBRIGHT, 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY2
-	{SPR_FLME, 2 + FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY3
-	{SPR_FLME, 2 + FF_FULLBRIGHT, 0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL}, // S_CYBRAKDEMONFLAMESHOT_DIE
+	{SPR_FLME, FF_TRANS50|FF_FULLBRIGHT  , 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY2}, // S_CYBRAKDEMONFLAMESHOT_FLY1
+	{SPR_FLME, FF_TRANS50|FF_FULLBRIGHT|1, 15, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY2
+	{SPR_FLME, FF_TRANS50|FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_CYBRAKDEMONFLAMESHOT_FLY3}, // S_CYBRAKDEMONFLAMESHOT_FLY3
+	{SPR_FLME, FF_TRANS50|FF_FULLBRIGHT|2, 0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL}, // S_CYBRAKDEMONFLAMESHOT_DIE
 
-	{SPR_FLAM, 3 + FF_FULLBRIGHT, 3, {A_SetFuse}, 10*TICRATE, 0, S_FLAME1}, // S_CYBRAKDEMONFLAMEREST
+	{SPR_FLAM, FF_TRANS50|FF_FULLBRIGHT|3, 3, {A_SetFuse}, 10*TICRATE, 0, S_FLAME1}, // S_CYBRAKDEMONFLAMEREST
 
 	{SPR_ELEC, 0 + FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_INIT2}, // S_CYBRAKDEMONELECTRICBARRIER_INIT1
 	{SPR_ELEC, 0 + FF_FULLBRIGHT, 0, {A_RemoteAction}, -1, S_CYBRAKDEMON_INVINCIBLERIZE, S_CYBRAKDEMONELECTRICBARRIER_PLAYSOUND}, // S_CYBRAKDEMONELECTRICBARRIER_INIT2
@@ -831,22 +834,22 @@ state_t states[NUMSTATES] =
 	{SPR_NULL, 0, 0, {A_SpawnFreshCopy}, 0, 0, S_CYBRAKDEMONELECTRICBARRIER_REVIVE3}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE2
 	{SPR_NULL, 0, TICRATE, {A_PlaySound}, sfx_s3k79, 0, S_NULL}, // S_CYBRAKDEMONELECTRICBARRIER_REVIVE3
 
-	{SPR_TARG, 0 + FF_FULLBRIGHT, 1, {A_VileFire}, sfx_s3k9d, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE2}, // S_CYBRAKDEMONTARGETRETICULE1
-	{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE3}, // S_CYBRAKDEMONTARGETRETICULE2
-	{SPR_TARG, 1 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE4}, // S_CYBRAKDEMONTARGETRETICULE3
-	{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE5}, // S_CYBRAKDEMONTARGETRETICULE4
-	{SPR_TARG, 2 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE6}, // S_CYBRAKDEMONTARGETRETICULE5
-	{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE7}, // S_CYBRAKDEMONTARGETRETICULE6
-	{SPR_TARG, 3 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE8}, // S_CYBRAKDEMONTARGETRETICULE7
-	{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE9}, // S_CYBRAKDEMONTARGETRETICULE8
-	{SPR_TARG, 4 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE10}, // S_CYBRAKDEMONTARGETRETICULE9
-	{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE11}, // S_CYBRAKDEMONTARGETRETICULE10
-	{SPR_TARG, 5 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE12}, // S_CYBRAKDEMONTARGETRETICULE11
-	{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE13}, // S_CYBRAKDEMONTARGETRETICULE12
-	{SPR_TARG, 0 + FF_FULLBRIGHT, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE14}, // S_CYBRAKDEMONTARGETRETICULE13
-	{SPR_TARG, 6 + FF_FULLBRIGHT, 1, {A_Repeat}, 6, S_CYBRAKDEMONTARGETRETICULE2, S_NULL}, // S_CYBRAKDEMONTARGETRETICULE14
-
-	{SPR_HOOP, 0 + FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_CYBRAKDEMONTARGETDOT
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT  , 1, {A_VileFire}, sfx_s3k9d, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE2}, // S_CYBRAKDEMONTARGETRETICULE1
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE3}, // S_CYBRAKDEMONTARGETRETICULE2
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|1, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE4}, // S_CYBRAKDEMONTARGETRETICULE3
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE5}, // S_CYBRAKDEMONTARGETRETICULE4
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|2, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE6}, // S_CYBRAKDEMONTARGETRETICULE5
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE7}, // S_CYBRAKDEMONTARGETRETICULE6
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|3, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE8}, // S_CYBRAKDEMONTARGETRETICULE7
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE9}, // S_CYBRAKDEMONTARGETRETICULE8
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|4, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE10}, // S_CYBRAKDEMONTARGETRETICULE9
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE11}, // S_CYBRAKDEMONTARGETRETICULE10
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|5, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE12}, // S_CYBRAKDEMONTARGETRETICULE11
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE13}, // S_CYBRAKDEMONTARGETRETICULE12
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT  , 1, {A_VileFire}, 0, MT_CYBRAKDEMON_TARGET_DOT, S_CYBRAKDEMONTARGETRETICULE14}, // S_CYBRAKDEMONTARGETRETICULE13
+	{SPR_TARG, FF_TRANS50|FF_FULLBRIGHT|6, 1, {A_Repeat}, 6, S_CYBRAKDEMONTARGETRETICULE2, S_NULL}, // S_CYBRAKDEMONTARGETRETICULE14
+
+	{SPR_HOOP, FF_TRANS50|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_CYBRAKDEMONTARGETDOT
 
 	{SPR_NPLM, 0, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY1,
 	{SPR_NPLM, 1, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMBOMBLARGE_FLY3}, //S_CYBRAKDEMONNAPALMBOMBLARGE_FLY2,
@@ -865,11 +868,11 @@ state_t states[NUMSTATES] =
 	{SPR_NULL, 0, 24, {A_Scream}, 0, 0, S_NULL}, //S_CYBRAKDEMONNAPALMBOMBSMALL_DIE5, // Sound
 
 	{SPR_SFLM, FF_FULLBRIGHT,   2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY2}, //S_CYBRAKDEMONNAPALMFLAME_FLY1,
-	{SPR_SFLM, FF_FULLBRIGHT+1, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY3}, //S_CYBRAKDEMONNAPALMFLAME_FLY2,
-	{SPR_SFLM, FF_FULLBRIGHT+2, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY4}, //S_CYBRAKDEMONNAPALMFLAME_FLY3,
-	{SPR_SFLM, FF_FULLBRIGHT+3, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY5}, //S_CYBRAKDEMONNAPALMFLAME_FLY4,
-	{SPR_SFLM, FF_FULLBRIGHT+4, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY6}, //S_CYBRAKDEMONNAPALMFLAME_FLY5,
-	{SPR_SFLM, FF_FULLBRIGHT+5, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY1}, //S_CYBRAKDEMONNAPALMFLAME_FLY6,
+	{SPR_SFLM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY3}, //S_CYBRAKDEMONNAPALMFLAME_FLY2,
+	{SPR_SFLM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY4}, //S_CYBRAKDEMONNAPALMFLAME_FLY3,
+	{SPR_SFLM, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY5}, //S_CYBRAKDEMONNAPALMFLAME_FLY4,
+	{SPR_SFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY6}, //S_CYBRAKDEMONNAPALMFLAME_FLY5,
+	{SPR_SFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_CYBRAKDEMONNAPALMFLAME_FLY1}, //S_CYBRAKDEMONNAPALMFLAME_FLY6,
 	{SPR_SFLM, FF_FULLBRIGHT,   0, {A_SpawnObjectRelative}, 0, MT_CYBRAKDEMON_FLAMEREST, S_NULL}, //S_CYBRAKDEMONNAPALMFLAME_DIE,
 
 	{SPR_NULL, 0, 1, {A_SetFuse}, TICRATE, 0, S_CYBRAKDEMONVILEEXPLOSION2}, //S_CYBRAKDEMONVILEEXPLOSION1,
@@ -909,18 +912,18 @@ state_t states[NUMSTATES] =
 	{SPR_METL,  5,  4, {NULL},         0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3
 	{SPR_METL,  4,  4, {NULL},         0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4
 
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)| 0, 1, {NULL}, 0, 0, S_MSSHIELD_F2},  // S_MSSHIELD_F1
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)| 1, 1, {NULL}, 0, 0, S_MSSHIELD_F3},  // S_MSSHIELD_F2
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)| 2, 1, {NULL}, 0, 0, S_MSSHIELD_F4},  // S_MSSHIELD_F3
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)| 3, 1, {NULL}, 0, 0, S_MSSHIELD_F5},  // S_MSSHIELD_F4
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)| 4, 1, {NULL}, 0, 0, S_MSSHIELD_F6},  // S_MSSHIELD_F5
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)| 5, 1, {NULL}, 0, 0, S_MSSHIELD_F7},  // S_MSSHIELD_F6
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)| 6, 1, {NULL}, 0, 0, S_MSSHIELD_F8},  // S_MSSHIELD_F7
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)| 7, 1, {NULL}, 0, 0, S_MSSHIELD_F9},  // S_MSSHIELD_F8
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)| 8, 1, {NULL}, 0, 0, S_MSSHIELD_F10}, // S_MSSHIELD_F9
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)| 9, 1, {NULL}, 0, 0, S_MSSHIELD_F11}, // S_MSSHIELD_F10
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)|10, 1, {NULL}, 0, 0, S_MSSHIELD_F12}, // S_MSSHIELD_F11
-	{SPR_MSCF, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT)|11, 1, {NULL}, 0, 0, S_MSSHIELD_F1},  // S_MSSHIELD_F12
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 0, 1, {NULL}, 0, 0, S_MSSHIELD_F2},  // S_MSSHIELD_F1
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 1, 1, {NULL}, 0, 0, S_MSSHIELD_F3},  // S_MSSHIELD_F2
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 2, 1, {NULL}, 0, 0, S_MSSHIELD_F4},  // S_MSSHIELD_F3
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 3, 1, {NULL}, 0, 0, S_MSSHIELD_F5},  // S_MSSHIELD_F4
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 4, 1, {NULL}, 0, 0, S_MSSHIELD_F6},  // S_MSSHIELD_F5
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 5, 1, {NULL}, 0, 0, S_MSSHIELD_F7},  // S_MSSHIELD_F6
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 6, 1, {NULL}, 0, 0, S_MSSHIELD_F8},  // S_MSSHIELD_F7
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 7, 1, {NULL}, 0, 0, S_MSSHIELD_F9},  // S_MSSHIELD_F8
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 8, 1, {NULL}, 0, 0, S_MSSHIELD_F10}, // S_MSSHIELD_F9
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 9, 1, {NULL}, 0, 0, S_MSSHIELD_F11}, // S_MSSHIELD_F10
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|10, 1, {NULL}, 0, 0, S_MSSHIELD_F12}, // S_MSSHIELD_F11
+	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|11, 1, {NULL}, 0, 0, S_MSSHIELD_F1},  // S_MSSHIELD_F12
 
 	// Ring
 	{SPR_RING,  0, 1, {NULL}, 0, 0, S_RING2},  // S_RING1
@@ -989,16 +992,16 @@ state_t states[NUMSTATES] =
 
 	// Special Stage Token
 	{SPR_EMMY, FF_FULLBRIGHT,   2, {NULL}, 0, 0, S_EMMY2}, // S_EMMY1
-	{SPR_EMMY, FF_FULLBRIGHT+1, 2, {NULL}, 0, 0, S_EMMY3}, // S_EMMY2
-	{SPR_EMMY, FF_FULLBRIGHT+2, 2, {NULL}, 0, 0, S_EMMY4}, // S_EMMY3
-	{SPR_EMMY, FF_FULLBRIGHT+3, 2, {NULL}, 0, 0, S_EMMY5}, // S_EMMY4
-	{SPR_EMMY, FF_FULLBRIGHT+4, 2, {NULL}, 0, 0, S_EMMY6}, // S_EMMY5
-	{SPR_EMMY, FF_FULLBRIGHT+5, 2, {NULL}, 0, 0, S_EMMY7}, // S_EMMY6
-	{SPR_EMMY, FF_FULLBRIGHT+6, 2, {NULL}, 0, 0, S_EMMY1}, // S_EMMY7
+	{SPR_EMMY, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_EMMY3}, // S_EMMY2
+	{SPR_EMMY, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_EMMY4}, // S_EMMY3
+	{SPR_EMMY, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_EMMY5}, // S_EMMY4
+	{SPR_EMMY, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_EMMY6}, // S_EMMY5
+	{SPR_EMMY, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_EMMY7}, // S_EMMY6
+	{SPR_EMMY, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_EMMY1}, // S_EMMY7
 
 	// Special Stage Token
-	{SPR_TOKE, FF_FULLBRIGHT,-1, {NULL}, 0, 0, S_NULL}, // S_TOKEN
-	{SPR_TOKE, FF_FULLBRIGHT, 1, {A_CapeChase}, 0, 0, S_MOVINGTOKEN}, // S_MOVINGTOKEN
+	{SPR_TOKE, FF_TRANS50|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_TOKEN
+	{SPR_TOKE, FF_TRANS50|FF_FULLBRIGHT,  1, {A_CapeChase}, 0, 0, S_MOVINGTOKEN}, // S_MOVINGTOKEN
 
 	// CTF Flags
 	{SPR_RFLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_REDFLAG
@@ -1034,12 +1037,12 @@ state_t states[NUMSTATES] =
 
 	// Chaos Emeralds
 	{SPR_CEMG, FF_FULLBRIGHT,   -1, {NULL}, 0, 0, S_NULL}, // S_CEMG1
-	{SPR_CEMG, FF_FULLBRIGHT+1, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG2
-	{SPR_CEMG, FF_FULLBRIGHT+2, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG3
-	{SPR_CEMG, FF_FULLBRIGHT+3, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG4
-	{SPR_CEMG, FF_FULLBRIGHT+4, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG5
-	{SPR_CEMG, FF_FULLBRIGHT+5, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG6
-	{SPR_CEMG, FF_FULLBRIGHT+6, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG7
+	{SPR_CEMG, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG2
+	{SPR_CEMG, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG3
+	{SPR_CEMG, FF_FULLBRIGHT|3, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG4
+	{SPR_CEMG, FF_FULLBRIGHT|4, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG5
+	{SPR_CEMG, FF_FULLBRIGHT|5, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG6
+	{SPR_CEMG, FF_FULLBRIGHT|6, -1, {NULL}, 0, 0, S_NULL}, // S_CEMG7
 
 	// Emeralds (for hunt)
 	{SPR_EMER, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EMER1
@@ -1132,11 +1135,11 @@ state_t states[NUMSTATES] =
 
 	// Red Shield's Spawn
 	{SPR_SFLM, FF_FULLBRIGHT,   2, {NULL}, 0, 0, S_SPINFIRE2}, // S_SPINFIRE1
-	{SPR_SFLM, FF_FULLBRIGHT+1, 2, {NULL}, 0, 0, S_SPINFIRE3}, // S_SPINFIRE2
-	{SPR_SFLM, FF_FULLBRIGHT+2, 2, {NULL}, 0, 0, S_SPINFIRE4}, // S_SPINFIRE3
-	{SPR_SFLM, FF_FULLBRIGHT+3, 2, {NULL}, 0, 0, S_SPINFIRE5}, // S_SPINFIRE4
-	{SPR_SFLM, FF_FULLBRIGHT+4, 2, {NULL}, 0, 0, S_SPINFIRE6}, // S_SPINFIRE5
-	{SPR_SFLM, FF_FULLBRIGHT+5, 2, {NULL}, 0, 0, S_SPINFIRE1}, // S_SPINFIRE6
+	{SPR_SFLM, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_SPINFIRE3}, // S_SPINFIRE2
+	{SPR_SFLM, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_SPINFIRE4}, // S_SPINFIRE3
+	{SPR_SFLM, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_SPINFIRE5}, // S_SPINFIRE4
+	{SPR_SFLM, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_SPINFIRE6}, // S_SPINFIRE5
+	{SPR_SFLM, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_SPINFIRE1}, // S_SPINFIRE6
 
 	// Floor Spike
 	{SPR_USPK, 0,-1, {A_SpikeRetract}, 1, 0, S_SPIKE2}, // S_SPIKE1 -- Fully extended
@@ -1372,7 +1375,7 @@ state_t states[NUMSTATES] =
 
 	{SPR_TORP, 0, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_TORPEDO}, // S_TORPEDO
 
-	{SPR_ENRG, FF_FULLBRIGHT|(tr_trans30<<FF_TRANSSHIFT), 1, {NULL}, 0, 0, S_ENERGYBALL2}, // S_ENERGYBALL1
+	{SPR_ENRG, FF_FULLBRIGHT|FF_TRANS30, 1, {NULL}, 0, 0, S_ENERGYBALL2}, // S_ENERGYBALL1
 	{SPR_NULL, 0, 1, {NULL}, 0, 0, S_ENERGYBALL1}, // S_ENERGYBALL2
 
 	// Skim Mine (also dropped by Jetty-Syn bomber)
@@ -1384,11 +1387,11 @@ state_t states[NUMSTATES] =
 
 	// Jetty-Syn Bullet
 	{SPR_JBUL, FF_FULLBRIGHT,   1, {NULL}, 0, 0, S_JETBULLET2}, // S_JETBULLET1
-	{SPR_JBUL, FF_FULLBRIGHT+1, 1, {NULL}, 0, 0, S_JETBULLET1}, // S_JETBULLET2
+	{SPR_JBUL, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_JETBULLET1}, // S_JETBULLET2
 
 	{SPR_TRLS, FF_FULLBRIGHT,   1, {NULL}, 0, 0, S_TURRETLASER},          // S_TURRETLASER
-	{SPR_TRLS, FF_FULLBRIGHT+1, 2, {NULL}, 0, 0, S_TURRETLASEREXPLODE2},  // S_TURRETLASEREXPLODE1
-	{SPR_TRLS, FF_FULLBRIGHT+2, 2, {NULL}, 0, 0, S_NULL},                 // S_TURRETLASEREXPLODE2
+	{SPR_TRLS, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_TURRETLASEREXPLODE2},  // S_TURRETLASEREXPLODE1
+	{SPR_TRLS, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_NULL},                 // S_TURRETLASEREXPLODE2
 
 	{SPR_CBLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CANNONBALL1
 
@@ -1396,7 +1399,12 @@ state_t states[NUMSTATES] =
 	{SPR_AROW, 1, 1, {A_ArrowCheck}, 0, 0, S_ARROWUP},   // S_ARROWUP
 	{SPR_AROW, 2, 1, {A_ArrowCheck}, 0, 0, S_ARROWDOWN}, // S_ARROWDOWN
 
-	{SPR_NULL, 0, 1, {NULL}, 0, 0, S_SPINFIRE1}, // S_DEMONFIRE
+	{SPR_CFIR, FF_FULLBRIGHT,   2, {NULL}, 0, 0, S_DEMONFIRE2}, // S_DEMONFIRE1
+	{SPR_CFIR, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_DEMONFIRE3}, // S_DEMONFIRE2
+	{SPR_CFIR, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DEMONFIRE4}, // S_DEMONFIRE3
+	{SPR_CFIR, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_DEMONFIRE5}, // S_DEMONFIRE4
+	{SPR_CFIR, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_DEMONFIRE6}, // S_DEMONFIRE5
+	{SPR_CFIR, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_DEMONFIRE1}, // S_DEMONFIRE6
 
 	// GFZ Flower
 	{SPR_FWR1, 0, 14, {NULL}, 0, 0, S_GFZFLOWERA2}, // S_GFZFLOWERA
@@ -1430,13 +1438,13 @@ state_t states[NUMSTATES] =
 	{SPR_SEWE, 5, 5, {NULL}, 0, 0, S_SEAWEED1}, // S_SEAWEED6
 
 	// Dripping water
-	{SPR_NULL, 0, 3*TICRATE, {NULL},                  0, 0, S_DRIPA2}, // S_DRIPA1
-	{SPR_DRIP, 0,         2, {NULL},                  0, 0, S_DRIPA3}, // S_DRIPA2
-	{SPR_DRIP, 1,         2, {NULL},                  0, 0, S_DRIPA4}, // S_DRIPA3
-	{SPR_DRIP, 2,         2, {A_SpawnObjectRelative}, 0, MT_WATERDROP, S_DRIPA1}, // S_DRIPA4
-	{SPR_DRIP, 3,        -1, {NULL},                  0, 0, S_DRIPB1}, // S_DRIPB1
-	{SPR_DRIP, 4,         1, {NULL},                  0, 0, S_DRIPC2}, // S_DRIPC1
-	{SPR_DRIP, 5,         1, {NULL},                  0, 0,   S_NULL}, // S_DRIPC2
+	{SPR_NULL, FF_TRANS30  , 3*TICRATE, {NULL},                  0, 0, S_DRIPA2}, // S_DRIPA1
+	{SPR_DRIP, FF_TRANS30  ,         2, {NULL},                  0, 0, S_DRIPA3}, // S_DRIPA2
+	{SPR_DRIP, FF_TRANS30|1,         2, {NULL},                  0, 0, S_DRIPA4}, // S_DRIPA3
+	{SPR_DRIP, FF_TRANS30|2,         2, {A_SpawnObjectRelative}, 0, MT_WATERDROP, S_DRIPA1}, // S_DRIPA4
+	{SPR_DRIP, FF_TRANS30|3,        -1, {NULL},                  0, 0, S_DRIPB1}, // S_DRIPB1
+	{SPR_DRIP, FF_TRANS30|4,         1, {NULL},                  0, 0, S_DRIPC2}, // S_DRIPC1
+	{SPR_DRIP, FF_TRANS30|5,         1, {NULL},                  0, 0,   S_NULL}, // S_DRIPC2
 
 	// Coral 1
 	{SPR_CRL1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL1
@@ -1448,16 +1456,16 @@ state_t states[NUMSTATES] =
 	{SPR_CRL3, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORAL3
 
 	// Blue Crystal
-	{SPR_BCRY, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUECRYSTAL1
+	{SPR_BCRY, FF_TRANS30, -1, {NULL}, 0, 0, S_NULL}, // S_BLUECRYSTAL1
 
 	// CEZ Chain
 	{SPR_CHAN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZCHAIN
 
 	// Flame
-	{SPR_FLAM, FF_FULLBRIGHT,   3, {NULL}, 0, 0, S_FLAME2}, // S_FLAME1
-	{SPR_FLAM, FF_FULLBRIGHT+1, 3, {NULL}, 0, 0, S_FLAME3}, // S_FLAME2
-	{SPR_FLAM, FF_FULLBRIGHT+2, 3, {NULL}, 0, 0, S_FLAME4}, // S_FLAME3
-	{SPR_FLAM, FF_FULLBRIGHT+3, 3, {NULL}, 0, 0, S_FLAME1}, // S_FLAME4
+	{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50,   3, {NULL}, 0, 0, S_FLAME2}, // S_FLAME1
+	{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50|1, 3, {NULL}, 0, 0, S_FLAME3}, // S_FLAME2
+	{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50|2, 3, {NULL}, 0, 0, S_FLAME4}, // S_FLAME3
+	{SPR_FLAM, FF_FULLBRIGHT|FF_TRANS50|3, 3, {NULL}, 0, 0, S_FLAME1}, // S_FLAME4
 
 	// Eggman statue
 	{SPR_ESTA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGSTATUE1
@@ -1513,9 +1521,9 @@ state_t states[NUMSTATES] =
 	{SPR_NULL, 0, 2*TICRATE, {NULL},             0, 0, S_FLAMEJETSTART}, // S_FLAMEJETSTND
 	{SPR_NULL, 0, 3*TICRATE, {A_ToggleFlameJet}, 0, 0,  S_FLAMEJETSTOP}, // S_FLAMEJETSTART
 	{SPR_NULL, 0,         1, {A_ToggleFlameJet}, 0, 0,  S_FLAMEJETSTND}, // S_FLAMEJETSTOP
-	{SPR_FLME, 0,         4, {NULL}, 0, 0, S_FLAMEJETFLAME2}, // S_FLAMEJETFLAME1
-	{SPR_FLME, 1,         5, {NULL}, 0, 0, S_FLAMEJETFLAME3}, // S_FLAMEJETFLAME2
-	{SPR_FLME, 2,        11, {NULL}, 0, 0,           S_NULL}, // S_FLAMEJETFLAME3
+	{SPR_FLME, FF_TRANS50  ,  4, {NULL}, 0, 0, S_FLAMEJETFLAME2}, // S_FLAMEJETFLAME1
+	{SPR_FLME, FF_TRANS60|1,  5, {NULL}, 0, 0, S_FLAMEJETFLAME3}, // S_FLAMEJETFLAME2
+	{SPR_FLME, FF_TRANS70|2, 11, {NULL}, 0, 0,           S_NULL}, // S_FLAMEJETFLAME3
 
 	// Spinning flame jets
 	// A: Counter-clockwise
@@ -1549,12 +1557,12 @@ state_t states[NUMSTATES] =
 	{SPR_NULL, 0, 1, {A_CapeChase}, 0, (64<<16), S_FJSPINHELPERB3}, // S_FJSPINHELPERB3
 
 	// Blade's flame
-	{SPR_DFLM, FF_FULLBRIGHT|(tr_trans40<<FF_TRANSSHIFT)|1, 1, {A_MoveRelative}, 0, 5, S_FLAMEJETFLAMEB2}, // S_FLAMEJETFLAMEB1
-	{SPR_DFLM, FF_FULLBRIGHT|(tr_trans40<<FF_TRANSSHIFT)|2, 1, {A_MoveRelative}, 0, 7, S_FLAMEJETFLAMEB3}, // S_FLAMEJETFLAMEB2
-	{SPR_DFLM, FF_FULLBRIGHT|(tr_trans40<<FF_TRANSSHIFT)|3,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB4}, // S_FLAMEJETFLAMEB3
-	{SPR_DFLM, FF_FULLBRIGHT|(tr_trans40<<FF_TRANSSHIFT)|4,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB5}, // S_FLAMEJETFLAMEB4
-	{SPR_DFLM, FF_FULLBRIGHT|(tr_trans40<<FF_TRANSSHIFT)|5,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB6}, // S_FLAMEJETFLAMEB5
-	{SPR_DFLM, FF_FULLBRIGHT|(tr_trans40<<FF_TRANSSHIFT)|6,12, {NULL}, 0, 0, S_NULL}, // S_FLAMEJETFLAMEB6
+	{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|1, 1, {A_MoveRelative}, 0, 5, S_FLAMEJETFLAMEB2}, // S_FLAMEJETFLAMEB1
+	{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|2, 1, {A_MoveRelative}, 0, 7, S_FLAMEJETFLAMEB3}, // S_FLAMEJETFLAMEB2
+	{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|3,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB4}, // S_FLAMEJETFLAMEB3
+	{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|4,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB5}, // S_FLAMEJETFLAMEB4
+	{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|5,24, {NULL}, 0, 0, S_FLAMEJETFLAMEB6}, // S_FLAMEJETFLAMEB5
+	{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|6,12, {NULL}, 0, 0, S_NULL}, // S_FLAMEJETFLAMEB6
 
 	// Trapgoyles
 	{SPR_GARG, 0, 67, {NULL},       0, 0, S_TRAPGOYLE_CHECK},  // S_TRAPGOYLE
@@ -1585,10 +1593,10 @@ state_t states[NUMSTATES] =
 
 	// Target/Red Crystal
 	{SPR_RCRY,               0, -1, {NULL},                  0, 0, S_TARGET_IDLE},  // S_TARGET_IDLE
-	{SPR_RCRY, FF_FULLBRIGHT+1,  0, {A_PlaySound},           sfx_ding, 1, S_TARGET_HIT2},  // S_TARGET_HIT1
-	{SPR_RCRY, FF_FULLBRIGHT+1, 45, {A_SetObjectFlags},      MF_PUSHABLE, 2, S_TARGET_RESPAWN},  // S_TARGET_HIT2
+	{SPR_RCRY, FF_FULLBRIGHT|1,  0, {A_PlaySound},           sfx_ding, 1, S_TARGET_HIT2},  // S_TARGET_HIT1
+	{SPR_RCRY, FF_FULLBRIGHT|1, 45, {A_SetObjectFlags},      MF_PUSHABLE, 2, S_TARGET_RESPAWN},  // S_TARGET_HIT2
 	{SPR_RCRY,               1,  0, {A_SpawnObjectRelative}, 0, MT_TARGET, S_NULL},  // S_TARGET_RESPAWN
-	{SPR_RCRY, FF_FULLBRIGHT+1, -1, {A_SetObjectFlags},      MF_PUSHABLE, 1, S_TARGET_ALLDONE},  // S_TARGET_ALLDONE
+	{SPR_RCRY, FF_FULLBRIGHT|1, -1, {A_SetObjectFlags},      MF_PUSHABLE, 1, S_TARGET_ALLDONE},  // S_TARGET_ALLDONE
 
 	// Stalagmites
 	{SPR_STLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_STG0
@@ -1657,142 +1665,142 @@ state_t states[NUMSTATES] =
 
 	// Disco ball
 	{SPR_DBAL, FF_FULLBRIGHT,   5, {NULL}, 0, 0, S_DBALL2}, // S_DBALL1
-	{SPR_DBAL, FF_FULLBRIGHT+1, 5, {NULL}, 0, 0, S_DBALL3}, // S_DBALL2
-	{SPR_DBAL, FF_FULLBRIGHT+2, 5, {NULL}, 0, 0, S_DBALL4}, // S_DBALL3
-	{SPR_DBAL, FF_FULLBRIGHT+3, 5, {NULL}, 0, 0, S_DBALL5}, // S_DBALL4
-	{SPR_DBAL, FF_FULLBRIGHT+4, 5, {NULL}, 0, 0, S_DBALL6}, // S_DBALL5
-	{SPR_DBAL, FF_FULLBRIGHT+5, 5, {NULL}, 0, 0, S_DBALL1}, // S_DBALL6
+	{SPR_DBAL, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_DBALL3}, // S_DBALL2
+	{SPR_DBAL, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_DBALL4}, // S_DBALL3
+	{SPR_DBAL, FF_FULLBRIGHT|3, 5, {NULL}, 0, 0, S_DBALL5}, // S_DBALL4
+	{SPR_DBAL, FF_FULLBRIGHT|4, 5, {NULL}, 0, 0, S_DBALL6}, // S_DBALL5
+	{SPR_DBAL, FF_FULLBRIGHT|5, 5, {NULL}, 0, 0, S_DBALL1}, // S_DBALL6
 
 	{SPR_ESTA, 1, -1, {NULL}, 0, 0, S_NULL}, // S_EGGSTATUE2
 
 	// Shield Orb
-	{SPR_ARMA,  0, 2, {NULL}, 0, 0, S_ARMA2 }, // S_ARMA1
-	{SPR_ARMA,  1, 2, {NULL}, 0, 0, S_ARMA3 }, // S_ARMA2
-	{SPR_ARMA,  2, 2, {NULL}, 0, 0, S_ARMA4 }, // S_ARMA3
-	{SPR_ARMA,  3, 2, {NULL}, 0, 0, S_ARMA5 }, // S_ARMA4
-	{SPR_ARMA,  4, 2, {NULL}, 0, 0, S_ARMA6 }, // S_ARMA5
-	{SPR_ARMA,  5, 2, {NULL}, 0, 0, S_ARMA7 }, // S_ARMA6
-	{SPR_ARMA,  6, 2, {NULL}, 0, 0, S_ARMA8 }, // S_ARMA7
-	{SPR_ARMA,  7, 2, {NULL}, 0, 0, S_ARMA9 }, // S_ARMA8
-	{SPR_ARMA,  8, 2, {NULL}, 0, 0, S_ARMA10}, // S_ARMA9
-	{SPR_ARMA,  9, 2, {NULL}, 0, 0, S_ARMA11}, // S_ARMA10
-	{SPR_ARMA, 10, 2, {NULL}, 0, 0, S_ARMA12}, // S_ARMA11
-	{SPR_ARMA, 11, 2, {NULL}, 0, 0, S_ARMA13}, // S_ARMA12
-	{SPR_ARMA, 12, 2, {NULL}, 0, 0, S_ARMA14}, // S_ARMA13
-	{SPR_ARMA, 13, 2, {NULL}, 0, 0, S_ARMA15}, // S_ARMA14
-	{SPR_ARMA, 14, 2, {NULL}, 0, 0, S_ARMA16}, // S_ARMA15
-	{SPR_ARMA, 15, 2, {NULL}, 0, 0, S_ARMA1 }, // S_ARMA16
-
-	{SPR_ARMF,  0+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF2 }, // S_ARMF1
-	{SPR_ARMF,  1+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF3 }, // S_ARMF2
-	{SPR_ARMF,  2+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF4 }, // S_ARMF3
-	{SPR_ARMF,  3+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF5 }, // S_ARMF4
-	{SPR_ARMF,  4+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF6 }, // S_ARMF5
-	{SPR_ARMF,  5+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF7 }, // S_ARMF6
-	{SPR_ARMF,  6+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF8 }, // S_ARMF7
-	{SPR_ARMF,  7+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF9 }, // S_ARMF8
-	{SPR_ARMF,  8+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF10}, // S_ARMF9
-	{SPR_ARMF,  9+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF11}, // S_ARMF10
-	{SPR_ARMF, 10+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF12}, // S_ARMF11
-	{SPR_ARMF, 11+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF13}, // S_ARMF12
-	{SPR_ARMF, 12+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF14}, // S_ARMF13
-	{SPR_ARMF, 13+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF15}, // S_ARMF14
-	{SPR_ARMF, 14+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF16}, // S_ARMF15
-	{SPR_ARMF, 15+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ARMF1 }, // S_ARMF16
-
-	{SPR_ARMB,  0+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB2 }, // S_ARMB1
-	{SPR_ARMB,  1+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB3 }, // S_ARMB2
-	{SPR_ARMB,  2+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB4 }, // S_ARMB3
-	{SPR_ARMB,  3+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB5 }, // S_ARMB4
-	{SPR_ARMB,  4+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB6 }, // S_ARMB5
-	{SPR_ARMB,  5+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB7 }, // S_ARMB6
-	{SPR_ARMB,  6+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB8 }, // S_ARMB7
-	{SPR_ARMB,  7+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB9 }, // S_ARMB8
-	{SPR_ARMB,  8+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB10}, // S_ARMB9
-	{SPR_ARMB,  9+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB11}, // S_ARMB10
-	{SPR_ARMB, 10+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB12}, // S_ARMB11
-	{SPR_ARMB, 11+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB13}, // S_ARMB12
-	{SPR_ARMB, 12+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB14}, // S_ARMB13
-	{SPR_ARMB, 13+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB15}, // S_ARMB14
-	{SPR_ARMB, 14+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB16}, // S_ARMB15
-	{SPR_ARMB, 15+FF_FULLBRIGHT, 3, {NULL}, 1, 0, S_ARMB1 }, // S_ARMB16
-
-	{SPR_WIND, 0, 2, {NULL}, 0, 0, S_WIND2}, // S_WIND1
-	{SPR_WIND, 1, 2, {NULL}, 0, 0, S_WIND3}, // S_WIND2
-	{SPR_WIND, 2, 2, {NULL}, 0, 0, S_WIND4}, // S_WIND3
-	{SPR_WIND, 3, 2, {NULL}, 0, 0, S_WIND5}, // S_WIND4
-	{SPR_WIND, 4, 2, {NULL}, 0, 0, S_WIND6}, // S_WIND5
-	{SPR_WIND, 5, 2, {NULL}, 0, 0, S_WIND7}, // S_WIND6
-	{SPR_WIND, 6, 2, {NULL}, 0, 0, S_WIND8}, // S_WIND7
-	{SPR_WIND, 7, 2, {NULL}, 0, 0, S_WIND1}, // S_WIND8
-
-	{SPR_MAGN,  0+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN2 }, // S_MAGN1
-	{SPR_MAGN,  1+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN3 }, // S_MAGN2
-	{SPR_MAGN,  2+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN4 }, // S_MAGN3
-	{SPR_MAGN,  3+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN5 }, // S_MAGN4
-	{SPR_MAGN,  4+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN6 }, // S_MAGN5
-	{SPR_MAGN,  5+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN7 }, // S_MAGN6
-	{SPR_MAGN,  6+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN8 }, // S_MAGN7
-	{SPR_MAGN,  7+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN9 }, // S_MAGN8
-	{SPR_MAGN,  8+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN10}, // S_MAGN9
-	{SPR_MAGN,  9+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN11}, // S_MAGN10
-	{SPR_MAGN, 10+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN12}, // S_MAGN11
-	{SPR_MAGN, 11+FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_MAGN1 }, // S_MAGN12
-
-	{SPR_FORC, 0, 3, {NULL}, 0, 0, S_FORC2 }, // S_FORC1
-	{SPR_FORC, 1, 3, {NULL}, 0, 0, S_FORC3 }, // S_FORC2
-	{SPR_FORC, 2, 3, {NULL}, 0, 0, S_FORC4 }, // S_FORC3
-	{SPR_FORC, 3, 3, {NULL}, 0, 0, S_FORC5 }, // S_FORC4
-	{SPR_FORC, 4, 3, {NULL}, 0, 0, S_FORC6 }, // S_FORC5
-	{SPR_FORC, 5, 3, {NULL}, 0, 0, S_FORC7 }, // S_FORC6
-	{SPR_FORC, 6, 3, {NULL}, 0, 0, S_FORC8 }, // S_FORC7
-	{SPR_FORC, 7, 3, {NULL}, 0, 0, S_FORC9 }, // S_FORC8
-	{SPR_FORC, 8, 3, {NULL}, 0, 0, S_FORC10}, // S_FORC9
-	{SPR_FORC, 9, 3, {NULL}, 0, 0, S_FORC1 }, // S_FORC10
-
-	{SPR_FORC,10, 3, {NULL}, 0, 0, S_FORC12}, // S_FORC11
-	{SPR_FORC,11, 3, {NULL}, 0, 0, S_FORC13}, // S_FORC12
-	{SPR_FORC,12, 3, {NULL}, 0, 0, S_FORC14}, // S_FORC13
-	{SPR_FORC,13, 3, {NULL}, 0, 0, S_FORC15}, // S_FORC14
-	{SPR_FORC,14, 3, {NULL}, 0, 0, S_FORC16}, // S_FORC15
-	{SPR_FORC,15, 3, {NULL}, 0, 0, S_FORC17}, // S_FORC16
-	{SPR_FORC,16, 3, {NULL}, 0, 0, S_FORC18}, // S_FORC17
-	{SPR_FORC,17, 3, {NULL}, 0, 0, S_FORC19}, // S_FORC18
-	{SPR_FORC,18, 3, {NULL}, 0, 0, S_FORC20}, // S_FORC19
-	{SPR_FORC,19, 3, {NULL}, 0, 0, S_FORC11}, // S_FORC20
-
-	{SPR_ELEM,  0, 4, {NULL}, 0, 0, S_ELEM2 }, // S_ELEM1
-	{SPR_ELEM,  1, 4, {NULL}, 0, 0, S_ELEM3 }, // S_ELEM2
-	{SPR_ELEM,  2, 4, {NULL}, 0, 0, S_ELEM4 }, // S_ELEM3
-	{SPR_ELEM,  3, 4, {NULL}, 0, 0, S_ELEM5 }, // S_ELEM4
-	{SPR_ELEM,  4, 4, {NULL}, 0, 0, S_ELEM6 }, // S_ELEM5
-	{SPR_ELEM,  5, 4, {NULL}, 0, 0, S_ELEM7 }, // S_ELEM6
-	{SPR_ELEM,  6, 4, {NULL}, 0, 0, S_ELEM8 }, // S_ELEM7
-	{SPR_ELEM,  7, 4, {NULL}, 0, 0, S_ELEM9 }, // S_ELEM8
-	{SPR_ELEM,  8, 4, {NULL}, 0, 0, S_ELEM10}, // S_ELEM9
-	{SPR_ELEM,  9, 4, {NULL}, 0, 0, S_ELEM11}, // S_ELEM10
-	{SPR_ELEM, 10, 4, {NULL}, 0, 0, S_ELEM12}, // S_ELEM11
-	{SPR_ELEM, 11, 4, {NULL}, 0, 0, S_ELEM1 }, // S_ELEM12
-
-	{SPR_ELEM, 12+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ELEMF2}, // S_ELEMF1
-	{SPR_ELEM, 13+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ELEMF3}, // S_ELEMF2
-	{SPR_ELEM, 14+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ELEMF4}, // S_ELEMF3
-	{SPR_ELEM, 15+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ELEMF5}, // S_ELEMF4
-	{SPR_ELEM, 16+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ELEMF6}, // S_ELEMF5
-	{SPR_ELEM, 17+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ELEMF7}, // S_ELEMF6
-	{SPR_ELEM, 18+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ELEMF8}, // S_ELEMF7
-	{SPR_ELEM, 19+FF_FULLBRIGHT, 3, {NULL}, 0, 0, S_ELEMF1}, // S_ELEMF8
-
-	{SPR_PITY, 0, 1, {NULL}, 0, 0, S_PITY2 }, // S_PITY1
-	{SPR_PITY, 1, 1, {NULL}, 0, 0, S_PITY3 }, // S_PITY2
-	{SPR_PITY, 0, 1, {NULL}, 0, 0, S_PITY4 }, // S_PITY3
-	{SPR_PITY, 2, 1, {NULL}, 0, 0, S_PITY5 }, // S_PITY4
-	{SPR_PITY, 0, 1, {NULL}, 0, 0, S_PITY6 }, // S_PITY5
-	{SPR_PITY, 3, 1, {NULL}, 0, 0, S_PITY7 }, // S_PITY6
-	{SPR_PITY, 0, 1, {NULL}, 0, 0, S_PITY8 }, // S_PITY7
-	{SPR_PITY, 4, 1, {NULL}, 0, 0, S_PITY9 }, // S_PITY8
-	{SPR_PITY, 0, 1, {NULL}, 0, 0, S_PITY10}, // S_PITY9
-	{SPR_PITY, 5, 1, {NULL}, 0, 0, S_PITY1 }, // S_PITY10
+	{SPR_ARMA, FF_TRANS40   , 2, {NULL}, 0, 0, S_ARMA2 }, // S_ARMA1
+	{SPR_ARMA, FF_TRANS40| 1, 2, {NULL}, 0, 0, S_ARMA3 }, // S_ARMA2
+	{SPR_ARMA, FF_TRANS40| 2, 2, {NULL}, 0, 0, S_ARMA4 }, // S_ARMA3
+	{SPR_ARMA, FF_TRANS40| 3, 2, {NULL}, 0, 0, S_ARMA5 }, // S_ARMA4
+	{SPR_ARMA, FF_TRANS40| 4, 2, {NULL}, 0, 0, S_ARMA6 }, // S_ARMA5
+	{SPR_ARMA, FF_TRANS40| 5, 2, {NULL}, 0, 0, S_ARMA7 }, // S_ARMA6
+	{SPR_ARMA, FF_TRANS40| 6, 2, {NULL}, 0, 0, S_ARMA8 }, // S_ARMA7
+	{SPR_ARMA, FF_TRANS40| 7, 2, {NULL}, 0, 0, S_ARMA9 }, // S_ARMA8
+	{SPR_ARMA, FF_TRANS40| 8, 2, {NULL}, 0, 0, S_ARMA10}, // S_ARMA9
+	{SPR_ARMA, FF_TRANS40| 9, 2, {NULL}, 0, 0, S_ARMA11}, // S_ARMA10
+	{SPR_ARMA, FF_TRANS40|10, 2, {NULL}, 0, 0, S_ARMA12}, // S_ARMA11
+	{SPR_ARMA, FF_TRANS40|11, 2, {NULL}, 0, 0, S_ARMA13}, // S_ARMA12
+	{SPR_ARMA, FF_TRANS40|12, 2, {NULL}, 0, 0, S_ARMA14}, // S_ARMA13
+	{SPR_ARMA, FF_TRANS40|13, 2, {NULL}, 0, 0, S_ARMA15}, // S_ARMA14
+	{SPR_ARMA, FF_TRANS40|14, 2, {NULL}, 0, 0, S_ARMA16}, // S_ARMA15
+	{SPR_ARMA, FF_TRANS40|15, 2, {NULL}, 0, 0, S_ARMA1 }, // S_ARMA16
+
+	{SPR_ARMF, FF_FULLBRIGHT   , 3, {NULL}, 0, 0, S_ARMF2 }, // S_ARMF1
+	{SPR_ARMF, FF_FULLBRIGHT| 1, 3, {NULL}, 0, 0, S_ARMF3 }, // S_ARMF2
+	{SPR_ARMF, FF_FULLBRIGHT| 2, 3, {NULL}, 0, 0, S_ARMF4 }, // S_ARMF3
+	{SPR_ARMF, FF_FULLBRIGHT| 3, 3, {NULL}, 0, 0, S_ARMF5 }, // S_ARMF4
+	{SPR_ARMF, FF_FULLBRIGHT| 4, 3, {NULL}, 0, 0, S_ARMF6 }, // S_ARMF5
+	{SPR_ARMF, FF_FULLBRIGHT| 5, 3, {NULL}, 0, 0, S_ARMF7 }, // S_ARMF6
+	{SPR_ARMF, FF_FULLBRIGHT| 6, 3, {NULL}, 0, 0, S_ARMF8 }, // S_ARMF7
+	{SPR_ARMF, FF_FULLBRIGHT| 7, 3, {NULL}, 0, 0, S_ARMF9 }, // S_ARMF8
+	{SPR_ARMF, FF_FULLBRIGHT| 8, 3, {NULL}, 0, 0, S_ARMF10}, // S_ARMF9
+	{SPR_ARMF, FF_FULLBRIGHT| 9, 3, {NULL}, 0, 0, S_ARMF11}, // S_ARMF10
+	{SPR_ARMF, FF_FULLBRIGHT|10, 3, {NULL}, 0, 0, S_ARMF12}, // S_ARMF11
+	{SPR_ARMF, FF_FULLBRIGHT|11, 3, {NULL}, 0, 0, S_ARMF13}, // S_ARMF12
+	{SPR_ARMF, FF_FULLBRIGHT|12, 3, {NULL}, 0, 0, S_ARMF14}, // S_ARMF13
+	{SPR_ARMF, FF_FULLBRIGHT|13, 3, {NULL}, 0, 0, S_ARMF15}, // S_ARMF14
+	{SPR_ARMF, FF_FULLBRIGHT|14, 3, {NULL}, 0, 0, S_ARMF16}, // S_ARMF15
+	{SPR_ARMF, FF_FULLBRIGHT|15, 3, {NULL}, 0, 0, S_ARMF1 }, // S_ARMF16
+
+	{SPR_ARMB, FF_FULLBRIGHT| 0, 3, {NULL}, 1, 0, S_ARMB2 }, // S_ARMB1
+	{SPR_ARMB, FF_FULLBRIGHT| 1, 3, {NULL}, 1, 0, S_ARMB3 }, // S_ARMB2
+	{SPR_ARMB, FF_FULLBRIGHT| 2, 3, {NULL}, 1, 0, S_ARMB4 }, // S_ARMB3
+	{SPR_ARMB, FF_FULLBRIGHT| 3, 3, {NULL}, 1, 0, S_ARMB5 }, // S_ARMB4
+	{SPR_ARMB, FF_FULLBRIGHT| 4, 3, {NULL}, 1, 0, S_ARMB6 }, // S_ARMB5
+	{SPR_ARMB, FF_FULLBRIGHT| 5, 3, {NULL}, 1, 0, S_ARMB7 }, // S_ARMB6
+	{SPR_ARMB, FF_FULLBRIGHT| 6, 3, {NULL}, 1, 0, S_ARMB8 }, // S_ARMB7
+	{SPR_ARMB, FF_FULLBRIGHT| 7, 3, {NULL}, 1, 0, S_ARMB9 }, // S_ARMB8
+	{SPR_ARMB, FF_FULLBRIGHT| 8, 3, {NULL}, 1, 0, S_ARMB10}, // S_ARMB9
+	{SPR_ARMB, FF_FULLBRIGHT| 9, 3, {NULL}, 1, 0, S_ARMB11}, // S_ARMB10
+	{SPR_ARMB, FF_FULLBRIGHT|10, 3, {NULL}, 1, 0, S_ARMB12}, // S_ARMB11
+	{SPR_ARMB, FF_FULLBRIGHT|11, 3, {NULL}, 1, 0, S_ARMB13}, // S_ARMB12
+	{SPR_ARMB, FF_FULLBRIGHT|12, 3, {NULL}, 1, 0, S_ARMB14}, // S_ARMB13
+	{SPR_ARMB, FF_FULLBRIGHT|13, 3, {NULL}, 1, 0, S_ARMB15}, // S_ARMB14
+	{SPR_ARMB, FF_FULLBRIGHT|14, 3, {NULL}, 1, 0, S_ARMB16}, // S_ARMB15
+	{SPR_ARMB, FF_FULLBRIGHT|15, 3, {NULL}, 1, 0, S_ARMB1 }, // S_ARMB16
+
+	{SPR_WIND, FF_TRANS70  , 2, {NULL}, 0, 0, S_WIND2}, // S_WIND1
+	{SPR_WIND, FF_TRANS70|1, 2, {NULL}, 0, 0, S_WIND3}, // S_WIND2
+	{SPR_WIND, FF_TRANS70|2, 2, {NULL}, 0, 0, S_WIND4}, // S_WIND3
+	{SPR_WIND, FF_TRANS70|3, 2, {NULL}, 0, 0, S_WIND5}, // S_WIND4
+	{SPR_WIND, FF_TRANS70|4, 2, {NULL}, 0, 0, S_WIND6}, // S_WIND5
+	{SPR_WIND, FF_TRANS70|5, 2, {NULL}, 0, 0, S_WIND7}, // S_WIND6
+	{SPR_WIND, FF_TRANS70|6, 2, {NULL}, 0, 0, S_WIND8}, // S_WIND7
+	{SPR_WIND, FF_TRANS70|7, 2, {NULL}, 0, 0, S_WIND1}, // S_WIND8
+
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40   , 2, {NULL}, 0, 0, S_MAGN2 }, // S_MAGN1
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 1, 2, {NULL}, 0, 0, S_MAGN3 }, // S_MAGN2
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 2, 2, {NULL}, 0, 0, S_MAGN4 }, // S_MAGN3
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 3, 2, {NULL}, 0, 0, S_MAGN5 }, // S_MAGN4
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 4, 2, {NULL}, 0, 0, S_MAGN6 }, // S_MAGN5
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 5, 2, {NULL}, 0, 0, S_MAGN7 }, // S_MAGN6
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 6, 2, {NULL}, 0, 0, S_MAGN8 }, // S_MAGN7
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 7, 2, {NULL}, 0, 0, S_MAGN9 }, // S_MAGN8
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 8, 2, {NULL}, 0, 0, S_MAGN10}, // S_MAGN9
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40| 9, 2, {NULL}, 0, 0, S_MAGN11}, // S_MAGN10
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40|10, 2, {NULL}, 0, 0, S_MAGN12}, // S_MAGN11
+	{SPR_MAGN, FF_FULLBRIGHT|FF_TRANS40|11, 2, {NULL}, 0, 0, S_MAGN1 }, // S_MAGN12
+
+	{SPR_FORC, FF_TRANS50  , 3, {NULL}, 0, 0, S_FORC2 }, // S_FORC1
+	{SPR_FORC, FF_TRANS50|1, 3, {NULL}, 0, 0, S_FORC3 }, // S_FORC2
+	{SPR_FORC, FF_TRANS50|2, 3, {NULL}, 0, 0, S_FORC4 }, // S_FORC3
+	{SPR_FORC, FF_TRANS50|3, 3, {NULL}, 0, 0, S_FORC5 }, // S_FORC4
+	{SPR_FORC, FF_TRANS50|4, 3, {NULL}, 0, 0, S_FORC6 }, // S_FORC5
+	{SPR_FORC, FF_TRANS50|5, 3, {NULL}, 0, 0, S_FORC7 }, // S_FORC6
+	{SPR_FORC, FF_TRANS50|6, 3, {NULL}, 0, 0, S_FORC8 }, // S_FORC7
+	{SPR_FORC, FF_TRANS50|7, 3, {NULL}, 0, 0, S_FORC9 }, // S_FORC8
+	{SPR_FORC, FF_TRANS50|8, 3, {NULL}, 0, 0, S_FORC10}, // S_FORC9
+	{SPR_FORC, FF_TRANS50|9, 3, {NULL}, 0, 0, S_FORC1 }, // S_FORC10
+
+	{SPR_FORC, FF_TRANS50|10, 3, {NULL}, 0, 0, S_FORC12}, // S_FORC11
+	{SPR_FORC, FF_TRANS50|11, 3, {NULL}, 0, 0, S_FORC13}, // S_FORC12
+	{SPR_FORC, FF_TRANS50|12, 3, {NULL}, 0, 0, S_FORC14}, // S_FORC13
+	{SPR_FORC, FF_TRANS50|13, 3, {NULL}, 0, 0, S_FORC15}, // S_FORC14
+	{SPR_FORC, FF_TRANS50|14, 3, {NULL}, 0, 0, S_FORC16}, // S_FORC15
+	{SPR_FORC, FF_TRANS50|15, 3, {NULL}, 0, 0, S_FORC17}, // S_FORC16
+	{SPR_FORC, FF_TRANS50|16, 3, {NULL}, 0, 0, S_FORC18}, // S_FORC17
+	{SPR_FORC, FF_TRANS50|17, 3, {NULL}, 0, 0, S_FORC19}, // S_FORC18
+	{SPR_FORC, FF_TRANS50|18, 3, {NULL}, 0, 0, S_FORC20}, // S_FORC19
+	{SPR_FORC, FF_TRANS50|19, 3, {NULL}, 0, 0, S_FORC11}, // S_FORC20
+
+	{SPR_ELEM, FF_TRANS50   , 4, {NULL}, 0, 0, S_ELEM2 }, // S_ELEM1
+	{SPR_ELEM, FF_TRANS50| 1, 4, {NULL}, 0, 0, S_ELEM3 }, // S_ELEM2
+	{SPR_ELEM, FF_TRANS50| 2, 4, {NULL}, 0, 0, S_ELEM4 }, // S_ELEM3
+	{SPR_ELEM, FF_TRANS50| 3, 4, {NULL}, 0, 0, S_ELEM5 }, // S_ELEM4
+	{SPR_ELEM, FF_TRANS50| 4, 4, {NULL}, 0, 0, S_ELEM6 }, // S_ELEM5
+	{SPR_ELEM, FF_TRANS50| 5, 4, {NULL}, 0, 0, S_ELEM7 }, // S_ELEM6
+	{SPR_ELEM, FF_TRANS50| 6, 4, {NULL}, 0, 0, S_ELEM8 }, // S_ELEM7
+	{SPR_ELEM, FF_TRANS50| 7, 4, {NULL}, 0, 0, S_ELEM9 }, // S_ELEM8
+	{SPR_ELEM, FF_TRANS50| 8, 4, {NULL}, 0, 0, S_ELEM10}, // S_ELEM9
+	{SPR_ELEM, FF_TRANS50| 9, 4, {NULL}, 0, 0, S_ELEM11}, // S_ELEM10
+	{SPR_ELEM, FF_TRANS50|10, 4, {NULL}, 0, 0, S_ELEM12}, // S_ELEM11
+	{SPR_ELEM, FF_TRANS50|11, 4, {NULL}, 0, 0, S_ELEM1 }, // S_ELEM12
+
+	{SPR_ELEM, FF_FULLBRIGHT|12, 3, {NULL}, 0, 0, S_ELEMF2}, // S_ELEMF1
+	{SPR_ELEM, FF_FULLBRIGHT|13, 3, {NULL}, 0, 0, S_ELEMF3}, // S_ELEMF2
+	{SPR_ELEM, FF_FULLBRIGHT|14, 3, {NULL}, 0, 0, S_ELEMF4}, // S_ELEMF3
+	{SPR_ELEM, FF_FULLBRIGHT|15, 3, {NULL}, 0, 0, S_ELEMF5}, // S_ELEMF4
+	{SPR_ELEM, FF_FULLBRIGHT|16, 3, {NULL}, 0, 0, S_ELEMF6}, // S_ELEMF5
+	{SPR_ELEM, FF_FULLBRIGHT|17, 3, {NULL}, 0, 0, S_ELEMF7}, // S_ELEMF6
+	{SPR_ELEM, FF_FULLBRIGHT|18, 3, {NULL}, 0, 0, S_ELEMF8}, // S_ELEMF7
+	{SPR_ELEM, FF_FULLBRIGHT|19, 3, {NULL}, 0, 0, S_ELEMF1}, // S_ELEMF8
+
+	{SPR_PITY, FF_TRANS20  , 1, {NULL}, 0, 0, S_PITY2 }, // S_PITY1
+	{SPR_PITY, FF_TRANS20|1, 1, {NULL}, 0, 0, S_PITY3 }, // S_PITY2
+	{SPR_PITY, FF_TRANS20  , 1, {NULL}, 0, 0, S_PITY4 }, // S_PITY3
+	{SPR_PITY, FF_TRANS20|2, 1, {NULL}, 0, 0, S_PITY5 }, // S_PITY4
+	{SPR_PITY, FF_TRANS20  , 1, {NULL}, 0, 0, S_PITY6 }, // S_PITY5
+	{SPR_PITY, FF_TRANS20|3, 1, {NULL}, 0, 0, S_PITY7 }, // S_PITY6
+	{SPR_PITY, FF_TRANS20  , 1, {NULL}, 0, 0, S_PITY8 }, // S_PITY7
+	{SPR_PITY, FF_TRANS20|4, 1, {NULL}, 0, 0, S_PITY9 }, // S_PITY8
+	{SPR_PITY, FF_TRANS20  , 1, {NULL}, 0, 0, S_PITY10}, // S_PITY9
+	{SPR_PITY, FF_TRANS20|5, 1, {NULL}, 0, 0, S_PITY1 }, // S_PITY10
 
 	// Invincibility Sparkles
 	{SPR_IVSP, 0, 1, {NULL}, 0, 0, S_IVSP2},   // S_IVSP1
@@ -1915,8 +1923,8 @@ state_t states[NUMSTATES] =
 	{SPR_RSPR, 1, 1, {NULL}, 0, 0, S_RDIAG1},   // S_RDIAG8
 
 	// Rain
-	{SPR_RAIN, 0, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1
-	{SPR_RAIN, 0, 1, {NULL}, 0, 0, S_RAIN1}, // S_RAINRETURN
+	{SPR_RAIN, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1
+	{SPR_RAIN, FF_TRANS50, 1, {NULL}, 0, 0, S_RAIN1}, // S_RAINRETURN
 
 	// Snowflake
 	{SPR_SNO1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW1
@@ -1924,61 +1932,61 @@ state_t states[NUMSTATES] =
 	{SPR_SNO1, 2, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW3
 
 	// Water Splish
-	{SPR_SPLH, 0, 2, {NULL}, 0, 0, S_SPLISH2}, // S_SPLISH1
-	{SPR_SPLH, 1, 2, {NULL}, 0, 0, S_SPLISH3}, // S_SPLISH2
-	{SPR_SPLH, 2, 2, {NULL}, 0, 0, S_SPLISH4}, // S_SPLISH3
-	{SPR_SPLH, 3, 2, {NULL}, 0, 0, S_SPLISH5}, // S_SPLISH4
-	{SPR_SPLH, 4, 2, {NULL}, 0, 0, S_SPLISH6}, // S_SPLISH5
-	{SPR_SPLH, 5, 2, {NULL}, 0, 0, S_SPLISH7}, // S_SPLISH6
-	{SPR_SPLH, 6, 2, {NULL}, 0, 0, S_SPLISH8}, // S_SPLISH7
-	{SPR_SPLH, 7, 2, {NULL}, 0, 0, S_SPLISH9}, // S_SPLISH8
-	{SPR_SPLH, 8, 2, {NULL}, 0, 0, S_NULL},    // S_SPLISH9
+	{SPR_SPLH, FF_TRANS50  , 2, {NULL}, 0, 0, S_SPLISH2}, // S_SPLISH1
+	{SPR_SPLH, FF_TRANS50|1, 2, {NULL}, 0, 0, S_SPLISH3}, // S_SPLISH2
+	{SPR_SPLH, FF_TRANS50|2, 2, {NULL}, 0, 0, S_SPLISH4}, // S_SPLISH3
+	{SPR_SPLH, FF_TRANS50|3, 2, {NULL}, 0, 0, S_SPLISH5}, // S_SPLISH4
+	{SPR_SPLH, FF_TRANS50|4, 2, {NULL}, 0, 0, S_SPLISH6}, // S_SPLISH5
+	{SPR_SPLH, FF_TRANS50|5, 2, {NULL}, 0, 0, S_SPLISH7}, // S_SPLISH6
+	{SPR_SPLH, FF_TRANS50|6, 2, {NULL}, 0, 0, S_SPLISH8}, // S_SPLISH7
+	{SPR_SPLH, FF_TRANS50|7, 2, {NULL}, 0, 0, S_SPLISH9}, // S_SPLISH8
+	{SPR_SPLH, FF_TRANS50|8, 2, {NULL}, 0, 0, S_NULL},    // S_SPLISH9
 
 	// Water Splash
-	{SPR_SPLA, 0, 3, {NULL}, 0, 0, S_SPLASH2},    // S_SPLASH1
-	{SPR_SPLA, 1, 3, {NULL}, 0, 0, S_SPLASH3},    // S_SPLASH2
-	{SPR_SPLA, 2, 3, {NULL}, 0, 0, S_RAINRETURN}, // S_SPLASH3
+	{SPR_SPLA, FF_TRANS50  , 3, {NULL}, 0, 0, S_SPLASH2},    // S_SPLASH1
+	{SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3},    // S_SPLASH2
+	{SPR_SPLA, FF_TRANS90|2, 3, {NULL}, 0, 0, S_RAINRETURN}, // S_SPLASH3
 
 	// Smoke
-	{SPR_SMOK, 0, 4, {NULL}, 0, 0, S_SMOKE2}, // S_SMOKE1
-	{SPR_SMOK, 1, 5, {NULL}, 0, 0, S_SMOKE3}, // S_SMOKE2
-	{SPR_SMOK, 2, 6, {NULL}, 0, 0, S_SMOKE4}, // S_SMOKE3
-	{SPR_SMOK, 3, 7, {NULL}, 0, 0, S_SMOKE5}, // S_SMOKE4
-	{SPR_SMOK, 4, 8, {NULL}, 0, 0, S_NULL},   // S_SMOKE5
+	{SPR_SMOK, FF_TRANS50  , 4, {NULL}, 0, 0, S_SMOKE2}, // S_SMOKE1
+	{SPR_SMOK, FF_TRANS50|1, 5, {NULL}, 0, 0, S_SMOKE3}, // S_SMOKE2
+	{SPR_SMOK, FF_TRANS50|2, 6, {NULL}, 0, 0, S_SMOKE4}, // S_SMOKE3
+	{SPR_SMOK, FF_TRANS50|3, 7, {NULL}, 0, 0, S_SMOKE5}, // S_SMOKE4
+	{SPR_SMOK, FF_TRANS50|4, 8, {NULL}, 0, 0, S_NULL},   // S_SMOKE5
 
 	// Bubbles
-	{SPR_BUBP, 0, 1, {A_BubbleRise}, 0, 1024, S_SMALLBUBBLE1},  // S_SMALLBUBBLE
-	{SPR_BUBP, 0, 1, {A_BubbleRise}, 0, 1024, S_SMALLBUBBLE},   // S_SMALLBUBBLE1
-	{SPR_BUBO, 0, 1, {A_BubbleRise}, 0, 1024, S_MEDIUMBUBBLE1}, // S_MEDIUMBUBBLE
-	{SPR_BUBO, 0, 1, {A_BubbleRise}, 0, 1024, S_MEDIUMBUBBLE},  // S_MEDIUMBUBBLE1
+	{SPR_BUBP, FF_TRANS50, 1, {A_BubbleRise}, 0, 1024, S_SMALLBUBBLE1},  // S_SMALLBUBBLE
+	{SPR_BUBP, FF_TRANS50, 1, {A_BubbleRise}, 0, 1024, S_SMALLBUBBLE},   // S_SMALLBUBBLE1
+	{SPR_BUBO, FF_TRANS50, 1, {A_BubbleRise}, 0, 1024, S_MEDIUMBUBBLE1}, // S_MEDIUMBUBBLE
+	{SPR_BUBO, FF_TRANS50, 1, {A_BubbleRise}, 0, 1024, S_MEDIUMBUBBLE},  // S_MEDIUMBUBBLE1
 
 	// Extra Large Bubble (breathable)
-	{SPR_BUBN, FF_FULLBRIGHT, 16, {A_BubbleRise}, 0, 1024, S_EXTRALARGEBUBBLE}, // S_LARGEBUBBLE
-	{SPR_BUBM, FF_FULLBRIGHT, 16, {A_BubbleRise}, 0, 1024, S_EXTRALARGEBUBBLE}, // S_EXTRALARGEBUBBLE
+	{SPR_BUBN, FF_TRANS50|FF_FULLBRIGHT, 16, {A_BubbleRise}, 0, 1024, S_EXTRALARGEBUBBLE}, // S_LARGEBUBBLE
+	{SPR_BUBM, FF_TRANS50|FF_FULLBRIGHT, 16, {A_BubbleRise}, 0, 1024, S_EXTRALARGEBUBBLE}, // S_EXTRALARGEBUBBLE
 
 	// Extra Large Bubble goes POP!
 	{SPR_POPP, 0, 16, {NULL}, 0, 0, S_NULL}, // S_POP1
 
-	{SPR_TFOG, FF_FULLBRIGHT,    2, {NULL}, 0, 0, S_FOG2},  // S_FOG1
-	{SPR_TFOG, FF_FULLBRIGHT+1,  2, {NULL}, 0, 0, S_FOG3},  // S_FOG2
-	{SPR_TFOG, FF_FULLBRIGHT+2,  2, {NULL}, 0, 0, S_FOG4},  // S_FOG3
-	{SPR_TFOG, FF_FULLBRIGHT+3,  2, {NULL}, 0, 0, S_FOG5},  // S_FOG4
-	{SPR_TFOG, FF_FULLBRIGHT+4,  2, {NULL}, 0, 0, S_FOG6},  // S_FOG5
-	{SPR_TFOG, FF_FULLBRIGHT+5,  2, {NULL}, 0, 0, S_FOG7},  // S_FOG6
-	{SPR_TFOG, FF_FULLBRIGHT+6,  2, {NULL}, 0, 0, S_FOG8},  // S_FOG7
-	{SPR_TFOG, FF_FULLBRIGHT+7,  2, {NULL}, 0, 0, S_FOG9},  // S_FOG8
-	{SPR_TFOG, FF_FULLBRIGHT+8,  2, {NULL}, 0, 0, S_FOG10}, // S_FOG9
-	{SPR_TFOG, FF_FULLBRIGHT+9,  2, {NULL}, 0, 0, S_FOG11}, // S_FOG10
-	{SPR_TFOG, FF_FULLBRIGHT+10, 2, {NULL}, 0, 0, S_FOG12}, // S_FOG11
-	{SPR_TFOG, FF_FULLBRIGHT+11, 2, {NULL}, 0, 0, S_FOG13}, // S_FOG12
-	{SPR_TFOG, FF_FULLBRIGHT+12, 2, {NULL}, 0, 0, S_FOG14}, // S_FOG13
-	{SPR_TFOG, FF_FULLBRIGHT+13, 2, {NULL}, 0, 0, S_NULL},  // S_FOG14
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50,    2, {NULL}, 0, 0, S_FOG2},  // S_FOG1
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|1,  2, {NULL}, 0, 0, S_FOG3},  // S_FOG2
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|2,  2, {NULL}, 0, 0, S_FOG4},  // S_FOG3
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|3,  2, {NULL}, 0, 0, S_FOG5},  // S_FOG4
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|4,  2, {NULL}, 0, 0, S_FOG6},  // S_FOG5
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|5,  2, {NULL}, 0, 0, S_FOG7},  // S_FOG6
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|6,  2, {NULL}, 0, 0, S_FOG8},  // S_FOG7
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|7,  2, {NULL}, 0, 0, S_FOG9},  // S_FOG8
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|8,  2, {NULL}, 0, 0, S_FOG10}, // S_FOG9
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|9,  2, {NULL}, 0, 0, S_FOG11}, // S_FOG10
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|10, 2, {NULL}, 0, 0, S_FOG12}, // S_FOG11
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|11, 2, {NULL}, 0, 0, S_FOG13}, // S_FOG12
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|12, 2, {NULL}, 0, 0, S_FOG14}, // S_FOG13
+	{SPR_TFOG, FF_FULLBRIGHT|FF_TRANS50|13, 2, {NULL}, 0, 0, S_NULL},  // S_FOG14
 
 	// Flower Seed
 	{SPR_SEED, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_SEED
 
 	// Particle sprite
-	{SPR_PRTL, FF_FULLBRIGHT, 2*TICRATE, {NULL}, 0, 0, S_NULL}, // S_PARTICLE
+	{SPR_PRTL, FF_FULLBRIGHT|FF_TRANS70, 2*TICRATE, {NULL}, 0, 0, S_NULL}, // S_PARTICLE
 	{SPR_NULL,     0,         1, {A_ParticleSpawn}, 0, 0, S_PARTICLEGEN}, // S_PARTICLEGEN
 
 	{SPR_SCOR, 0, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRA  - 100
@@ -2011,12 +2019,12 @@ state_t states[NUMSTATES] =
 
 	// Red Rings (thrown)
 	{SPR_RRNG, FF_FULLBRIGHT,   1, {A_ThrownRing}, 0, 0, S_RRNG2}, // S_RRNG1
-	{SPR_RRNG, FF_FULLBRIGHT+1, 1, {A_ThrownRing}, 0, 0, S_RRNG3}, // S_RRNG2
-	{SPR_RRNG, FF_FULLBRIGHT+2, 1, {A_ThrownRing}, 0, 0, S_RRNG4}, // S_RRNG3
-	{SPR_RRNG, FF_FULLBRIGHT+3, 1, {A_ThrownRing}, 0, 0, S_RRNG5}, // S_RRNG4
-	{SPR_RRNG, FF_FULLBRIGHT+4, 1, {A_ThrownRing}, 0, 0, S_RRNG6}, // S_RRNG5
-	{SPR_RRNG, FF_FULLBRIGHT+5, 1, {A_ThrownRing}, 0, 0, S_RRNG7}, // S_RRNG6
-	{SPR_RRNG, FF_FULLBRIGHT+6, 1, {A_ThrownRing}, 0, 0, S_RRNG1}, // S_RRNG7
+	{SPR_RRNG, FF_FULLBRIGHT|1, 1, {A_ThrownRing}, 0, 0, S_RRNG3}, // S_RRNG2
+	{SPR_RRNG, FF_FULLBRIGHT|2, 1, {A_ThrownRing}, 0, 0, S_RRNG4}, // S_RRNG3
+	{SPR_RRNG, FF_FULLBRIGHT|3, 1, {A_ThrownRing}, 0, 0, S_RRNG5}, // S_RRNG4
+	{SPR_RRNG, FF_FULLBRIGHT|4, 1, {A_ThrownRing}, 0, 0, S_RRNG6}, // S_RRNG5
+	{SPR_RRNG, FF_FULLBRIGHT|5, 1, {A_ThrownRing}, 0, 0, S_RRNG7}, // S_RRNG6
+	{SPR_RRNG, FF_FULLBRIGHT|6, 1, {A_ThrownRing}, 0, 0, S_RRNG1}, // S_RRNG7
 
 	// Bounce Ring
 	{SPR_RNGB, 0, 1, {NULL}, 0, 0, S_BOUNCERING2},   // S_BOUNCERING1
@@ -2499,14 +2507,14 @@ state_t states[NUMSTATES] =
 
 	// Coin
 	{SPR_COIN, FF_FULLBRIGHT,   5, {NULL}, 0, 0, S_COIN2}, // S_COIN1
-	{SPR_COIN, FF_FULLBRIGHT+1, 5, {NULL}, 0, 0, S_COIN3}, // S_COIN2
-	{SPR_COIN, FF_FULLBRIGHT+2, 5, {NULL}, 0, 0, S_COIN1}, // S_COIN3
+	{SPR_COIN, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_COIN3}, // S_COIN2
+	{SPR_COIN, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_COIN1}, // S_COIN3
 
 	// Coin Sparkle
 	{SPR_CPRK, FF_FULLBRIGHT,   5, {NULL}, 0, 0, S_COINSPARKLE2}, // S_COINSPARKLE1
-	{SPR_CPRK, FF_FULLBRIGHT+1, 5, {NULL}, 0, 0, S_COINSPARKLE3}, // S_COINSPARKLE2
-	{SPR_CPRK, FF_FULLBRIGHT+2, 5, {NULL}, 0, 0, S_COINSPARKLE4}, // S_COINSPARKLE3
-	{SPR_CPRK, FF_FULLBRIGHT+3, 5, {NULL}, 0, 0, S_NULL},         // S_COINSPARKLE4
+	{SPR_CPRK, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_COINSPARKLE3}, // S_COINSPARKLE2
+	{SPR_CPRK, FF_FULLBRIGHT|2, 5, {NULL}, 0, 0, S_COINSPARKLE4}, // S_COINSPARKLE3
+	{SPR_CPRK, FF_FULLBRIGHT|3, 5, {NULL}, 0, 0, S_NULL},         // S_COINSPARKLE4
 
 	// Goomba
 	{SPR_GOOM, 0, 6, {A_Look}, 0, 0, S_GOOMBA1B}, // S_GOOMBA1
@@ -2542,12 +2550,12 @@ state_t states[NUMSTATES] =
 
 	// Thrown Mario Fireball
 	{SPR_FBLL, FF_FULLBRIGHT,   3, {NULL}, 0, 0, S_FIREBALL2},    // S_FIREBALL1
-	{SPR_FBLL, FF_FULLBRIGHT+1, 3, {NULL}, 0, 0, S_FIREBALL3},    // S_FIREBALL2
-	{SPR_FBLL, FF_FULLBRIGHT+2, 3, {NULL}, 0, 0, S_FIREBALL4},    // S_FIREBALL3
-	{SPR_FBLL, FF_FULLBRIGHT+3, 3, {NULL}, 0, 0, S_FIREBALL1},    // S_FIREBALL4
-	{SPR_FBLL, FF_FULLBRIGHT+4, 3, {NULL}, 0, 0, S_FIREBALLEXP2}, // S_FIREBALLEXP1
-	{SPR_FBLL, FF_FULLBRIGHT+5, 3, {NULL}, 0, 0, S_FIREBALLEXP3}, // S_FIREBALLEXP2
-	{SPR_FBLL, FF_FULLBRIGHT+6, 3, {NULL}, 0, 0, S_NULL},         // S_FIREBALLEXP3
+	{SPR_FBLL, FF_FULLBRIGHT|1, 3, {NULL}, 0, 0, S_FIREBALL3},    // S_FIREBALL2
+	{SPR_FBLL, FF_FULLBRIGHT|2, 3, {NULL}, 0, 0, S_FIREBALL4},    // S_FIREBALL3
+	{SPR_FBLL, FF_FULLBRIGHT|3, 3, {NULL}, 0, 0, S_FIREBALL1},    // S_FIREBALL4
+	{SPR_FBLL, FF_FULLBRIGHT|4, 3, {NULL}, 0, 0, S_FIREBALLEXP2}, // S_FIREBALLEXP1
+	{SPR_FBLL, FF_FULLBRIGHT|5, 3, {NULL}, 0, 0, S_FIREBALLEXP3}, // S_FIREBALLEXP2
+	{SPR_FBLL, FF_FULLBRIGHT|6, 3, {NULL}, 0, 0, S_NULL},         // S_FIREBALLEXP3
 
 	// Turtle Shell
 	{SPR_SHLL, 0, -1, {NULL}, 0, 0, S_NULL},  // S_SHELL
@@ -2558,11 +2566,11 @@ state_t states[NUMSTATES] =
 
 	// Puma (Mario fireball)
 	{SPR_PUMA, FF_FULLBRIGHT,   3, {A_FishJump}, 0, 0, S_PUMA2}, // S_PUMA1
-	{SPR_PUMA, FF_FULLBRIGHT+1, 3, {A_FishJump}, 0, 0, S_PUMA3}, // S_PUMA2
-	{SPR_PUMA, FF_FULLBRIGHT+2, 3, {A_FishJump}, 0, 0, S_PUMA1}, // S_PUMA3
-	{SPR_PUMA, FF_FULLBRIGHT+3, 3, {A_FishJump}, 0, 0, S_PUMA5}, // S_PUMA4
-	{SPR_PUMA, FF_FULLBRIGHT+4, 3, {A_FishJump}, 0, 0, S_PUMA6}, // S_PUMA5
-	{SPR_PUMA, FF_FULLBRIGHT+5, 3, {A_FishJump}, 0, 0, S_PUMA4}, // S_PUMA6
+	{SPR_PUMA, FF_FULLBRIGHT|1, 3, {A_FishJump}, 0, 0, S_PUMA3}, // S_PUMA2
+	{SPR_PUMA, FF_FULLBRIGHT|2, 3, {A_FishJump}, 0, 0, S_PUMA1}, // S_PUMA3
+	{SPR_PUMA, FF_FULLBRIGHT|3, 3, {A_FishJump}, 0, 0, S_PUMA5}, // S_PUMA4
+	{SPR_PUMA, FF_FULLBRIGHT|4, 3, {A_FishJump}, 0, 0, S_PUMA6}, // S_PUMA5
+	{SPR_PUMA, FF_FULLBRIGHT|5, 3, {A_FishJump}, 0, 0, S_PUMA4}, // S_PUMA6
 
 	// Hammer
 	{SPR_HAMM, 0, 3, {NULL}, 0, 0, S_HAMMER2}, // S_HAMMER1
@@ -2707,15 +2715,15 @@ state_t states[NUMSTATES] =
 
 	// Nights Sparkle
 	{SPR_NSPK, FF_FULLBRIGHT, 140, {NULL}, 0, 0, S_NIGHTSPARKLE2},   // S_NIGHTSPARKLE1
-	{SPR_NSPK, FF_FULLBRIGHT+1, 7, {NULL}, 0, 0, S_NIGHTSPARKLE3},   // S_NIGHTSPARKLE2
-	{SPR_NSPK, FF_FULLBRIGHT+2, 7, {NULL}, 0, 0, S_NIGHTSPARKLE4},   // S_NIGHTSPARKLE3
-	{SPR_NSPK, FF_FULLBRIGHT+3, 7, {NULL}, 0, 0, S_NULL},            // S_NIGHTSPARKLE4
+	{SPR_NSPK, FF_FULLBRIGHT|1, 7, {NULL}, 0, 0, S_NIGHTSPARKLE3},   // S_NIGHTSPARKLE2
+	{SPR_NSPK, FF_FULLBRIGHT|2, 7, {NULL}, 0, 0, S_NIGHTSPARKLE4},   // S_NIGHTSPARKLE3
+	{SPR_NSPK, FF_FULLBRIGHT|3, 7, {NULL}, 0, 0, S_NULL},            // S_NIGHTSPARKLE4
 
 	// Red Sparkle
-	{SPR_NSPK, FF_FULLBRIGHT+4, 140, {NULL}, 0, 0, S_NIGHTSPARKLESUPER2}, // S_NIGHTSPARKLESUPER1
-	{SPR_NSPK, FF_FULLBRIGHT+5, 7, {NULL}, 0, 0, S_NIGHTSPARKLESUPER3},   // S_NIGHTSPARKLESUPER2
-	{SPR_NSPK, FF_FULLBRIGHT+6, 7, {NULL}, 0, 0, S_NIGHTSPARKLESUPER4},   // S_NIGHTSPARKLESUPER3
-	{SPR_NSPK, FF_FULLBRIGHT+7, 7, {NULL}, 0, 0, S_NULL},                 // S_NIGHTSPARKLESUPER4
+	{SPR_NSPK, FF_FULLBRIGHT|4, 140, {NULL}, 0, 0, S_NIGHTSPARKLESUPER2}, // S_NIGHTSPARKLESUPER1
+	{SPR_NSPK, FF_FULLBRIGHT|5, 7, {NULL}, 0, 0, S_NIGHTSPARKLESUPER3},   // S_NIGHTSPARKLESUPER2
+	{SPR_NSPK, FF_FULLBRIGHT|6, 7, {NULL}, 0, 0, S_NIGHTSPARKLESUPER4},   // S_NIGHTSPARKLESUPER3
+	{SPR_NSPK, FF_FULLBRIGHT|7, 7, {NULL}, 0, 0, S_NULL},                 // S_NIGHTSPARKLESUPER4
 
 	// Paraloop helper -- THIS IS WHAT DETERMINES THE TIMER NOW
 	{SPR_NULL, 0, 160, {NULL}, 0, 0, S_NULL}, // S_NIGHTSLOOPHELPER
@@ -2739,25 +2747,25 @@ state_t states[NUMSTATES] =
 	{SPR_HOOP, 2, -1, {NULL}, 0, 0, S_NULL}, // S_HOOP_XMASB
 
 	{SPR_NSCR, FF_FULLBRIGHT,    -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE10
-	{SPR_NSCR, FF_FULLBRIGHT+1,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE20
-	{SPR_NSCR, FF_FULLBRIGHT+2,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE30
-	{SPR_NSCR, FF_FULLBRIGHT+3,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE40
-	{SPR_NSCR, FF_FULLBRIGHT+4,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE50
-	{SPR_NSCR, FF_FULLBRIGHT+5,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE60
-	{SPR_NSCR, FF_FULLBRIGHT+6,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE70
-	{SPR_NSCR, FF_FULLBRIGHT+7,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE80
-	{SPR_NSCR, FF_FULLBRIGHT+8,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE90
-	{SPR_NSCR, FF_FULLBRIGHT+9,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE100
-	{SPR_NSCR, FF_FULLBRIGHT+10, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE10_2
-	{SPR_NSCR, FF_FULLBRIGHT+11, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE20_2
-	{SPR_NSCR, FF_FULLBRIGHT+12, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE30_2
-	{SPR_NSCR, FF_FULLBRIGHT+13, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE40_2
-	{SPR_NSCR, FF_FULLBRIGHT+14, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE50_2
-	{SPR_NSCR, FF_FULLBRIGHT+15, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE60_2
-	{SPR_NSCR, FF_FULLBRIGHT+16, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE70_2
-	{SPR_NSCR, FF_FULLBRIGHT+17, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE80_2
-	{SPR_NSCR, FF_FULLBRIGHT+18, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE90_2
-	{SPR_NSCR, FF_FULLBRIGHT+19, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE100_2
+	{SPR_NSCR, FF_FULLBRIGHT|1,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE20
+	{SPR_NSCR, FF_FULLBRIGHT|2,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE30
+	{SPR_NSCR, FF_FULLBRIGHT|3,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE40
+	{SPR_NSCR, FF_FULLBRIGHT|4,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE50
+	{SPR_NSCR, FF_FULLBRIGHT|5,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE60
+	{SPR_NSCR, FF_FULLBRIGHT|6,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE70
+	{SPR_NSCR, FF_FULLBRIGHT|7,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE80
+	{SPR_NSCR, FF_FULLBRIGHT|8,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE90
+	{SPR_NSCR, FF_FULLBRIGHT|9,  -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE100
+	{SPR_NSCR, FF_FULLBRIGHT|10, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE10_2
+	{SPR_NSCR, FF_FULLBRIGHT|11, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE20_2
+	{SPR_NSCR, FF_FULLBRIGHT|12, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE30_2
+	{SPR_NSCR, FF_FULLBRIGHT|13, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE40_2
+	{SPR_NSCR, FF_FULLBRIGHT|14, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE50_2
+	{SPR_NSCR, FF_FULLBRIGHT|15, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE60_2
+	{SPR_NSCR, FF_FULLBRIGHT|16, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE70_2
+	{SPR_NSCR, FF_FULLBRIGHT|17, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE80_2
+	{SPR_NSCR, FF_FULLBRIGHT|18, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE90_2
+	{SPR_NSCR, FF_FULLBRIGHT|19, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSCORE100_2
 
 	{SPR_NWNG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSWING
 	{SPR_NWNG, 1, -1, {NULL}, 0, 0, S_NULL}, // S_NIGHTSWING_XMAS
@@ -2778,21 +2786,21 @@ state_t states[NUMSTATES] =
 
 	// Orbiting Chaos Emeralds for NiGHTS
 	{SPR_CEMG, FF_FULLBRIGHT,   1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM1}, // S_ORBITEM1
-	{SPR_CEMG, FF_FULLBRIGHT+1, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM2}, // S_ORBITEM2
-	{SPR_CEMG, FF_FULLBRIGHT+2, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM3}, // S_ORBITEM3
-	{SPR_CEMG, FF_FULLBRIGHT+3, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM4}, // S_ORBITEM4
-	{SPR_CEMG, FF_FULLBRIGHT+4, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM5}, // S_ORBITEM5
-	{SPR_CEMG, FF_FULLBRIGHT+5, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM6}, // S_ORBITEM6
-	{SPR_CEMG, FF_FULLBRIGHT+6, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM7}, // S_ORBITEM7
-	{SPR_CEMG, FF_FULLBRIGHT+7, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM8
-	{SPR_CEMG, FF_FULLBRIGHT+8, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM9
-	{SPR_CEMG, FF_FULLBRIGHT+9, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM10
-	{SPR_CEMG, FF_FULLBRIGHT+10, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM11
-	{SPR_CEMG, FF_FULLBRIGHT+11, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM12
-	{SPR_CEMG, FF_FULLBRIGHT+12, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM13
-	{SPR_CEMG, FF_FULLBRIGHT+13, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM14
-	{SPR_CEMG, FF_FULLBRIGHT+14, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM15
-	{SPR_CEMG, FF_FULLBRIGHT+15, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM16
+	{SPR_CEMG, FF_FULLBRIGHT|1, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM2}, // S_ORBITEM2
+	{SPR_CEMG, FF_FULLBRIGHT|2, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM3}, // S_ORBITEM3
+	{SPR_CEMG, FF_FULLBRIGHT|3, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM4}, // S_ORBITEM4
+	{SPR_CEMG, FF_FULLBRIGHT|4, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM5}, // S_ORBITEM5
+	{SPR_CEMG, FF_FULLBRIGHT|5, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM6}, // S_ORBITEM6
+	{SPR_CEMG, FF_FULLBRIGHT|6, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM7}, // S_ORBITEM7
+	{SPR_CEMG, FF_FULLBRIGHT|7, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM8
+	{SPR_CEMG, FF_FULLBRIGHT|8, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM9
+	{SPR_CEMG, FF_FULLBRIGHT|9, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM10
+	{SPR_CEMG, FF_FULLBRIGHT|10, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM11
+	{SPR_CEMG, FF_FULLBRIGHT|11, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM12
+	{SPR_CEMG, FF_FULLBRIGHT|12, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM13
+	{SPR_CEMG, FF_FULLBRIGHT|13, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM14
+	{SPR_CEMG, FF_FULLBRIGHT|14, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM15
+	{SPR_CEMG, FF_FULLBRIGHT|15, 1, {A_OrbitNights}, ANG2*2, 0, S_ORBITEM8}, // S_ORBITEM16
 
 	// Flicky helper for NiGHTS
 	{SPR_BIRD, 0, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER2}, // S_NIGHTOPIANHELPER1
@@ -2818,22 +2826,22 @@ state_t states[NUMSTATES] =
 	{SPR_SUPT, 8,    16, {NULL}, 0, 0, S_NIGHTSDRONE1}, // S_SUPERTRANS9
 
 	// Spark
-	{SPR_SPRK, 0, 1, {NULL}, 0, 0, S_SPRK2},  // S_SPRK1
-	{SPR_SPRK, 1, 1, {NULL}, 0, 0, S_SPRK3},  // S_SPRK2
-	{SPR_SPRK, 2, 1, {NULL}, 0, 0, S_SPRK4},  // S_SPRK3
-	{SPR_SPRK, 3, 1, {NULL}, 0, 0, S_SPRK5},  // S_SPRK4
-	{SPR_SPRK, 0, 1, {NULL}, 0, 0, S_SPRK6},  // S_SPRK5
-	{SPR_SPRK, 1, 1, {NULL}, 0, 0, S_SPRK7},  // S_SPRK6
-	{SPR_SPRK, 2, 1, {NULL}, 0, 0, S_SPRK8},  // S_SPRK7
-	{SPR_SPRK, 3, 1, {NULL}, 0, 0, S_SPRK9},  // S_SPRK8
-	{SPR_SPRK, 0, 1, {NULL}, 0, 0, S_SPRK10}, // S_SPRK9
-	{SPR_SPRK, 1, 1, {NULL}, 0, 0, S_SPRK11}, // S_SPRK10
-	{SPR_SPRK, 2, 1, {NULL}, 0, 0, S_SPRK12}, // S_SPRK11
-	{SPR_SPRK, 3, 1, {NULL}, 0, 0, S_SPRK13}, // S_SPRK12
-	{SPR_SPRK, 0, 1, {NULL}, 0, 0, S_SPRK14}, // S_SPRK13
-	{SPR_SPRK, 1, 1, {NULL}, 0, 0, S_SPRK15}, // S_SPRK14
-	{SPR_SPRK, 2, 1, {NULL}, 0, 0, S_SPRK16}, // S_SPRK15
-	{SPR_SPRK, 3, 1, {NULL}, 0, 0, S_NULL},   // S_SPRK16
+	{SPR_SPRK, FF_TRANS40  , 1, {NULL}, 0, 0, S_SPRK2},  // S_SPRK1
+	{SPR_SPRK, FF_TRANS50|1, 1, {NULL}, 0, 0, S_SPRK3},  // S_SPRK2
+	{SPR_SPRK, FF_TRANS50|2, 1, {NULL}, 0, 0, S_SPRK4},  // S_SPRK3
+	{SPR_SPRK, FF_TRANS50|3, 1, {NULL}, 0, 0, S_SPRK5},  // S_SPRK4
+	{SPR_SPRK, FF_TRANS60  , 1, {NULL}, 0, 0, S_SPRK6},  // S_SPRK5
+	{SPR_SPRK, FF_TRANS60|1, 1, {NULL}, 0, 0, S_SPRK7},  // S_SPRK6
+	{SPR_SPRK, FF_TRANS60|2, 1, {NULL}, 0, 0, S_SPRK8},  // S_SPRK7
+	{SPR_SPRK, FF_TRANS70|3, 1, {NULL}, 0, 0, S_SPRK9},  // S_SPRK8
+	{SPR_SPRK, FF_TRANS70  , 1, {NULL}, 0, 0, S_SPRK10}, // S_SPRK9
+	{SPR_SPRK, FF_TRANS70|1, 1, {NULL}, 0, 0, S_SPRK11}, // S_SPRK10
+	{SPR_SPRK, FF_TRANS80|2, 1, {NULL}, 0, 0, S_SPRK12}, // S_SPRK11
+	{SPR_SPRK, FF_TRANS80|3, 1, {NULL}, 0, 0, S_SPRK13}, // S_SPRK12
+	{SPR_SPRK, FF_TRANS80  , 1, {NULL}, 0, 0, S_SPRK14}, // S_SPRK13
+	{SPR_SPRK, FF_TRANS90|1, 1, {NULL}, 0, 0, S_SPRK15}, // S_SPRK14
+	{SPR_SPRK, FF_TRANS90|2, 1, {NULL}, 0, 0, S_SPRK16}, // S_SPRK15
+	{SPR_SPRK, FF_TRANS90|3, 1, {NULL}, 0, 0, S_NULL},   // S_SPRK16
 
 	// Robot Explosion
 	{SPR_BOM1, 0, 1, {A_Scream}, 0, 0, S_XPLD2}, // S_XPLD1
@@ -7367,7 +7375,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_DEMONFIRE
 		-1,             // doomednum
-		S_DEMONFIRE,    // spawnstate
+		S_DEMONFIRE1,   // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -12940,33 +12948,6 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
-	{           // MT_CHAOSSPAWNER
-		750,            // doomednum
-		S_INVISIBLE,    // spawnstate
-		1000,           // spawnhealth
-		S_NULL,         // seestate
-		sfx_None,       // seesound
-		8,              // reactiontime
-		sfx_None,       // attacksound
-		S_NULL,         // painstate
-		0,              // painchance
-		sfx_None,       // painsound
-		S_NULL,         // meleestate
-		S_NULL,         // missilestate
-		S_NULL,         // deathstate
-		S_NULL,         // xdeathstate
-		sfx_None,       // deathsound
-		1,              // speed
-		8*FRACUNIT,     // radius
-		16*FRACUNIT,    // height
-		0,              // display offset
-		4,              // mass
-		0,              // damage
-		sfx_None,       // activesound
-		MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY, // flags
-		S_NULL          // raisestate
-	},
-
 	{           // MT_TELEPORTMAN
 		751,            // doomednum
 		S_INVISIBLE,    // spawnstate
diff --git a/src/info.h b/src/info.h
index bc9b7f8fb0827bf4e83aeaa4183804f30110810c..0c73281df34d7061803ac16f0aa23cd0d0c70dab 100644
--- a/src/info.h
+++ b/src/info.h
@@ -355,6 +355,7 @@ typedef enum sprite
 	SPR_TRLS,
 	SPR_CBLL, // Cannonball
 	SPR_AROW, // Arrow
+	SPR_CFIR, // Colored fire of various sorts
 
 	// Greenflower Scenery
 	SPR_FWR1,
@@ -1907,7 +1908,12 @@ typedef enum state
 	S_ARROWDOWN,
 
 	// Trapgoyle Demon fire
-	S_DEMONFIRE,
+	S_DEMONFIRE1,
+	S_DEMONFIRE2,
+	S_DEMONFIRE3,
+	S_DEMONFIRE4,
+	S_DEMONFIRE5,
+	S_DEMONFIRE6,
 
 	S_GFZFLOWERA,
 	S_GFZFLOWERA2,
@@ -3934,7 +3940,6 @@ typedef enum mobj_type
 	MT_NIGHTOPIANHELPER, // the actual helper object that orbits you
 
 	// Utility Objects
-	MT_CHAOSSPAWNER,
 	MT_TELEPORTMAN,
 	MT_ALTVIEWMAN,
 	MT_CRUMBLEOBJ, // Sound generator for crumbling platform
diff --git a/src/m_menu.c b/src/m_menu.c
index b8be38e825dc6816c487e4f7a0278ab46719df56..06aaac0ef0d7629d9e8ea572c04b089b87a63a48 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -387,9 +387,6 @@ CV_PossibleValue_t gametype_cons_t[] =
 	{GT_HIDEANDSEEK, "Hide and Seek"},
 
 	{GT_CTF, "CTF"},
-#ifdef CHAOSISNOTDEADYET
-	{GT_CHAOS, "Chaos"},
-#endif
 	{0, NULL}
 };
 consvar_t cv_newgametype = {"newgametype", "Co-op", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange, 0, NULL, NULL, 0, 0, NULL};
@@ -1129,7 +1126,9 @@ static menuitem_t OP_MouseOptionsMenu[] =
 	{IT_STRING | IT_CVAR, NULL, "Mouse Move",       &cv_mousemove,        40},
 	{IT_STRING | IT_CVAR, NULL, "Invert Mouse",     &cv_invertmouse,      50},
 	{IT_STRING | IT_CVAR | IT_CV_SLIDER,
-	                      NULL, "Mouse Speed",      &cv_mousesens,        60},
+	                      NULL, "Mouse X Speed",    &cv_mousesens,        60},
+	{IT_STRING | IT_CVAR | IT_CV_SLIDER,
+	                      NULL, "Mouse Y Speed",    &cv_mouseysens,        70},
 };
 
 static menuitem_t OP_Mouse2OptionsMenu[] =
@@ -1139,9 +1138,11 @@ static menuitem_t OP_Mouse2OptionsMenu[] =
 	                                                &cv_mouse2port,       20},
 	{IT_STRING | IT_CVAR, NULL, "Always MouseLook", &cv_alwaysfreelook2,  30},
 	{IT_STRING | IT_CVAR, NULL, "Mouse Move",       &cv_mousemove2,       40},
-	{IT_STRING | IT_CVAR, NULL, "Invert Mouse",    &cv_invertmouse2,      50},
+	{IT_STRING | IT_CVAR, NULL, "Invert Mouse",     &cv_invertmouse2,     50},
 	{IT_STRING | IT_CVAR | IT_CV_SLIDER,
-	                      NULL, "Mouse Speed",     &cv_mousesens2,        60},
+	                      NULL, "Mouse X Speed",    &cv_mousesens2,       60},
+	{IT_STRING | IT_CVAR | IT_CV_SLIDER,
+	                      NULL, "Mouse Y Speed",    &cv_mouseysens2,      70},
 };
 
 static menuitem_t OP_VideoOptionsMenu[] =
@@ -1901,9 +1902,6 @@ static void Newgametype_OnChange(void)
 			(cv_newgametype.value == GT_COMPETITION && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_COMPETITION)) ||
 			(cv_newgametype.value == GT_RACE && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_RACE)) ||
 			((cv_newgametype.value == GT_MATCH || cv_newgametype.value == GT_TEAMMATCH) && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_MATCH)) ||
-#ifdef CHAOSISNOTDEADYET
-			(cv_newgametype.value == GT_CHAOS && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_CHAOS)) ||
-#endif
 			((cv_newgametype.value == GT_TAG || cv_newgametype.value == GT_HIDEANDSEEK) && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_TAG)) ||
 			(cv_newgametype.value == GT_CTF && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_CTF)))
 		{
@@ -3468,11 +3466,6 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt)
 			if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE))
 				return true;
 
-#ifdef CHAOSISNOTDEADYET
-			if (gt == GT_CHAOS && (mapheaderinfo[mapnum]->typeoflevel & TOL_CHAOS))
-				return true;
-#endif
-
 			return false;
 
 		case LLM_LEVELSELECT:
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 54e151123b041237a3bc38d78b12cb2d6ed02f41..18a4ec5ff415be7bee7f5b828fca47ece86ac247 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -2715,14 +2715,6 @@ void A_BossDeath(mobj_t *mo)
 	P_LinedefExecute(LE_BOSSDEAD, mo, NULL);
 	mo->health = 0;
 
-#ifdef CHAOSISNOTDEADYET
-	if (mo->flags2 & MF2_CHAOSBOSS)
-	{
-		P_RemoveMobj(mo);
-		return;
-	}
-#endif
-
 	// Boss is dead (but not necessarily fleeing...)
 	// Lua may use this to ignore bosses after they start fleeing
 	mo->flags2 |= MF2_BOSSDEAD;
@@ -5635,10 +5627,11 @@ void A_MixUp(mobj_t *actor)
 //
 void A_RecyclePowers(mobj_t *actor)
 {
-#ifdef WEIGHTEDRECYCLER
 	INT32 i, j, k, numplayers = 0;
 
+#ifdef WEIGHTEDRECYCLER
 	UINT8 beneficiary = 255;
+#endif
 	UINT8 playerslist[MAXPLAYERS];
 	UINT8 postscramble[MAXPLAYERS];
 
@@ -5651,6 +5644,11 @@ void A_RecyclePowers(mobj_t *actor)
 		return;
 #endif
 
+#if !defined(WEIGHTEDRECYCLER) && !defined(HAVE_BLUA)
+	// actor is used in all scenarios but this one, funny enough
+	(void)actor;
+#endif
+
 	if (!multiplayer)
 		return;
 
@@ -5665,9 +5663,11 @@ void A_RecyclePowers(mobj_t *actor)
 			numplayers++;
 			postscramble[j] = playerslist[j] = (UINT8)i;
 
+#ifdef WEIGHTEDRECYCLER
 			// The guy who started the recycle gets the best result
 			if (actor && actor->target && actor->target->player && &players[i] == actor->target->player)
 				beneficiary = (UINT8)i;
+#endif
 
 			// Save powers
 			for (k = 0; k < NUMPOWERS; k++)
@@ -5684,6 +5684,13 @@ void A_RecyclePowers(mobj_t *actor)
 		return; //nobody to touch!
 
 	//shuffle the post scramble list, whee!
+	// hardcoded 0-1 to 1-0 for two players
+	if (numplayers == 2)
+	{
+		postscramble[0] = playerslist[1];
+		postscramble[1] = playerslist[0];
+	}
+	else
 	for (j = 0; j < numplayers; j++)
 	{
 		UINT8 tempint;
@@ -5694,6 +5701,7 @@ void A_RecyclePowers(mobj_t *actor)
 		postscramble[i] = tempint;
 	}
 
+#ifdef WEIGHTEDRECYCLER
 	//the joys of qsort...
 	if (beneficiary != 255) {
 		qsort(playerslist, numplayers, sizeof(UINT8), P_RecycleCompare);
@@ -5710,6 +5718,7 @@ void A_RecyclePowers(mobj_t *actor)
 			}
 		}
 	}
+#endif
 
 	// now assign!
 	for (i = 0; i < numplayers; i++)
@@ -5737,137 +5746,6 @@ void A_RecyclePowers(mobj_t *actor)
 			P_RestoreMusic(&players[recv_pl]);
 		P_FlashPal(&players[recv_pl], PAL_RECYCLE, 10);
 	}
-#else
-	INT32 i, numplayers = 0;
-
-#ifdef HAVE_BLUA
-	if (LUA_CallAction("A_RecyclePowers", actor))
-		return;
-#endif
-	if (!multiplayer)
-		return;
-
-	numplayers = 0;
-
-	// Count the number of players in the game
-	for (i = 0; i < MAXPLAYERS; i++)
-		if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE
-			&& !players[i].exiting && !players[i].powers[pw_super] && !((netgame || multiplayer) && players[i].spectator))
-			numplayers++;
-
-	if (numplayers <= 1)
-		return; //nobody to touch!
-
-	else if (numplayers == 2) //simple swap is all that's needed
-	{
-		UINT16 temp[NUMPOWERS];
-		INT32 weapons;
-		INT32 weaponheld;
-
-		INT32 one = -1, two = 0; // default value 0 to make the compiler shut up
-
-		for (i = 0; i < MAXPLAYERS; i++)
-			if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE
-				&& !players[i].exiting && !players[i].powers[pw_super] && !((netgame || multiplayer) && players[i].spectator))
-			{
-				if (one == -1)
-					one = i;
-				else
-					two = i;
-			}
-		for (i = 0; i < NUMPOWERS; i++)
-		{
-			if (i == pw_flashing || i == pw_underwater || i == pw_spacetime
-			    || i == pw_tailsfly || i == pw_extralife || i == pw_super || i == pw_nocontrol)
-				continue;
-			temp[i] = players[one].powers[i];
-			players[one].powers[i] = players[two].powers[i];
-			players[two].powers[i] = temp[i];
-		}
-		//1.1: weapons need to be swapped too
-		weapons = players[one].ringweapons;
-		players[one].ringweapons = players[two].ringweapons;
-		players[two].ringweapons = weapons;
-
-		weaponheld = players[one].currentweapon;
-		players[one].currentweapon = players[two].currentweapon;
-		players[two].currentweapon = weaponheld;
-
-		P_SpawnShieldOrb(players[one].mo->player);
-		P_SpawnShieldOrb(players[two].mo->player);
-		P_FlashPal(&players[one], PAL_RECYCLE, 10);
-		P_FlashPal(&players[two], PAL_RECYCLE, 10);
-		//piece o' cake, eh?
-	}
-	else
-	{
-		//well, the cake is a LIE!
-		UINT16 temp[MAXPLAYERS][NUMPOWERS];
-		INT32 weapons[MAXPLAYERS];
-		INT32 weaponheld[MAXPLAYERS];
-		INT32 counter = 0, j = 0, prandom = 0, recyclefrom = 0;
-
-		for (i = 0; i < MAXPLAYERS; i++)
-		{
-			if (playeringame[i] && players[i].playerstate == PST_LIVE
-				&& players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super]
-				&& !((netgame || multiplayer) && players[i].spectator))
-			{
-				for (j = 0; j < NUMPOWERS; j++)
-					temp[counter][j] = players[i].powers[j];
-				//1.1: ring weapons too
-				weapons[counter] = players[i].ringweapons;
-				weaponheld[counter] = players[i].currentweapon;
-				counter++;
-			}
-		}
-		counter = 0;
-
-		// Mix them up!
-		for (;;)
-		{
-			if (counter > 255) // fail-safe to avoid endless loop
-				break;
-			prandom = P_Random();
-			prandom %= numplayers; // I love modular arithmetic, don't you?
-			if (prandom) // Make sure it's not a useless mix
-				break;
-			counter++;
-		}
-
-		counter = 0;
-
-		for (i = 0; i < MAXPLAYERS; i++)
-		{
-			if (playeringame[i] && players[i].playerstate == PST_LIVE
-				&& players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super]
-				&& !((netgame || multiplayer) && players[i].spectator))
-			{
-				recyclefrom = (counter + prandom) % numplayers;
-				for (j = 0; j < NUMPOWERS; j++)
-				{
-					if (j == pw_flashing || j == pw_underwater || j == pw_spacetime
-					    || j == pw_tailsfly || j == pw_extralife || j == pw_super || j == pw_nocontrol)
-						continue;
-					players[i].powers[j] = temp[recyclefrom][j];
-				}
-				//1.1: weapon rings too
-				players[i].ringweapons = weapons[recyclefrom];
-				players[i].currentweapon = weaponheld[recyclefrom];
-
-				P_SpawnShieldOrb(players[i].mo->player);
-				P_FlashPal(&players[i], PAL_RECYCLE, 10);
-				counter++;
-			}
-		}
-	}
-	for (i = 0; i < MAXPLAYERS; i++) //just for sneakers/invinc.
-		if (playeringame[i] && players[i].playerstate == PST_LIVE
-			&& players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super]
-			&& !((netgame || multiplayer) && players[i].spectator))
-			if (P_IsLocalPlayer(players[i].mo->player))
-				P_RestoreMusic(players[i].mo->player);
-#endif
 
 	S_StartSound(NULL, sfx_gravch); //heh, the sound effect I used is already in
 }
@@ -6160,13 +6038,7 @@ void A_Boss2Pogo(mobj_t *actor)
 			goop->momy = FixedMul(FINESINE(fa),ns);
 			goop->momz = FixedMul(4*FRACUNIT, actor->scale);
 
-
-#ifdef CHAOSISNOTDEADYET
-			if (gametype == GT_CHAOS)
-				goop->fuse = 5*TICRATE;
-			else
-#endif
-				goop->fuse = 10*TICRATE;
+			goop->fuse = 10*TICRATE;
 		}
 		actor->reactiontime = 0; // we already shot goop, so don't do it again!
 		if (actor->info->attacksound)
diff --git a/src/p_fab.c b/src/p_fab.c
index 77abccccdeff72d9a39bc9c19374b3c0f6724ea3..7ccb93a94cf145024dd2b124dbdfc555d06f394e 100644
--- a/src/p_fab.c
+++ b/src/p_fab.c
@@ -11,124 +11,5 @@
 /// \brief some new action routines, separated from the original doom
 ///        sources, so that you can include it or remove it easy.
 
-#include "doomdef.h"
-#include "g_game.h"
-#include "p_local.h"
-#include "m_random.h"
-
-static void Translucency_OnChange(void);
-
-/**	\brief cv_translucency
-	console variables to turn on and off translucency
-*/
-consvar_t cv_translucency = {"translucency", "On", CV_CALL|CV_SAVE, CV_OnOff,
-	Translucency_OnChange, 0, NULL, NULL, 0, 0, NULL};
-
-/**	\brief Reset Translucency
-*/
-
-static boolean resettrans = false;
-
-/**	\brief	The R_SetTrans function
-	 Set the translucency map for each frame state of mobj
-
-	\param	state1	1st state
-	\param	state2	last state
-	\param	transmap	translucency
-
-	\return	void
-
-
-*/
-static void R_SetTrans(statenum_t state1, statenum_t state2, transnum_t transmap)
-{
-	state_t *state = &states[state1];
-
-	do
-	{
-		state->frame &= ~FF_TRANSMASK;
-		if (!resettrans)
-			state->frame |= (transmap<<FF_TRANSSHIFT);
-		state++;
-	} while (state1++ < state2);
-}
-
-/**	\brief	The P_SetTranslucencies function
-	 hack the translucency in the states for a set of standard doom sprites
-
-	\return	void
-
-
-*/
-static void P_SetTranslucencies(void)
-{
-	R_SetTrans(S_SMOKE1, S_SMOKE5, tr_trans50);
-	R_SetTrans(S_SPLASH1, 0, tr_trans50);
-	R_SetTrans(S_SPLASH2, 0, tr_trans70);
-	R_SetTrans(S_SPLASH3, 0, tr_trans90);
-
-	R_SetTrans(S_DRIPA1, S_DRIPC2, tr_trans30);
-
-	R_SetTrans(S_BLUECRYSTAL1, S_BLUECRYSTAL1, tr_trans30);
-
-	R_SetTrans(S_THOK, 0, tr_trans50); // Thok! mobj
-
-	R_SetTrans(S_FLAME1, S_FLAME4, tr_trans50); // Flame
-
-	R_SetTrans(S_PARTICLE, S_PARTICLE, tr_trans70);
-
-	// Flame jet
-	R_SetTrans(S_FLAMEJETFLAME1, S_FLAMEJETFLAME1, tr_trans50);
-	R_SetTrans(S_FLAMEJETFLAME2, S_FLAMEJETFLAME2, tr_trans60);
-	R_SetTrans(S_FLAMEJETFLAME3, S_FLAMEJETFLAME3, tr_trans70);
-
-	R_SetTrans(S_BLACKEGG_GOOP1, S_BLACKEGG_GOOP3, tr_trans50);
-	R_SetTrans(S_BLACKEGG_GOOP4, 0, tr_trans60);
-	R_SetTrans(S_BLACKEGG_GOOP5, 0, tr_trans70);
-	R_SetTrans(S_BLACKEGG_GOOP6, 0, tr_trans80);
-	R_SetTrans(S_BLACKEGG_GOOP7, 0, tr_trans90);
-
-	R_SetTrans(S_CYBRAKDEMONFLAMESHOT_FLY1, S_CYBRAKDEMONFLAMESHOT_DIE, tr_trans50); // Flame
-	R_SetTrans(S_CYBRAKDEMONFLAMEREST, 0, tr_trans50); // Flame
-	R_SetTrans(S_CYBRAKDEMONTARGETRETICULE1, S_CYBRAKDEMONTARGETRETICULE14, tr_trans50); // Target
-	R_SetTrans(S_CYBRAKDEMONTARGETDOT, S_CYBRAKDEMONTARGETDOT, tr_trans50); // Target
-
-	R_SetTrans(S_FOG1, S_FOG14, tr_trans50);
-
-	// if higher translucency needed, toy around with the other tr_trans variables
-
-	// shield translucencies
-	R_SetTrans(S_ARMA1, S_ARMA16, tr_trans40);
-	R_SetTrans(S_WIND1, S_WIND8,  tr_trans70);
-	R_SetTrans(S_MAGN1, S_MAGN12, tr_trans40);
-	R_SetTrans(S_FORC1, S_FORC20, tr_trans50);
-	R_SetTrans(S_ELEM1, S_ELEM12, tr_trans50);
-	R_SetTrans(S_PITY1, S_PITY10, tr_trans20); // Not sure if Pity Shield should be translucent or not; I mean, the Genesis sprite it's based off of wasn't...
-
-	// translucent spark
-	R_SetTrans(S_SPRK1, S_SPRK1, tr_trans40);
-	R_SetTrans(S_SPRK2, S_SPRK4, tr_trans50);
-	R_SetTrans(S_SPRK5, S_SPRK7, tr_trans60);
-	R_SetTrans(S_SPRK8, S_SPRK10, tr_trans70);
-	R_SetTrans(S_SPRK11, S_SPRK13, tr_trans80);
-	R_SetTrans(S_SPRK14, S_SPRK16, tr_trans90);
-
-	R_SetTrans(S_SMALLBUBBLE, S_SMALLBUBBLE1, tr_trans50);
-	R_SetTrans(S_MEDIUMBUBBLE, S_MEDIUMBUBBLE1, tr_trans50);
-	R_SetTrans(S_LARGEBUBBLE, S_EXTRALARGEBUBBLE, tr_trans50);
-
-	R_SetTrans(S_SPLISH1, S_SPLISH9, tr_trans50);
-	R_SetTrans(S_TOKEN, S_MOVINGTOKEN, tr_trans50);
-	R_SetTrans(S_RAIN1, 0, tr_trans50);
-}
-
-/**	\brief	The Translucency_OnChange function
-	executed when cv_translucency changed
-*/
-static void Translucency_OnChange(void)
-{
-	if (!cv_translucency.value)
-		resettrans = true;
-	P_SetTranslucencies();
-	resettrans = false;
-}
+/// \todo
+///   This file is now unused, please remove at some point
diff --git a/src/p_inter.c b/src/p_inter.c
index 5044b5b81e60c391ba471cc1175f8bd4b67a24f3..8eaa4765a87f7d7d8d828fc1b32a01e2370a302b 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -1590,33 +1590,6 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
 			case MT_SPIKE:
 				str = M_GetText("%s was %s by spikes.\n");
 				break;
-#ifdef CHAOSISNOTDEADYET
-/* These were obviously made for Chaos, and they're extremely out of date.
-   We either need to keep them out of the EXE or update them to contain
-   proper text for all enemies we currently have in the game.
-*/
-			case MT_BLUECRAWLA:
-				str = M_GetText("%s was %s by a blue crawla!\n");
-				break;
-			case MT_REDCRAWLA:
-				str = M_GetText("%s was %s by a red crawla!\n");
-				break;
-			case MT_JETTGUNNER:
-				str = M_GetText("%s was %s by a jetty-syn gunner!\n");
-				break;
-			case MT_JETTBOMBER:
-				str = M_GetText("%s was %s by a jetty-syn bomber!\n");
-				break;
-			case MT_CRAWLACOMMANDER:
-				str = M_GetText("%s was %s by a crawla commander!\n");
-				break;
-			case MT_EGGMOBILE:
-				str = M_GetText("%s was %s by the Egg Mobile!\n");
-				break;
-			case MT_EGGMOBILE2:
-				str = M_GetText("%s was %s by the Egg Slimer!\n");
-				break;
-#endif
 			default:
 				str = M_GetText("%s was %s by an environmental hazard.\n");
 				break;
@@ -1864,11 +1837,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
 	{
 		if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording!
 			G_StopMetalRecording();
-#ifdef CHAOSISNOTDEADYET
-		if (gametype == GT_CHAOS)
-			target->player->score /= 2; // Halve the player's score in Chaos Mode
-		else
-#endif
 		if (gametype == GT_MATCH && cv_match_scoring.value == 0 // note, no team match suicide penalty
 			&& ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player)))
 		{ // Suicide penalty
@@ -1896,39 +1864,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
 		{
 			INT32 score = 0;
 
-#ifdef CHAOSISNOTDEADYET
-			if (gametype == GT_CHAOS)
-			{
-				if ((target->flags & MF_ENEMY)
-					&& !(target->flags & MF_MISSILE))
-					source->player->scoreadd++;
-
-				switch (target->type)
-				{
-					case MT_BLUECRAWLA:
-					case MT_GOOMBA:
-						score = 100*source->player->scoreadd;
-						break;
-					case MT_REDCRAWLA:
-					case MT_BLUEGOOMBA:
-						score = 150*source->player->scoreadd;
-						break;
-					case MT_JETTBOMBER:
-						score = 400*source->player->scoreadd;
-						break;
-					case MT_JETTGUNNER:
-						score = 500*source->player->scoreadd;
-						break;
-					case MT_CRAWLACOMMANDER:
-						score = 300*source->player->scoreadd;
-						break;
-					default:
-						score = 100*source->player->scoreadd;
-						break;
-				}
-			}
-			else
-#endif
 			if (maptol & TOL_NIGHTS) // Enemies always worth 200, bosses don't do anything.
 			{
 				if ((target->flags & MF_ENEMY) && !(target->flags & (MF_MISSILE|MF_BOSS)))
@@ -2089,9 +2024,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
 	// This determines the kind of object spawned
 	// during the death frame of a thing.
 	if (!mariomode // Don't show birds, etc. in Mario Mode Tails 12-23-2001
-#ifdef CHAOSISNOTDEADYET
-	&& gametype != GT_CHAOS // Or Chaos Mode!
-#endif
 	&& target->flags & MF_ENEMY)
 	{
 		if (cv_soniccd.value)
@@ -2512,11 +2444,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj
 		return false;
 
 	// In COOP/RACE/CHAOS, you can't hurt other players unless cv_friendlyfire is on
-	if (!cv_friendlyfire.value && (G_PlatformGametype()
-#ifdef CHAOSISNOTDEADYET
-		|| gametype == GT_CHAOS
-#endif
-		))
+	if (!cv_friendlyfire.value && (G_PlatformGametype()))
 		return false;
 
 	// Tag handling
@@ -2843,17 +2771,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 
 		if (target->health > 1)
 		{
-
-#ifdef CHAOSISNOTDEADYET
-			if (gametype == GT_CHAOS && source && source->player)
-			{
-				player = source->player;
-				if (!((player->pflags & PF_USEDOWN) && player->dashspeed
-				&& (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING)))
-					player->scoreadd++;
-				P_AddPlayerScore(player, 300*player->scoreadd);
-			}
-#endif
 			if (target->info->painsound)
 				S_StartSound(target, target->info->painsound);
 
@@ -2882,14 +2799,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 
 		if (target->health > 1)
 			target->flags2 |= MF2_FRET;
-
-#ifdef CHAOSISNOTDEADYET
-		if (gametype == GT_CHAOS && source && source->player)
-		{
-			source->player->scoreadd++;
-			P_AddPlayerScore(source->player, 300*source->player->scoreadd);
-		}
-#endif
 	}
 #ifdef HAVE_BLUA
 	else if (target->flags & MF_ENEMY)
diff --git a/src/p_local.h b/src/p_local.h
index 9f8918cd81092327de4dd5fdef5deeb9151a47b3..0b27c40f307732e6d3dc4b66b99c02885ad64e7c 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -144,7 +144,7 @@ void P_GivePlayerLives(player_t *player, INT32 numlives);
 UINT8 P_GetNextEmerald(void);
 void P_GiveEmerald(boolean spawnObj);
 void P_ResetScore(player_t *player);
-boolean P_MenuActivePause(void);
+boolean P_AutoPause(void);
 
 void P_DoJumpShield(player_t *player);
 void P_BlackOw(player_t *player);
diff --git a/src/p_mobj.c b/src/p_mobj.c
index e85e25b052948f6b882c3d769f1aa73b428855ba..cac4bc24bc4b326b18ff79f21107f53a7419b205 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -1354,50 +1354,143 @@ static void P_SceneryXYMovement(mobj_t *mo)
 	P_SceneryXYFriction(mo, oldx, oldy);
 }
 
-static void P_RingZMovement(mobj_t *mo)
+//
+// P_AdjustMobjFloorZ_FFloors
+//
+// Utility function for P_ZMovement and related
+// Adjusts mo->floorz/mo->ceiling accordingly for FFloors
+//
+// "motype" determines what behaviour to use exactly
+// This is to keep things consistent in case these various object types NEED to be different
+//
+// motype options:
+// 0 - normal
+// 1 - forces false check for water (rings)
+// 2 - forces false check for water + different quicksand behaviour (scenery)
+//
+static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype)
 {
+	ffloor_t *rover;
+	fixed_t delta1, delta2, thingtop;
+
 	I_Assert(mo != NULL);
 	I_Assert(!P_MobjWasRemoved(mo));
 
-	// Intercept the stupid 'fall through 3dfloors' bug
-	if (mo->subsector->sector->ffloors)
+	thingtop = mo->z + mo->height;
+
+	for (rover = sector->ffloors; rover; rover = rover->next)
 	{
-		ffloor_t *rover;
-		fixed_t delta1, delta2;
-		INT32 thingtop = mo->z + mo->height;
+		if (!(rover->flags & FF_EXISTS))
+			continue;
 
-		for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next)
+		if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should be affected
+			;
+		else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only
+			continue;
+		else if (rover->flags & FF_QUICKSAND) // quicksand
+			;
+		else if (!((rover->flags & FF_BLOCKPLAYER && mo->player) // solid to players?
+			    || (rover->flags & FF_BLOCKOTHERS && !mo->player))) // solid to others?
+			continue;
+		if (rover->flags & FF_QUICKSAND)
 		{
-			if (!(rover->flags & FF_EXISTS))
-				continue;
-
-			if ((!(rover->flags & FF_BLOCKOTHERS || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE)))
-				continue;
-
-			if (rover->flags & FF_QUICKSAND)
+			switch (motype)
 			{
-				if (mo->z < *rover->topheight && *rover->bottomheight < thingtop)
-				{
-					if (mo->floorz < mo->z)
+				case 2: // scenery does things differently for some reason
+					if (mo->z < *rover->topheight && *rover->bottomheight < thingtop)
+					{
 						mo->floorz = mo->z;
-				}
-				continue;
+						continue;
+					}
+					break;
+				default:
+					if (mo->z < *rover->topheight && *rover->bottomheight < thingtop)
+					{
+						if (mo->floorz < mo->z)
+							mo->floorz = mo->z;
+					}
+					continue; // This is so you can jump/spring up through quicksand from below.
 			}
+		}
 
-			delta1 = mo->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			if (*rover->topheight > mo->floorz && abs(delta1) < abs(delta2)
-				&& (!(rover->flags & FF_REVERSEPLATFORM)))
-			{
-				mo->floorz = *rover->topheight;
-			}
-			if (*rover->bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2)
-				&& (/*mo->z + mo->height <= *rover->bottomheight ||*/ !(rover->flags & FF_PLATFORM)))
-			{
-				mo->ceilingz = *rover->bottomheight;
-			}
+		delta1 = mo->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
+		delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
+		if (*rover->topheight > mo->floorz && abs(delta1) < abs(delta2)
+			&& !(rover->flags & FF_REVERSEPLATFORM))
+		{
+			mo->floorz = *rover->topheight;
+		}
+		if (*rover->bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2)
+			&& !(rover->flags & FF_PLATFORM))
+		{
+			mo->ceilingz = *rover->bottomheight;
+		}
+	}
+}
+
+//
+// P_AdjustMobjFloorZ_PolyObjs
+//
+// Utility function for P_ZMovement and related
+// Adjusts mo->floorz/mo->ceiling accordingly for PolyObjs
+//
+static void P_AdjustMobjFloorZ_PolyObjs(mobj_t *mo, subsector_t *subsec)
+{
+	polyobj_t *po = subsec->polyList;
+	sector_t *polysec;
+	fixed_t delta1, delta2, thingtop;
+	fixed_t polytop, polybottom;
+
+	I_Assert(mo != NULL);
+	I_Assert(!P_MobjWasRemoved(mo));
+
+	thingtop = mo->z + mo->height;
+
+	while(po)
+	{
+		if (!P_MobjInsidePolyobj(po, mo) || !(po->flags & POF_SOLID))
+		{
+			po = (polyobj_t *)(po->link.next);
+			continue;
+		}
+
+		// We're inside it! Yess...
+		polysec = po->lines[0]->backsector;
+
+		if (po->flags & POF_CLIPPLANES)
+		{
+			polytop = polysec->ceilingheight;
+			polybottom = polysec->floorheight;
+		}
+		else
+		{
+			polytop = INT32_MAX;
+			polybottom = INT32_MIN;
 		}
+
+		delta1 = mo->z - (polybottom + ((polytop - polybottom)/2));
+		delta2 = thingtop - (polybottom + ((polytop - polybottom)/2));
+
+		if (polytop > mo->floorz && abs(delta1) < abs(delta2))
+			mo->floorz = polytop;
+
+		if (polybottom < mo->ceilingz && abs(delta1) >= abs(delta2))
+			mo->ceilingz = polybottom;
+
+		po = (polyobj_t *)(po->link.next);
 	}
+}
+
+static void P_RingZMovement(mobj_t *mo)
+{
+	I_Assert(mo != NULL);
+	I_Assert(!P_MobjWasRemoved(mo));
+
+	// Intercept the stupid 'fall through 3dfloors' bug
+	if (mo->subsector->sector->ffloors)
+		P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 1);
+	if (mo->subsector->polyList)
+		P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector);
 
 	// adjust height
 	if (mo->pmomz && mo->z != mo->floorz)
@@ -1443,7 +1536,7 @@ boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover)
 	I_Assert(mo != NULL);
 	I_Assert(!P_MobjWasRemoved(mo));
 
-	if ((rover->flags & FF_SWIMMABLE) && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3
+	if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3
 		&& !(rover->master->flags & ML_BLOCKMONSTERS)
 		&& ((rover->master->flags & ML_EFFECT3) || mo->z-mo->momz > *rover->topheight - FixedMul(16*FRACUNIT, mo->scale)))
 			return true;
@@ -1464,55 +1557,9 @@ static boolean P_ZMovement(mobj_t *mo)
 
 	// Intercept the stupid 'fall through 3dfloors' bug
 	if (mo->subsector->sector->ffloors)
-	{
-		ffloor_t *rover;
-		fixed_t delta1, delta2, thingtop = mo->z + mo->height;
-
-		for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next)
-		{
-#if 0 // I question the utility of having four seperate z movement functions.
-			if (!(rover->flags & FF_EXISTS)
-				|| (!((((rover->flags & FF_BLOCKPLAYER) && mo->player)
-				|| ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) || rover->flags & FF_QUICKSAND)
-				|| (rover->flags & FF_SWIMMABLE)))
-			{
-				continue;
-			}
-#else
-			if (!(rover->flags & FF_EXISTS))
-				continue;
-
-			if (mo->player && P_CheckSolidLava(mo, rover)) // only the player should be affected
-				;
-			else if (!((((rover->flags & FF_BLOCKPLAYER) && mo->player)
-				|| ((rover->flags & FF_BLOCKOTHERS) && !mo->player))
-				|| rover->flags & FF_QUICKSAND))
-				continue;
-#endif
-			if (rover->flags & FF_QUICKSAND)
-			{
-				if (mo->z < *rover->topheight && *rover->bottomheight < thingtop)
-				{
-					if (mo->floorz < mo->z)
-						mo->floorz = mo->z;
-				}
-				continue;
-			}
-
-			delta1 = mo->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			if (*rover->topheight > mo->floorz && abs(delta1) < abs(delta2)
-				&& (!(rover->flags & FF_REVERSEPLATFORM)))
-			{
-				mo->floorz = *rover->topheight;
-			}
-			if (*rover->bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2)
-				&& (/*mo->z + mo->height <= *rover->bottomheight ||*/ !(rover->flags & FF_PLATFORM)))
-			{
-				mo->ceilingz = *rover->bottomheight;
-			}
-		}
-	}
+		P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0);
+	if (mo->subsector->polyList)
+		P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector);
 
 	// adjust height
 	if (mo->pmomz && mo->z != mo->floorz)
@@ -1922,45 +1969,9 @@ static void P_PlayerZMovement(mobj_t *mo)
 
 	// Intercept the stupid 'fall through 3dfloors' bug
 	if (mo->subsector->sector->ffloors)
-	{
-		ffloor_t *rover;
-		fixed_t delta1, delta2;
-		INT32 thingtop = mo->z + mo->height;
-
-		for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next)
-		{
-			if (!(rover->flags & FF_EXISTS))
-				continue;
-
-			if (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))
-				;
-			else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND))
-				continue;
-
-			if (rover->flags & FF_QUICKSAND)
-			{
-				if (mo->z < *rover->topheight && *rover->bottomheight < thingtop)
-				{
-					if (mo->floorz < mo->z)
-						mo->floorz = mo->z;
-				}
-				continue; // This is so you can jump/spring up through quicksand from below.
-			}
-
-			delta1 = mo->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			if (*rover->topheight > mo->floorz && abs(delta1) < abs(delta2)
-				&& (!(rover->flags & FF_REVERSEPLATFORM)))
-			{
-				mo->floorz = *rover->topheight;
-			}
-			if (*rover->bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2)
-				&& (/*mo->z + mo->height <= *rover->bottomheight ||*/ !(rover->flags & FF_PLATFORM)))
-			{
-				mo->ceilingz = *rover->bottomheight;
-			}
-		}
-	}
+		P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0);
+	if (mo->subsector->polyList)
+		P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector);
 
 	// check for smooth step up
 	if ((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height > mo->ceilingz)
@@ -2052,27 +2063,25 @@ static void P_PlayerZMovement(mobj_t *mo)
 
 								while(po)
 								{
-									if (!P_MobjInsidePolyobj(po, mo))
+									if (!P_MobjInsidePolyobj(po, mo) || !(po->flags & POF_SOLID))
 									{
 										po = (polyobj_t *)(po->link.next);
 										continue;
 									}
 
+									// We're inside it! Yess...
 									polysec = po->lines[0]->backsector;
 
 									// Moving polyobjects should act like conveyors if the player lands on one. (I.E. none of the momentum cut thing below) -Red
-									if ((mo->z == polysec->ceilingheight || mo->z+mo->height == polysec->floorheight) && (po->flags & POF_SOLID) && po->thinker)
+									if ((mo->z == polysec->ceilingheight || mo->z+mo->height == polysec->floorheight) && po->thinker)
 										stopmovecut = true;
 
-									if (!(po->flags & POF_LDEXEC)
-										|| !(po->flags & POF_SOLID))
+									if (!(po->flags & POF_LDEXEC))
 									{
 										po = (polyobj_t *)(po->link.next);
 										continue;
 									}
 
-									// We're inside it! Yess...
-
 									if (mo->z == polysec->ceilingheight)
 									{
 										// We're landing on a PO, so check for
@@ -2241,42 +2250,9 @@ static boolean P_SceneryZMovement(mobj_t *mo)
 {
 	// Intercept the stupid 'fall through 3dfloors' bug
 	if (mo->subsector->sector->ffloors)
-	{
-		ffloor_t *rover;
-		fixed_t delta1, delta2;
-		INT32 thingtop = mo->z + mo->height;
-
-		for (rover = mo->subsector->sector->ffloors; rover; rover = rover->next)
-		{
-			if (!(rover->flags & FF_EXISTS))
-				continue;
-
-			if ((!(rover->flags & FF_BLOCKOTHERS || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE)))
-				continue;
-
-			if (rover->flags & FF_QUICKSAND)
-			{
-				if (mo->z < *rover->topheight && *rover->bottomheight < thingtop)
-				{
-					mo->floorz = mo->z;
-					continue;
-				}
-			}
-
-			delta1 = mo->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			if (*rover->topheight > mo->floorz && abs(delta1) < abs(delta2)
-				&& (!(rover->flags & FF_REVERSEPLATFORM)))
-			{
-				mo->floorz = *rover->topheight;
-			}
-			if (*rover->bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2)
-				&& (/*mo->z + mo->height <= *rover->bottomheight ||*/ !(rover->flags & FF_PLATFORM)))
-			{
-				mo->ceilingz = *rover->bottomheight;
-			}
-		}
-	}
+		P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 2);
+	if (mo->subsector->polyList)
+		P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector);
 
 	// adjust height
 	if (mo->pmomz && mo->z != mo->floorz)
@@ -3371,11 +3347,7 @@ static void P_Boss2Thinker(mobj_t *mobj)
 	if (!mobj->movecount)
 		mobj->flags2 &= ~MF2_FRET;
 
-	if (!mobj->tracer
-#ifdef CHAOSISNOTDEADYET
-		&& gametype != GT_CHAOS
-#endif
-		)
+	if (!mobj->tracer)
 	{
 		var1 = 0;
 		A_BossJetFume(mobj);
@@ -3398,11 +3370,7 @@ static void P_Boss2Thinker(mobj_t *mobj)
 		return;
 	}
 
-	if (mobj->state == &states[mobj->info->spawnstate] && mobj->health > mobj->info->damage
-#ifdef CHAOSISNOTDEADYET
-	&& gametype != GT_CHAOS
-#endif
-	)
+	if (mobj->state == &states[mobj->info->spawnstate] && mobj->health > mobj->info->damage)
 		A_Boss2Chase(mobj);
 	else if (mobj->health > 0 && mobj->state != &states[mobj->info->painstate] && mobj->state != &states[mobjinfo[mobj->info->missilestate].raisestate])
 	{
@@ -5116,32 +5084,6 @@ void P_SetScale(mobj_t *mobj, fixed_t newscale)
 	}
 }
 
-// Returns true if no boss with health is in the level.
-// Used for Chaos mode
-
-#ifdef CHAOSISNOTDEADYET
-static boolean P_BossDoesntExist(void)
-{
-	thinker_t *th;
-	mobj_t *mo2;
-
-	// scan the thinkers
-	for (th = thinkercap.next; th != &thinkercap; th = th->next)
-	{
-		if (th->function.acp1 != (actionf_p1)P_MobjThinker)
-			continue;
-
-		mo2 = (mobj_t *)th;
-
-		if (mo2->flags & MF_BOSS && mo2->health)
-			return false;
-	}
-
-	// No boss found!
-	return true;
-}
-#endif
-
 void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on your target
 {
 	fixed_t dist, ndist, speedmul;
@@ -6130,14 +6072,6 @@ void P_MobjThinker(mobj_t *mobj)
 					return;
 				}
 
-#ifdef CHAOSISNOTDEADYET
-				if (gametype == GT_CHAOS && mobj->target->health <= 0)
-				{
-					P_RemoveMobj(mobj);
-					return;
-				}
-#endif
-
 				jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale));
 				jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale));
 
@@ -6209,14 +6143,6 @@ void P_MobjThinker(mobj_t *mobj)
 					return;
 				}
 
-#ifdef CHAOSISNOTDEADYET
-				if (gametype == GT_CHAOS && mobj->target->health <= 0)
-				{
-					P_RemoveMobj(mobj);
-					return;
-				}
-#endif
-
 				jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-60*FRACUNIT, mobj->target->scale));
 				jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-60*FRACUNIT, mobj->target->scale));
 
@@ -6239,13 +6165,6 @@ void P_MobjThinker(mobj_t *mobj)
 					return;
 				}
 
-#ifdef CHAOSISNOTDEADYET
-				if (gametype == GT_CHAOS && mobj->target->health <= 0)
-				{
-					P_RemoveMobj(mobj);
-					return;
-				}
-#endif
 				P_UnsetThingPosition(mobj);
 				mobj->x = mobj->target->x;
 				mobj->y = mobj->target->y;
@@ -6677,148 +6596,6 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
 					}
 					P_RemoveMobj(mobj); // make sure they disappear
 					return;
-				case MT_CHAOSSPAWNER: // Chaos Mode spawner thingy
-				{
-					// 8 enemies: Blue Crawla, Red Crawla, Crawla Commander,
-					//            Jett-Synn Bomber, Jett-Synn Gunner, Skim,
-					//            Egg Mobile, Egg Slimer.
-					// Max. 3 chances per enemy.
-
-#ifdef CHAOSISNOTDEADYET
-
-					mobjtype_t spawnchance[8*3], enemy;
-					mobj_t *spawnedmo;
-					INT32 i = 0, numchoices = 0, stop;
-					fixed_t sfloorz, space, airspace, spawnz[8*3];
-
-					sfloorz = mobj->floorz;
-					space = mobj->ceilingz - sfloorz;
-
-					// This makes the assumption there is no gravity-defying water.
-					// A fair assumption to make, if you ask me.
-					airspace = min(space, mobj->ceilingz - mobj->watertop);
-
-					mobj->fuse = cv_chaos_spawnrate.value*TICRATE;
-					prandom = P_Random(); // Gotta love those random numbers!
-
-					if (cv_chaos_bluecrawla.value && space >= mobjinfo[MT_BLUECRAWLA].height)
-					{
-						stop = i + cv_chaos_bluecrawla.value;
-						for (; i < stop; i++)
-						{
-							spawnchance[i] = MT_BLUECRAWLA;
-							spawnz[i] = sfloorz;
-							numchoices++;
-						}
-					}
-					if (cv_chaos_redcrawla.value && space >= mobjinfo[MT_REDCRAWLA].height)
-					{
-						stop = i + cv_chaos_redcrawla.value;
-						for (; i < stop; i++)
-						{
-							spawnchance[i] = MT_REDCRAWLA;
-							spawnz[i] = sfloorz;
-							numchoices++;
-						}
-					}
-					if (cv_chaos_crawlacommander.value
-						&& space >= mobjinfo[MT_CRAWLACOMMANDER].height + 33*FRACUNIT)
-					{
-						stop = i + cv_chaos_crawlacommander.value;
-						for (; i < stop; i++)
-						{
-							spawnchance[i] = MT_CRAWLACOMMANDER;
-							spawnz[i] = sfloorz + 33*FRACUNIT;
-							numchoices++;
-						}
-					}
-					if (cv_chaos_jettysynbomber.value
-						&& airspace >= mobjinfo[MT_JETTBOMBER].height + 33*FRACUNIT)
-					{
-						stop = i + cv_chaos_jettysynbomber.value;
-						for (; i < stop; i++)
-						{
-							spawnchance[i] = MT_JETTBOMBER;
-							spawnz[i] = max(sfloorz, mobj->watertop) + 33*FRACUNIT;
-							numchoices++;
-						}
-					}
-					if (cv_chaos_jettysyngunner.value
-						&& airspace >= mobjinfo[MT_JETTGUNNER].height + 33*FRACUNIT)
-					{
-						stop = i + cv_chaos_jettysyngunner.value;
-						for (; i < stop; i++)
-						{
-							spawnchance[i] = MT_JETTGUNNER;
-							spawnz[i] = max(sfloorz, mobj->watertop) + 33*FRACUNIT;
-							numchoices++;
-						}
-					}
-					if (cv_chaos_skim.value
-						&& mobj->watertop < mobj->ceilingz - mobjinfo[MT_SKIM].height
-						&& mobj->watertop - sfloorz > mobjinfo[MT_SKIM].height/2)
-					{
-						stop = i + cv_chaos_skim.value;
-						for (; i < stop; i++)
-						{
-							spawnchance[i] = MT_SKIM;
-							spawnz[i] = mobj->watertop;
-							numchoices++;
-						}
-					}
-					if (P_BossDoesntExist())
-					{
-						if (cv_chaos_eggmobile1.value
-							&& space >= mobjinfo[MT_EGGMOBILE].height + 33*FRACUNIT)
-						{
-							stop = i + cv_chaos_eggmobile1.value;
-							for (; i < stop; i++)
-							{
-								spawnchance[i] = MT_EGGMOBILE;
-								spawnz[i] = sfloorz + 33*FRACUNIT;
-								numchoices++;
-							}
-						}
-						if (cv_chaos_eggmobile2.value
-							&& space >= mobjinfo[MT_EGGMOBILE2].height + 33*FRACUNIT)
-						{
-							stop = i + cv_chaos_eggmobile2.value;
-							for (; i < stop; i++)
-							{
-								spawnchance[i] = MT_EGGMOBILE2;
-								spawnz[i] = sfloorz + 33*FRACUNIT;
-								numchoices++;
-							}
-						}
-					}
-
-					if (numchoices)
-					{
-						fixed_t fogz;
-
-						i = prandom % numchoices;
-						enemy = spawnchance[i];
-
-						fogz = spawnz[i] - 32*FRACUNIT;
-						if (fogz < sfloorz)
-							fogz = sfloorz;
-
-						spawnedmo = P_SpawnMobj(mobj->x, mobj->y, spawnz[i], enemy);
-						P_SpawnMobj(mobj->x, mobj->y, fogz, MT_TFOG);
-
-						P_SupermanLook4Players(spawnedmo);
-						if (spawnedmo->target && spawnedmo->type != MT_SKIM)
-							P_SetMobjState(spawnedmo, spawnedmo->info->seestate);
-
-						if (spawnedmo->flags & MF_BOSS)
-						{
-							spawnedmo->flags2 |= MF2_CHAOSBOSS;
-							spawnedmo->momx = spawnedmo->momy = 0;
-						}
-					}
-#endif
-					break;
-				}
 				case MT_METALSONIC_BATTLE:
 					break; // don't remove
 				case MT_SPIKE:
@@ -8178,7 +7955,8 @@ void P_SpawnMapThing(mapthing_t *mthing)
 
 	if (i == NUMMOBJTYPES)
 	{
-		if (mthing->type == 3328) // 3D Mode start Thing
+		if (mthing->type == 3328 // 3D Mode start Thing
+		 || mthing->type == 750) // Chaos mode spawn
 			return;
 		CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y);
 		i = MT_UNKNOWN;
@@ -8597,15 +8375,6 @@ ML_NOCLIMB : Direction not controllable
 		if (mthing->angle > 0)
 			mobj->health = mthing->angle;
 		break;
-	case MT_CHAOSSPAWNER:
-#ifndef CHAOSISNOTDEADYET
-		return;
-#else
-		if (gametype != GT_CHAOS)
-			return;
-		mobj->fuse = P_Random()*2;
-		break;
-#endif
 	case MT_TRAPGOYLE:
 	case MT_TRAPGOYLEUP:
 	case MT_TRAPGOYLEDOWN:
diff --git a/src/p_pspr.h b/src/p_pspr.h
index 339dd1f96cbb32f1497fa3c4b62669d087b41af7..e0b57675cd45568e3826c656d8edf17fd032f2ae 100644
--- a/src/p_pspr.h
+++ b/src/p_pspr.h
@@ -43,6 +43,16 @@
 #define FF_TRANSMASK 0xf0000
 /// \brief shift for FF_TRANSMASK
 #define FF_TRANSSHIFT 16
+/// \brief preshifted translucency flags
+#define FF_TRANS10 (tr_trans10<<FF_TRANSSHIFT)
+#define FF_TRANS20 (tr_trans20<<FF_TRANSSHIFT)
+#define FF_TRANS30 (tr_trans30<<FF_TRANSSHIFT)
+#define FF_TRANS40 (tr_trans40<<FF_TRANSSHIFT)
+#define FF_TRANS50 (tr_trans50<<FF_TRANSSHIFT)
+#define FF_TRANS60 (tr_trans60<<FF_TRANSSHIFT)
+#define FF_TRANS70 (tr_trans70<<FF_TRANSSHIFT)
+#define FF_TRANS80 (tr_trans80<<FF_TRANSSHIFT)
+#define FF_TRANS90 (tr_trans90<<FF_TRANSSHIFT)
 
 /**	\brief translucency tables
 
diff --git a/src/p_saveg.c b/src/p_saveg.c
index bf64d9a2b2bf11d49df16b7899a18ca70df850a0..851d653fa2c2736d8a59a720f9a493b4f7ee5ffb 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -990,6 +990,241 @@ static inline UINT32 SavePlayer(const player_t *player)
 	return 0xFFFFFFFF;
 }
 
+//
+// SaveMobjThinker
+//
+// Saves a mobj_t thinker
+//
+static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
+{
+	const mobj_t *mobj = (const mobj_t *)th;
+	UINT32 diff;
+	UINT16 diff2;
+
+	// Ignore stationary hoops - these will be respawned from mapthings.
+	if (mobj->type == MT_HOOP)
+		return;
+
+	// These are NEVER saved.
+	if (mobj->type == MT_HOOPCOLLIDE)
+		return;
+
+	// This hoop has already been collected.
+	if (mobj->type == MT_HOOPCENTER && mobj->threshold == 4242)
+		return;
+
+	if (mobj->spawnpoint && mobj->info->doomednum != -1)
+	{
+		// spawnpoint is not modified but we must save it since it is an identifier
+		diff = MD_SPAWNPOINT;
+
+		if ((mobj->x != mobj->spawnpoint->x << FRACBITS) ||
+			(mobj->y != mobj->spawnpoint->y << FRACBITS) ||
+			(mobj->angle != FixedAngle(mobj->spawnpoint->angle*FRACUNIT)))
+			diff |= MD_POS;
+
+		if (mobj->info->doomednum != mobj->spawnpoint->type)
+			diff |= MD_TYPE;
+	}
+	else
+		diff = MD_POS | MD_TYPE; // not a map spawned thing so make it from scratch
+
+	diff2 = 0;
+
+	// not the default but the most probable
+	if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0)
+		diff |= MD_MOM;
+	if (mobj->radius != mobj->info->radius)
+		diff |= MD_RADIUS;
+	if (mobj->height != mobj->info->height)
+		diff |= MD_HEIGHT;
+	if (mobj->flags != mobj->info->flags)
+		diff |= MD_FLAGS;
+	if (mobj->flags2)
+		diff |= MD_FLAGS2;
+	if (mobj->health != mobj->info->spawnhealth)
+		diff |= MD_HEALTH;
+	if (mobj->reactiontime != mobj->info->reactiontime)
+		diff |= MD_RTIME;
+	if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate)
+		diff |= MD_STATE;
+	if (mobj->tics != mobj->state->tics)
+		diff |= MD_TICS;
+	if (mobj->sprite != mobj->state->sprite)
+		diff |= MD_SPRITE;
+	if (mobj->frame != mobj->state->frame)
+		diff |= MD_FRAME;
+	if (mobj->eflags)
+		diff |= MD_EFLAGS;
+	if (mobj->player)
+		diff |= MD_PLAYER;
+
+	if (mobj->movedir)
+		diff |= MD_MOVEDIR;
+	if (mobj->movecount)
+		diff |= MD_MOVECOUNT;
+	if (mobj->threshold)
+		diff |= MD_THRESHOLD;
+	if (mobj->lastlook != -1)
+		diff |= MD_LASTLOOK;
+	if (mobj->target)
+		diff |= MD_TARGET;
+	if (mobj->tracer)
+		diff |= MD_TRACER;
+	if (mobj->friction != ORIG_FRICTION)
+		diff |= MD_FRICTION;
+	if (mobj->movefactor != ORIG_FRICTION_FACTOR)
+		diff |= MD_MOVEFACTOR;
+	if (mobj->fuse)
+		diff |= MD_FUSE;
+	if (mobj->watertop)
+		diff |= MD_WATERTOP;
+	if (mobj->waterbottom)
+		diff |= MD_WATERBOTTOM;
+	if (mobj->scale != FRACUNIT)
+		diff |= MD_SCALE;
+	if (mobj->destscale != mobj->scale)
+		diff |= MD_DSCALE;
+	if (mobj->scalespeed != FRACUNIT/12)
+		diff2 |= MD2_SCALESPEED;
+
+	if (mobj == redflag)
+		diff |= MD_REDFLAG;
+	if (mobj == blueflag)
+		diff |= MD_BLUEFLAG;
+
+	if (mobj->cusval)
+		diff2 |= MD2_CUSVAL;
+	if (mobj->cvmem)
+		diff2 |= MD2_CVMEM;
+	if (mobj->color)
+		diff2 |= MD2_COLOR;
+	if (mobj->skin)
+		diff2 |= MD2_SKIN;
+	if (mobj->extravalue1)
+		diff2 |= MD2_EXTVAL1;
+	if (mobj->extravalue2)
+		diff2 |= MD2_EXTVAL2;
+	if (mobj->hnext)
+		diff2 |= MD2_HNEXT;
+	if (mobj->hprev)
+		diff2 |= MD2_HPREV;
+	if (diff2 != 0)
+		diff |= MD_MORE;
+
+	// Scrap all of that. If we're a hoop center, this is ALL we're saving.
+	if (mobj->type == MT_HOOPCENTER)
+		diff = MD_SPAWNPOINT;
+
+	WRITEUINT8(save_p, type);
+	WRITEUINT32(save_p, diff);
+	if (diff & MD_MORE)
+		WRITEUINT16(save_p, diff2);
+
+	// save pointer, at load time we will search this pointer to reinitilize pointers
+	WRITEUINT32(save_p, (size_t)mobj);
+
+	WRITEFIXED(save_p, mobj->z); // Force this so 3dfloor problems don't arise.
+	WRITEFIXED(save_p, mobj->floorz);
+	WRITEFIXED(save_p, mobj->ceilingz);
+
+	if (diff & MD_SPAWNPOINT)
+	{
+		size_t z;
+
+		for (z = 0; z < nummapthings; z++)
+			if (&mapthings[z] == mobj->spawnpoint)
+				WRITEUINT16(save_p, z);
+		if (mobj->type == MT_HOOPCENTER)
+			return;
+	}
+
+	if (diff & MD_TYPE)
+		WRITEUINT32(save_p, mobj->type);
+	if (diff & MD_POS)
+	{
+		WRITEFIXED(save_p, mobj->x);
+		WRITEFIXED(save_p, mobj->y);
+		WRITEANGLE(save_p, mobj->angle);
+	}
+	if (diff & MD_MOM)
+	{
+		WRITEFIXED(save_p, mobj->momx);
+		WRITEFIXED(save_p, mobj->momy);
+		WRITEFIXED(save_p, mobj->momz);
+	}
+	if (diff & MD_RADIUS)
+		WRITEFIXED(save_p, mobj->radius);
+	if (diff & MD_HEIGHT)
+		WRITEFIXED(save_p, mobj->height);
+	if (diff & MD_FLAGS)
+		WRITEUINT32(save_p, mobj->flags);
+	if (diff & MD_FLAGS2)
+		WRITEUINT32(save_p, mobj->flags2);
+	if (diff & MD_HEALTH)
+		WRITEINT32(save_p, mobj->health);
+	if (diff & MD_RTIME)
+		WRITEINT32(save_p, mobj->reactiontime);
+	if (diff & MD_STATE)
+		WRITEUINT16(save_p, mobj->state-states);
+	if (diff & MD_TICS)
+		WRITEINT32(save_p, mobj->tics);
+	if (diff & MD_SPRITE)
+		WRITEUINT16(save_p, mobj->sprite);
+	if (diff & MD_FRAME)
+		WRITEUINT32(save_p, mobj->frame);
+	if (diff & MD_EFLAGS)
+		WRITEUINT8(save_p, mobj->eflags);
+	if (diff & MD_PLAYER)
+		WRITEUINT8(save_p, mobj->player-players);
+	if (diff & MD_MOVEDIR)
+		WRITEANGLE(save_p, mobj->movedir);
+	if (diff & MD_MOVECOUNT)
+		WRITEINT32(save_p, mobj->movecount);
+	if (diff & MD_THRESHOLD)
+		WRITEINT32(save_p, mobj->threshold);
+	if (diff & MD_LASTLOOK)
+		WRITEINT32(save_p, mobj->lastlook);
+	if (diff & MD_TARGET)
+		WRITEUINT32(save_p, mobj->target->mobjnum);
+	if (diff & MD_TRACER)
+		WRITEUINT32(save_p, mobj->tracer->mobjnum);
+	if (diff & MD_FRICTION)
+		WRITEFIXED(save_p, mobj->friction);
+	if (diff & MD_MOVEFACTOR)
+		WRITEFIXED(save_p, mobj->movefactor);
+	if (diff & MD_FUSE)
+		WRITEINT32(save_p, mobj->fuse);
+	if (diff & MD_WATERTOP)
+		WRITEFIXED(save_p, mobj->watertop);
+	if (diff & MD_WATERBOTTOM)
+		WRITEFIXED(save_p, mobj->waterbottom);
+	if (diff & MD_SCALE)
+		WRITEFIXED(save_p, mobj->scale);
+	if (diff & MD_DSCALE)
+		WRITEFIXED(save_p, mobj->destscale);
+	if (diff2 & MD2_SCALESPEED)
+		WRITEFIXED(save_p, mobj->scalespeed);
+	if (diff2 & MD2_CUSVAL)
+		WRITEINT32(save_p, mobj->cusval);
+	if (diff2 & MD2_CVMEM)
+		WRITEINT32(save_p, mobj->cvmem);
+	if (diff2 & MD2_SKIN)
+		WRITEUINT8(save_p, (UINT8)((skin_t *)mobj->skin - skins));
+	if (diff2 & MD2_COLOR)
+		WRITEUINT8(save_p, mobj->color);
+	if (diff2 & MD2_EXTVAL1)
+		WRITEINT32(save_p, mobj->extravalue1);
+	if (diff2 & MD2_EXTVAL2)
+		WRITEINT32(save_p, mobj->extravalue2);
+	if (diff2 & MD2_HNEXT)
+		WRITEUINT32(save_p, mobj->hnext->mobjnum);
+	if (diff2 & MD2_HPREV)
+		WRITEUINT32(save_p, mobj->hprev->mobjnum);
+
+	WRITEUINT32(save_p, mobj->mobjnum);
+}
+
 //
 // SaveSpecialLevelThinker
 //
@@ -1395,9 +1630,6 @@ static inline void SaveWhatThinker(const thinker_t *th, const UINT8 type)
 static void P_NetArchiveThinkers(void)
 {
 	const thinker_t *th;
-	const mobj_t *mobj;
-	UINT32 diff;
-	UINT16 diff2;
 
 	WRITEUINT32(save_p, ARCHIVEBLOCK_THINKERS);
 
@@ -1406,230 +1638,8 @@ static void P_NetArchiveThinkers(void)
 	{
 		if (th->function.acp1 == (actionf_p1)P_MobjThinker)
 		{
-			mobj = (const mobj_t *)th;
-
-			// Ignore stationary hoops - these will be respawned from mapthings.
-			if (mobj->type == MT_HOOP)
-				continue;
-
-			// These are NEVER saved.
-			if (mobj->type == MT_HOOPCOLLIDE)
-				continue;
-
-			// This hoop has already been collected.
-			if (mobj->type == MT_HOOPCENTER && mobj->threshold == 4242)
-				continue;
-
-			if (mobj->spawnpoint && mobj->info->doomednum != -1)
-			{
-				// spawnpoint is not modified but we must save it since it is an identifier
-				diff = MD_SPAWNPOINT;
-
-				if ((mobj->x != mobj->spawnpoint->x << FRACBITS) ||
-					(mobj->y != mobj->spawnpoint->y << FRACBITS) ||
-					(mobj->angle != FixedAngle(mobj->spawnpoint->angle*FRACUNIT)))
-					diff |= MD_POS;
-
-				if (mobj->info->doomednum != mobj->spawnpoint->type)
-					diff |= MD_TYPE;
-			}
-			else
-				diff = MD_POS | MD_TYPE; // not a map spawned thing so make it from scratch
-
-			diff2 = 0;
-
-			// not the default but the most probable
-			if (mobj->momx != 0 || mobj->momy != 0 || mobj->momz != 0)
-				diff |= MD_MOM;
-			if (mobj->radius != mobj->info->radius)
-				diff |= MD_RADIUS;
-			if (mobj->height != mobj->info->height)
-				diff |= MD_HEIGHT;
-			if (mobj->flags != mobj->info->flags)
-				diff |= MD_FLAGS;
-			if (mobj->flags2)
-				diff |= MD_FLAGS2;
-			if (mobj->health != mobj->info->spawnhealth)
-				diff |= MD_HEALTH;
-			if (mobj->reactiontime != mobj->info->reactiontime)
-				diff |= MD_RTIME;
-			if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate)
-				diff |= MD_STATE;
-			if (mobj->tics != mobj->state->tics)
-				diff |= MD_TICS;
-			if (mobj->sprite != mobj->state->sprite)
-				diff |= MD_SPRITE;
-			if (mobj->frame != mobj->state->frame)
-				diff |= MD_FRAME;
-			if (mobj->eflags)
-				diff |= MD_EFLAGS;
-			if (mobj->player)
-				diff |= MD_PLAYER;
-
-			if (mobj->movedir)
-				diff |= MD_MOVEDIR;
-			if (mobj->movecount)
-				diff |= MD_MOVECOUNT;
-			if (mobj->threshold)
-				diff |= MD_THRESHOLD;
-			if (mobj->lastlook != -1)
-				diff |= MD_LASTLOOK;
-			if (mobj->target)
-				diff |= MD_TARGET;
-			if (mobj->tracer)
-				diff |= MD_TRACER;
-			if (mobj->friction != ORIG_FRICTION)
-				diff |= MD_FRICTION;
-			if (mobj->movefactor != ORIG_FRICTION_FACTOR)
-				diff |= MD_MOVEFACTOR;
-			if (mobj->fuse)
-				diff |= MD_FUSE;
-			if (mobj->watertop)
-				diff |= MD_WATERTOP;
-			if (mobj->waterbottom)
-				diff |= MD_WATERBOTTOM;
-			if (mobj->scale != FRACUNIT)
-				diff |= MD_SCALE;
-			if (mobj->destscale != mobj->scale)
-				diff |= MD_DSCALE;
-			if (mobj->scalespeed != FRACUNIT/12)
-				diff2 |= MD2_SCALESPEED;
-
-			if (mobj == redflag)
-				diff |= MD_REDFLAG;
-			if (mobj == blueflag)
-				diff |= MD_BLUEFLAG;
-
-			if (mobj->cusval)
-				diff2 |= MD2_CUSVAL;
-			if (mobj->cvmem)
-				diff2 |= MD2_CVMEM;
-			if (mobj->color)
-				diff2 |= MD2_COLOR;
-			if (mobj->skin)
-				diff2 |= MD2_SKIN;
-			if (mobj->extravalue1)
-				diff2 |= MD2_EXTVAL1;
-			if (mobj->extravalue2)
-				diff2 |= MD2_EXTVAL2;
-			if (mobj->hnext)
-				diff2 |= MD2_HNEXT;
-			if (mobj->hprev)
-				diff2 |= MD2_HPREV;
-			if (diff2 != 0)
-				diff |= MD_MORE;
-
-			// Scrap all of that. If we're a hoop center, this is ALL we're saving.
-			if (mobj->type == MT_HOOPCENTER)
-				diff = MD_SPAWNPOINT;
-
-			WRITEUINT8(save_p, tc_mobj);
-			WRITEUINT32(save_p, diff);
-			if (diff & MD_MORE)
-				WRITEUINT16(save_p, diff2);
-
-			// save pointer, at load time we will search this pointer to reinitilize pointers
-			WRITEUINT32(save_p, (size_t)mobj);
-
-			WRITEFIXED(save_p, mobj->z); // Force this so 3dfloor problems don't arise.
-			WRITEFIXED(save_p, mobj->floorz);
-			WRITEFIXED(save_p, mobj->ceilingz);
-
-			if (diff & MD_SPAWNPOINT)
-			{
-				size_t z;
-
-				for (z = 0; z < nummapthings; z++)
-					if (&mapthings[z] == mobj->spawnpoint)
-						WRITEUINT16(save_p, z);
-				if (mobj->type == MT_HOOPCENTER)
-					continue;
-			}
-
-			if (diff & MD_TYPE)
-				WRITEUINT32(save_p, mobj->type);
-			if (diff & MD_POS)
-			{
-				WRITEFIXED(save_p, mobj->x);
-				WRITEFIXED(save_p, mobj->y);
-				WRITEANGLE(save_p, mobj->angle);
-			}
-			if (diff & MD_MOM)
-			{
-				WRITEFIXED(save_p, mobj->momx);
-				WRITEFIXED(save_p, mobj->momy);
-				WRITEFIXED(save_p, mobj->momz);
-			}
-			if (diff & MD_RADIUS)
-				WRITEFIXED(save_p, mobj->radius);
-			if (diff & MD_HEIGHT)
-				WRITEFIXED(save_p, mobj->height);
-			if (diff & MD_FLAGS)
-				WRITEUINT32(save_p, mobj->flags);
-			if (diff & MD_FLAGS2)
-				WRITEUINT32(save_p, mobj->flags2);
-			if (diff & MD_HEALTH)
-				WRITEINT32(save_p, mobj->health);
-			if (diff & MD_RTIME)
-				WRITEINT32(save_p, mobj->reactiontime);
-			if (diff & MD_STATE)
-				WRITEUINT16(save_p, mobj->state-states);
-			if (diff & MD_TICS)
-				WRITEINT32(save_p, mobj->tics);
-			if (diff & MD_SPRITE)
-				WRITEUINT16(save_p, mobj->sprite);
-			if (diff & MD_FRAME)
-				WRITEUINT32(save_p, mobj->frame);
-			if (diff & MD_EFLAGS)
-				WRITEUINT8(save_p, mobj->eflags);
-			if (diff & MD_PLAYER)
-				WRITEUINT8(save_p, mobj->player-players);
-			if (diff & MD_MOVEDIR)
-				WRITEANGLE(save_p, mobj->movedir);
-			if (diff & MD_MOVECOUNT)
-				WRITEINT32(save_p, mobj->movecount);
-			if (diff & MD_THRESHOLD)
-				WRITEINT32(save_p, mobj->threshold);
-			if (diff & MD_LASTLOOK)
-				WRITEINT32(save_p, mobj->lastlook);
-			if (diff & MD_TARGET)
-				WRITEUINT32(save_p, mobj->target->mobjnum);
-			if (diff & MD_TRACER)
-				WRITEUINT32(save_p, mobj->tracer->mobjnum);
-			if (diff & MD_FRICTION)
-				WRITEFIXED(save_p, mobj->friction);
-			if (diff & MD_MOVEFACTOR)
-				WRITEFIXED(save_p, mobj->movefactor);
-			if (diff & MD_FUSE)
-				WRITEINT32(save_p, mobj->fuse);
-			if (diff & MD_WATERTOP)
-				WRITEFIXED(save_p, mobj->watertop);
-			if (diff & MD_WATERBOTTOM)
-				WRITEFIXED(save_p, mobj->waterbottom);
-			if (diff & MD_SCALE)
-				WRITEFIXED(save_p, mobj->scale);
-			if (diff & MD_DSCALE)
-				WRITEFIXED(save_p, mobj->destscale);
-			if (diff2 & MD2_SCALESPEED)
-				WRITEFIXED(save_p, mobj->scalespeed);
-			if (diff2 & MD2_CUSVAL)
-				WRITEINT32(save_p, mobj->cusval);
-			if (diff2 & MD2_CVMEM)
-				WRITEINT32(save_p, mobj->cvmem);
-			if (diff2 & MD2_SKIN)
-				WRITEUINT8(save_p, (UINT8)((skin_t *)mobj->skin - skins));
-			if (diff2 & MD2_COLOR)
-				WRITEUINT8(save_p, mobj->color);
-			if (diff2 & MD2_EXTVAL1)
-				WRITEINT32(save_p, mobj->extravalue1);
-			if (diff2 & MD2_EXTVAL2)
-				WRITEINT32(save_p, mobj->extravalue2);
-			if (diff2 & MD2_HNEXT)
-				WRITEUINT32(save_p, mobj->hnext->mobjnum);
-			if (diff2 & MD2_HPREV)
-				WRITEUINT32(save_p, mobj->hprev->mobjnum);
-
-			WRITEUINT32(save_p, mobj->mobjnum);
+			SaveMobjThinker(th, tc_mobj);
+			continue;
 		}
 #ifdef PARANOIA
 		else if (th->function.acp1 == (actionf_p1)P_RainThinker
@@ -1862,6 +1872,232 @@ static inline player_t *LoadPlayer(UINT32 player)
 	return &players[player];
 }
 
+//
+// LoadMobjThinker
+//
+// Loads a mobj_t from a save game
+//
+static void LoadMobjThinker(actionf_p1 thinker)
+{
+	thinker_t *next;
+	mobj_t *mobj;
+	UINT32 diff;
+	UINT16 diff2;
+	INT32 i;
+	fixed_t z, floorz, ceilingz;
+
+	diff = READUINT32(save_p);
+	if (diff & MD_MORE)
+		diff2 = READUINT16(save_p);
+	else
+		diff2 = 0;
+
+	next = (void *)(size_t)READUINT32(save_p);
+
+	z = READFIXED(save_p); // Force this so 3dfloor problems don't arise.
+	floorz = READFIXED(save_p);
+	ceilingz = READFIXED(save_p);
+
+	if (diff & MD_SPAWNPOINT)
+	{
+		UINT16 spawnpointnum = READUINT16(save_p);
+
+		if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case
+		{
+			P_SpawnHoopsAndRings(&mapthings[spawnpointnum]);
+			return;
+		}
+
+		mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
+
+		mobj->spawnpoint = &mapthings[spawnpointnum];
+		mapthings[spawnpointnum].mobj = mobj;
+	}
+	else
+		mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
+
+	// declare this as a valid mobj as soon as possible.
+	mobj->thinker.function.acp1 = thinker;
+
+	mobj->z = z;
+	mobj->floorz = floorz;
+	mobj->ceilingz = ceilingz;
+
+	if (diff & MD_TYPE)
+		mobj->type = READUINT32(save_p);
+	else
+	{
+		for (i = 0; i < NUMMOBJTYPES; i++)
+			if (mobj->spawnpoint && mobj->spawnpoint->type == mobjinfo[i].doomednum)
+				break;
+		if (i == NUMMOBJTYPES)
+		{
+			if (mobj->spawnpoint)
+				CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type %d\n", mobj->spawnpoint->type);
+			else
+				CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type NULL\n");
+			I_Error("Savegame corrupted");
+		}
+		mobj->type = i;
+	}
+	mobj->info = &mobjinfo[mobj->type];
+	if (diff & MD_POS)
+	{
+		mobj->x = READFIXED(save_p);
+		mobj->y = READFIXED(save_p);
+		mobj->angle = READANGLE(save_p);
+	}
+	else
+	{
+		mobj->x = mobj->spawnpoint->x << FRACBITS;
+		mobj->y = mobj->spawnpoint->y << FRACBITS;
+		mobj->angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT);
+	}
+	if (diff & MD_MOM)
+	{
+		mobj->momx = READFIXED(save_p);
+		mobj->momy = READFIXED(save_p);
+		mobj->momz = READFIXED(save_p);
+	} // otherwise they're zero, and the memset took care of it
+
+	if (diff & MD_RADIUS)
+		mobj->radius = READFIXED(save_p);
+	else
+		mobj->radius = mobj->info->radius;
+	if (diff & MD_HEIGHT)
+		mobj->height = READFIXED(save_p);
+	else
+		mobj->height = mobj->info->height;
+	if (diff & MD_FLAGS)
+		mobj->flags = READUINT32(save_p);
+	else
+		mobj->flags = mobj->info->flags;
+	if (diff & MD_FLAGS2)
+		mobj->flags2 = READUINT32(save_p);
+	if (diff & MD_HEALTH)
+		mobj->health = READINT32(save_p);
+	else
+		mobj->health = mobj->info->spawnhealth;
+	if (diff & MD_RTIME)
+		mobj->reactiontime = READINT32(save_p);
+	else
+		mobj->reactiontime = mobj->info->reactiontime;
+
+	if (diff & MD_STATE)
+		mobj->state = &states[READUINT16(save_p)];
+	else
+		mobj->state = &states[mobj->info->spawnstate];
+	if (diff & MD_TICS)
+		mobj->tics = READINT32(save_p);
+	else
+		mobj->tics = mobj->state->tics;
+	if (diff & MD_SPRITE)
+		mobj->sprite = READUINT16(save_p);
+	else
+		mobj->sprite = mobj->state->sprite;
+	if (diff & MD_FRAME)
+		mobj->frame = READUINT32(save_p);
+	else
+		mobj->frame = mobj->state->frame;
+	if (diff & MD_EFLAGS)
+		mobj->eflags = READUINT8(save_p);
+	if (diff & MD_PLAYER)
+	{
+		i = READUINT8(save_p);
+		mobj->player = &players[i];
+		mobj->player->mo = mobj;
+		// added for angle prediction
+		if (consoleplayer == i)
+			localangle = mobj->angle;
+		if (secondarydisplayplayer == i)
+			localangle2 = mobj->angle;
+	}
+	if (diff & MD_MOVEDIR)
+		mobj->movedir = READANGLE(save_p);
+	if (diff & MD_MOVECOUNT)
+		mobj->movecount = READINT32(save_p);
+	if (diff & MD_THRESHOLD)
+		mobj->threshold = READINT32(save_p);
+	if (diff & MD_LASTLOOK)
+		mobj->lastlook = READINT32(save_p);
+	else
+		mobj->lastlook = -1;
+	if (diff & MD_TARGET)
+		mobj->target = (mobj_t *)(size_t)READUINT32(save_p);
+	if (diff & MD_TRACER)
+		mobj->tracer = (mobj_t *)(size_t)READUINT32(save_p);
+	if (diff & MD_FRICTION)
+		mobj->friction = READFIXED(save_p);
+	else
+		mobj->friction = ORIG_FRICTION;
+	if (diff & MD_MOVEFACTOR)
+		mobj->movefactor = READFIXED(save_p);
+	else
+		mobj->movefactor = ORIG_FRICTION_FACTOR;
+	if (diff & MD_FUSE)
+		mobj->fuse = READINT32(save_p);
+	if (diff & MD_WATERTOP)
+		mobj->watertop = READFIXED(save_p);
+	if (diff & MD_WATERBOTTOM)
+		mobj->waterbottom = READFIXED(save_p);
+	if (diff & MD_SCALE)
+		mobj->scale = READFIXED(save_p);
+	else
+		mobj->scale = FRACUNIT;
+	if (diff & MD_DSCALE)
+		mobj->destscale = READFIXED(save_p);
+	else
+		mobj->destscale = mobj->scale;
+	if (diff2 & MD2_SCALESPEED)
+		mobj->scalespeed = READFIXED(save_p);
+	else
+		mobj->scalespeed = FRACUNIT/12;
+	if (diff2 & MD2_CUSVAL)
+		mobj->cusval = READINT32(save_p);
+	if (diff2 & MD2_CVMEM)
+		mobj->cvmem = READINT32(save_p);
+	if (diff2 & MD2_SKIN)
+		mobj->skin = &skins[READUINT8(save_p)];
+	if (diff2 & MD2_COLOR)
+		mobj->color = READUINT8(save_p);
+	if (diff2 & MD2_EXTVAL1)
+		mobj->extravalue1 = READINT32(save_p);
+	if (diff2 & MD2_EXTVAL2)
+		mobj->extravalue2 = READINT32(save_p);
+	if (diff2 & MD2_HNEXT)
+		mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p);
+	if (diff2 & MD2_HPREV)
+		mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p);
+
+	if (diff & MD_REDFLAG)
+	{
+		redflag = mobj;
+		rflagpoint = mobj->spawnpoint;
+	}
+	if (diff & MD_BLUEFLAG)
+	{
+		blueflag = mobj;
+		bflagpoint = mobj->spawnpoint;
+	}
+
+	// set sprev, snext, bprev, bnext, subsector
+	P_SetThingPosition(mobj);
+
+	mobj->mobjnum = READUINT32(save_p);
+
+	if (mobj->player)
+	{
+		if (mobj->eflags & MFE_VERTICALFLIP)
+			mobj->player->viewz = mobj->z + mobj->height - mobj->player->viewheight;
+		else
+			mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight;
+	}
+
+	P_AddThinker(&mobj->thinker);
+
+	mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function
+}
+
 //
 // LoadSpecialLevelThinker
 //
@@ -2131,11 +2367,15 @@ static void LoadPusherThinker(actionf_p1 thinker)
 static inline void LoadLaserThinker(actionf_p1 thinker)
 {
 	laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL);
+	ffloor_t *rover = NULL;
 	ht->thinker.function.acp1 = thinker;
 	ht->sector = LoadSector(READUINT32(save_p));
-	ht->ffloor = NULL;
 	ht->sec = LoadSector(READUINT32(save_p));
 	ht->sourceline = LoadLine(READUINT32(save_p));
+	for (rover = ht->sector->ffloors; rover; rover = rover->next)
+		if (rover->secnum == (size_t)(ht->sec - sectors)
+		&& rover->master == ht->sourceline)
+			ht->ffloor = rover;
 	P_AddThinker(&ht->thinker);
 }
 
@@ -2333,13 +2573,8 @@ static void P_NetUnArchiveThinkers(void)
 {
 	thinker_t *currentthinker;
 	thinker_t *next;
-	mobj_t *mobj;
-	UINT32 diff;
-	UINT16 diff2;
-	INT32 i;
 	UINT8 tclass;
 	UINT8 restoreNum = false;
-	fixed_t z, floorz, ceilingz;
 
 	if (READUINT32(save_p) != ARCHIVEBLOCK_THINKERS)
 		I_Error("Bad $$$.sav at archive block Thinkers");
@@ -2350,7 +2585,6 @@ static void P_NetUnArchiveThinkers(void)
 	{
 		next = currentthinker->next;
 
-		mobj = (mobj_t *)currentthinker;
 		if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
 			P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it
 		else
@@ -2372,216 +2606,7 @@ static void P_NetUnArchiveThinkers(void)
 		switch (tclass)
 		{
 			case tc_mobj:
-				diff = READUINT32(save_p);
-				if (diff & MD_MORE)
-					diff2 = READUINT16(save_p);
-				else
-					diff2 = 0;
-
-				next = (void *)(size_t)READUINT32(save_p);
-
-				z = READFIXED(save_p); // Force this so 3dfloor problems don't arise.
-				floorz = READFIXED(save_p);
-				ceilingz = READFIXED(save_p);
-
-				if (diff & MD_SPAWNPOINT)
-				{
-					UINT16 spawnpointnum = READUINT16(save_p);
-
-					if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case
-					{
-						P_SpawnHoopsAndRings(&mapthings[spawnpointnum]);
-						continue;
-					}
-
-					mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
-
-					mobj->spawnpoint = &mapthings[spawnpointnum];
-					mapthings[spawnpointnum].mobj = mobj;
-				}
-				else
-					mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
-
-				// declare this as a valid mobj as soon as possible.
-				mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
-
-				mobj->z = z;
-				mobj->floorz = floorz;
-				mobj->ceilingz = ceilingz;
-
-				if (diff & MD_TYPE)
-					mobj->type = READUINT32(save_p);
-				else
-				{
-					for (i = 0; i < NUMMOBJTYPES; i++)
-						if (mobj->spawnpoint && mobj->spawnpoint->type == mobjinfo[i].doomednum)
-							break;
-					if (i == NUMMOBJTYPES)
-					{
-						if (mobj->spawnpoint)
-							CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type %d\n", mobj->spawnpoint->type);
-						else
-							CONS_Alert(CONS_ERROR, "Found mobj with unknown map thing type NULL\n");
-						I_Error("Savegame corrupted");
-					}
-					mobj->type = i;
-				}
-				mobj->info = &mobjinfo[mobj->type];
-				if (diff & MD_POS)
-				{
-					mobj->x = READFIXED(save_p);
-					mobj->y = READFIXED(save_p);
-					mobj->angle = READANGLE(save_p);
-				}
-				else
-				{
-					mobj->x = mobj->spawnpoint->x << FRACBITS;
-					mobj->y = mobj->spawnpoint->y << FRACBITS;
-					mobj->angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT);
-				}
-				if (diff & MD_MOM)
-				{
-					mobj->momx = READFIXED(save_p);
-					mobj->momy = READFIXED(save_p);
-					mobj->momz = READFIXED(save_p);
-				} // otherwise they're zero, and the memset took care of it
-
-				if (diff & MD_RADIUS)
-					mobj->radius = READFIXED(save_p);
-				else
-					mobj->radius = mobj->info->radius;
-				if (diff & MD_HEIGHT)
-					mobj->height = READFIXED(save_p);
-				else
-					mobj->height = mobj->info->height;
-				if (diff & MD_FLAGS)
-					mobj->flags = READUINT32(save_p);
-				else
-					mobj->flags = mobj->info->flags;
-				if (diff & MD_FLAGS2)
-					mobj->flags2 = READUINT32(save_p);
-				if (diff & MD_HEALTH)
-					mobj->health = READINT32(save_p);
-				else
-					mobj->health = mobj->info->spawnhealth;
-				if (diff & MD_RTIME)
-					mobj->reactiontime = READINT32(save_p);
-				else
-					mobj->reactiontime = mobj->info->reactiontime;
-
-				if (diff & MD_STATE)
-					mobj->state = &states[READUINT16(save_p)];
-				else
-					mobj->state = &states[mobj->info->spawnstate];
-				if (diff & MD_TICS)
-					mobj->tics = READINT32(save_p);
-				else
-					mobj->tics = mobj->state->tics;
-				if (diff & MD_SPRITE)
-					mobj->sprite = READUINT16(save_p);
-				else
-					mobj->sprite = mobj->state->sprite;
-				if (diff & MD_FRAME)
-					mobj->frame = READUINT32(save_p);
-				else
-					mobj->frame = mobj->state->frame;
-				if (diff & MD_EFLAGS)
-					mobj->eflags = READUINT8(save_p);
-				if (diff & MD_PLAYER)
-				{
-					i = READUINT8(save_p);
-					mobj->player = &players[i];
-					mobj->player->mo = mobj;
-					// added for angle prediction
-					if (consoleplayer == i)
-						localangle = mobj->angle;
-					if (secondarydisplayplayer == i)
-						localangle2 = mobj->angle;
-				}
-				if (diff & MD_MOVEDIR)
-					mobj->movedir = READANGLE(save_p);
-				if (diff & MD_MOVECOUNT)
-					mobj->movecount = READINT32(save_p);
-				if (diff & MD_THRESHOLD)
-					mobj->threshold = READINT32(save_p);
-				if (diff & MD_LASTLOOK)
-					mobj->lastlook = READINT32(save_p);
-				else
-					mobj->lastlook = -1;
-				if (diff & MD_TARGET)
-					mobj->target = (mobj_t *)(size_t)READUINT32(save_p);
-				if (diff & MD_TRACER)
-					mobj->tracer = (mobj_t *)(size_t)READUINT32(save_p);
-				if (diff & MD_FRICTION)
-					mobj->friction = READFIXED(save_p);
-				else
-					mobj->friction = ORIG_FRICTION;
-				if (diff & MD_MOVEFACTOR)
-					mobj->movefactor = READFIXED(save_p);
-				else
-					mobj->movefactor = ORIG_FRICTION_FACTOR;
-				if (diff & MD_FUSE)
-					mobj->fuse = READINT32(save_p);
-				if (diff & MD_WATERTOP)
-					mobj->watertop = READFIXED(save_p);
-				if (diff & MD_WATERBOTTOM)
-					mobj->waterbottom = READFIXED(save_p);
-				if (diff & MD_SCALE)
-					mobj->scale = READFIXED(save_p);
-				else
-					mobj->scale = FRACUNIT;
-				if (diff & MD_DSCALE)
-					mobj->destscale = READFIXED(save_p);
-				else
-					mobj->destscale = mobj->scale;
-				if (diff2 & MD2_SCALESPEED)
-					mobj->scalespeed = READFIXED(save_p);
-				else
-					mobj->scalespeed = FRACUNIT/12;
-				if (diff2 & MD2_CUSVAL)
-					mobj->cusval = READINT32(save_p);
-				if (diff2 & MD2_CVMEM)
-					mobj->cvmem = READINT32(save_p);
-				if (diff2 & MD2_SKIN)
-					mobj->skin = &skins[READUINT8(save_p)];
-				if (diff2 & MD2_COLOR)
-					mobj->color = READUINT8(save_p);
-				if (diff2 & MD2_EXTVAL1)
-					mobj->extravalue1 = READINT32(save_p);
-				if (diff2 & MD2_EXTVAL2)
-					mobj->extravalue2 = READINT32(save_p);
-				if (diff2 & MD2_HNEXT)
-					mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p);
-				if (diff2 & MD2_HPREV)
-					mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p);
-
-				if (diff & MD_REDFLAG)
-				{
-					redflag = mobj;
-					rflagpoint = mobj->spawnpoint;
-				}
-				if (diff & MD_BLUEFLAG)
-				{
-					blueflag = mobj;
-					bflagpoint = mobj->spawnpoint;
-				}
-
-				// set sprev, snext, bprev, bnext, subsector
-				P_SetThingPosition(mobj);
-
-				mobj->mobjnum = READUINT32(save_p);
-
-				if (mobj->player)
-				{
-					if (mobj->eflags & MFE_VERTICALFLIP)
-						mobj->player->viewz = mobj->z + mobj->height - mobj->player->viewheight;
-					else
-						mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight;
-				}
-
-				P_AddThinker(&mobj->thinker);
-
-				mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function
+				LoadMobjThinker((actionf_p1)P_MobjThinker);
 				break;
 
 			case tc_ceiling:
diff --git a/src/p_setup.c b/src/p_setup.c
index ca78db05a61f003a693ac83a92109991f3c856de..f2b0c49d84c3a1222308e130a539eff55a8cd670 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1502,22 +1502,26 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
 
 static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, fixed_t bx1, fixed_t by1)
 {
-	fixed_t bx2 = bx1 + MAPBLOCKUNITS;
-	fixed_t by2 = by1 + MAPBLOCKUNITS;
-	line_t boxline, testline;
-	vertex_t vbox, vtest;
+	fixed_t bbox[4];
+	line_t testline;
+	vertex_t vtest;
+
+	bbox[BOXRIGHT] = bx1 + MAPBLOCKUNITS;
+	bbox[BOXTOP] = by1 + MAPBLOCKUNITS;
+	bbox[BOXLEFT] = bx1;
+	bbox[BOXBOTTOM] = by1;
 
 	// Trivial rejection
-	if (cx1 < bx1 && cx2 < bx1)
+	if (cx1 < bbox[BOXLEFT] && cx2 < bbox[BOXLEFT])
 		return false;
 
-	if (cx1 > bx2 && cx2 > bx2)
+	if (cx1 > bbox[BOXRIGHT] && cx2 > bbox[BOXRIGHT])
 		return false;
 
-	if (cy1 < by1 && cy2 < by1)
+	if (cy1 < bbox[BOXBOTTOM] && cy2 < bbox[BOXBOTTOM])
 		return false;
 
-	if (cy1 > by2 && cy2 > by2)
+	if (cy1 > bbox[BOXTOP] && cy2 > bbox[BOXTOP])
 		return false;
 
 	// Rats, guess we gotta check
@@ -1527,12 +1531,11 @@ static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, f
 	cy1 <<= FRACBITS;
 	cx2 <<= FRACBITS;
 	cy2 <<= FRACBITS;
-	bx1 <<= FRACBITS;
-	by1 <<= FRACBITS;
-	bx2 <<= FRACBITS;
-	by2 <<= FRACBITS;
+	bbox[BOXTOP] <<= FRACBITS;
+	bbox[BOXBOTTOM] <<= FRACBITS;
+	bbox[BOXLEFT] <<= FRACBITS;
+	bbox[BOXRIGHT] <<= FRACBITS;
 
-	boxline.v1 = &vbox;
 	testline.v1 = &vtest;
 
 	testline.v1->x = cx1;
@@ -1540,47 +1543,12 @@ static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, f
 	testline.dx = cx2 - cx1;
 	testline.dy = cy2 - cy1;
 
-	// Test line against bottom edge of box
-	boxline.v1->x = bx1;
-	boxline.v1->y = by1;
-	boxline.dx = bx2 - bx1;
-	boxline.dy = 0;
-
-	if (P_PointOnLineSide(cx1, cy1, &boxline) != P_PointOnLineSide(cx2, cy2, &boxline)
-		&& P_PointOnLineSide(boxline.v1->x, boxline.v1->y, &testline) != P_PointOnLineSide(boxline.v1->x+boxline.dx, boxline.v1->y+boxline.dy, &testline))
-		return true;
-
-	// Right edge of box
-	boxline.v1->x = bx2;
-	boxline.v1->y = by1;
-	boxline.dx = 0;
-	boxline.dy = by2-by1;
-
-	if (P_PointOnLineSide(cx1, cy1, &boxline) != P_PointOnLineSide(cx2, cy2, &boxline)
-		&& P_PointOnLineSide(boxline.v1->x, boxline.v1->y, &testline) != P_PointOnLineSide(boxline.v1->x+boxline.dx, boxline.v1->y+boxline.dy, &testline))
-		return true;
-
-	// Top edge of box
-	boxline.v1->x = bx1;
-	boxline.v1->y = by2;
-	boxline.dx = bx2 - bx1;
-	boxline.dy = 0;
-
-	if (P_PointOnLineSide(cx1, cy1, &boxline) != P_PointOnLineSide(cx2, cy2, &boxline)
-		&& P_PointOnLineSide(boxline.v1->x, boxline.v1->y, &testline) != P_PointOnLineSide(boxline.v1->x+boxline.dx, boxline.v1->y+boxline.dy, &testline))
-		return true;
-
-	// Left edge of box
-	boxline.v1->x = bx1;
-	boxline.v1->y = by1;
-	boxline.dx = 0;
-	boxline.dy = by2-by1;
-
-	if (P_PointOnLineSide(cx1, cy1, &boxline) != P_PointOnLineSide(cx2, cy2, &boxline)
-		&& P_PointOnLineSide(boxline.v1->x, boxline.v1->y, &testline) != P_PointOnLineSide(boxline.v1->x+boxline.dx, boxline.v1->y+boxline.dy, &testline))
-		return true;
+	if ((testline.dx > 0) ^ (testline.dy > 0))
+		testline.slopetype = ST_NEGATIVE;
+	else
+		testline.slopetype = ST_POSITIVE;
 
-	return false;
+	return P_BoxOnLineSide(bbox, &testline) == -1;
 }
 
 //
@@ -2435,11 +2403,8 @@ boolean P_SetupLevel(boolean skipprecip)
 
 	// chasecam on in chaos, race, coop
 	// chasecam off in match, tag, capture the flag
-	chase = (gametype == GT_RACE || gametype == GT_COMPETITION || gametype == GT_COOP
-#ifdef CHAOSISNOTDEADYET
-		|| gametype == GT_CHAOS
-#endif
-		) || (maptol & TOL_2D);
+	chase = (gametype == GT_RACE || gametype == GT_COMPETITION || gametype == GT_COOP)
+		|| (maptol & TOL_2D);
 
 	if (!dedicated)
 	{
diff --git a/src/p_spec.c b/src/p_spec.c
index 323b93c6d8d18e2271c3d3316cc2405bf7c6a987..8228c60b3e5e085276d9a0ca23a420798b5adbcb 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -94,6 +94,7 @@ typedef struct
 	thinker_t **thinkers;
 } thinkerlist_t;
 
+static void P_SearchForDisableLinedefs(void);
 static void P_SpawnScrollers(void);
 static void P_SpawnFriction(void);
 static void P_SpawnPushers(void);
@@ -4776,6 +4777,18 @@ void P_UpdateSpecials(void)
 	}
 }
 
+static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2)
+{
+	ffloor_t *rover;
+
+	if (!sec->ffloors)
+		return NULL;
+	for (rover = sec->ffloors; rover; rover = rover->next)
+		if (rover->secnum == (size_t)(sec2 - sectors))
+			return rover;
+	return NULL;
+}
+
 /** Adds a newly formed 3Dfloor structure to a sector's ffloors list.
   *
   * \param sec    Target sector.
@@ -4822,7 +4835,9 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
 	size_t i;
 
 	if (sec == sec2)
-		return false; //Don't need a fake floor on a control sector.
+		return NULL; //Don't need a fake floor on a control sector.
+	if ((ffloor = (P_GetFFloorBySec(sec, sec2))))
+		return ffloor; // If this ffloor already exists, return it
 
 	if (sec2->ceilingheight < sec2->floorheight)
 	{
@@ -5312,9 +5327,6 @@ void T_LaserFlash(laserthink_t *flash)
 	ffloor_t *ffloor = flash->ffloor;
 	sector_t *sector = flash->sector;
 
-	if (!ffloor)
-		flash->ffloor = ffloor = P_AddFakeFloor(sector, flash->sec, flash->sourceline, laserflags, NULL);
-
 	if (!ffloor || !(ffloor->flags & FF_EXISTS))
 		return;
 
@@ -5409,6 +5421,10 @@ void P_SpawnSpecials(INT32 fromnetsave)
 	thinkerlist_t *secthinkers;
 	thinker_t *th;
 
+	// This used to be used, and *should* be used in the future,
+	// but currently isn't.
+	(void)fromnetsave;
+
 	// Set the default gravity. Custom gravity overrides this setting.
 	gravity = FRACUNIT/2;
 
@@ -5480,37 +5496,12 @@ void P_SpawnSpecials(INT32 fromnetsave)
 		curWeather = PRECIP_NONE;
 
 	P_InitTagLists();   // Create xref tables for tags
+	P_SearchForDisableLinedefs(); // Disable linedefs are now allowed to disable *any* line
+
 	P_SpawnScrollers(); // Add generalized scrollers
 	P_SpawnFriction();  // Friction model using linedefs
 	P_SpawnPushers();   // Pusher model using linedefs
 
-	// Look for disable linedefs
-	for (i = 0; i < numlines; i++)
-	{
-		if (lines[i].special == 6)
-		{
-			// Ability flags can disable disable linedefs now, lol
-			if (netgame || multiplayer)
-			{
-				// future: nonet flag?
-			}
-			else if (((lines[i].flags & ML_NETONLY) != ML_NETONLY)
-			&& !(players[consoleplayer].charability == CA_THOK          && (lines[i].flags & ML_NOSONIC))
-			&& !(players[consoleplayer].charability == CA_FLY           && (lines[i].flags & ML_NOTAILS))
-			&& !(players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX )))
-			{
-				for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;)
-				{
-					lines[j].tag = 0;
-					lines[j].special = 0;
-				}
-			}
-			lines[i].special = 0;
-			lines[i].tag = 0;
-		}
-	}
-
-
 	// Look for thinkers that affect FOFs, and sort them by sector
 
 	secthinkers = Z_Calloc(numsectors * sizeof(thinkerlist_t), PU_STATIC, NULL);
@@ -5993,12 +5984,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
 				break;
 
 			case 160: // Float/bob platform
-				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-				{
-					P_AddFakeFloor(&sectors[s], &sectors[sec], lines + i,
-						FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB, secthinkers);
-				}
+				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB, secthinkers);
 				break;
 
 			case 170: // Crumbling platform
@@ -6043,13 +6029,8 @@ void P_SpawnSpecials(INT32 fromnetsave)
 				break;
 
 			case 176: // Air bobbing platform that will crumble and bob on the water when it falls and hits
-				sec = sides[*lines[i].sidenum].sector - sectors;
+				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB|FF_CRUMBLE, secthinkers);
 				lines[i].flags |= ML_BLOCKMONSTERS;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-				{
-					P_AddFakeFloor(&sectors[s], &sectors[sec], lines + i,
-						FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB|FF_CRUMBLE, secthinkers);
-				}
 				P_AddOldAirbob(lines[i].frontsector, lines + i, true);
 				break;
 
@@ -6061,21 +6042,11 @@ void P_SpawnSpecials(INT32 fromnetsave)
 				break;
 
 			case 178: // Crumbling platform that will float when it hits water
-				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-				{
-					P_AddFakeFloor(&sectors[s], &sectors[sec], lines + i,
-						FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE|FF_FLOATBOB, secthinkers);
-				}
+				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CRUMBLE|FF_FLOATBOB, secthinkers);
 				break;
 
 			case 179: // Crumbling platform that will float when it hits water, but not return
-				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-				{
-					P_AddFakeFloor(&sectors[s], &sectors[sec], lines + i,
-						FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE|FF_FLOATBOB|FF_NORETURN, secthinkers);
-				}
+				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE|FF_FLOATBOB|FF_NORETURN, secthinkers);
 				break;
 
 			case 180: // Air bobbing platform that will crumble
@@ -6158,14 +6129,13 @@ void P_SpawnSpecials(INT32 fromnetsave)
 				break;
 
 			case 202: // Fog
+				ffloorflags = FF_EXISTS|FF_RENDERALL|FF_FOG|FF_BOTHPLANES|FF_INVERTPLANES|FF_ALLSIDES|FF_INVERTSIDES|FF_CUTEXTRA|FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES;
 				sec = sides[*lines[i].sidenum].sector - sectors;
 				// SoM: Because it's fog, check for an extra colormap and set
 				// the fog flag...
 				if (sectors[sec].extra_colormap)
 					sectors[sec].extra_colormap->fog = 1;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-					P_AddFakeFloor(&sectors[s], &sectors[sec], lines + i,
-						FF_EXISTS|FF_RENDERALL|FF_FOG|FF_BOTHPLANES|FF_INVERTPLANES|FF_ALLSIDES|FF_INVERTSIDES|FF_CUTEXTRA|FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES, secthinkers);
+				P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
 				break;
 
 			case 220: // Like opaque water, but not swimmable. (Good for snow effect on FOFs)
@@ -6195,12 +6165,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
 				break;
 
 			case 250: // Mario Block
-				sec = sides[*lines[i].sidenum].sector - sectors;
-				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-				{
-					P_AddFakeFloor(&sectors[s], &sectors[sec], lines + i,
-						FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO, secthinkers);
-				}
+				P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO, secthinkers);
 				break;
 
 			case 251: // A THWOMP!
@@ -6247,13 +6212,11 @@ void P_SpawnSpecials(INT32 fromnetsave)
 				break;
 
 			case 258: // Laser block
-				if (!fromnetsave) // This creates a FOF which disrupts net saves
-				{
-					sec = sides[*lines[i].sidenum].sector - sectors;
+				sec = sides[*lines[i].sidenum].sector - sectors;
 
-					for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
-						EV_AddLaserThinker(&sectors[s], &sectors[sec], lines + i, secthinkers);
-				}
+				// No longer totally disrupts netgames
+				for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;)
+					EV_AddLaserThinker(&sectors[s], &sectors[sec], lines + i, secthinkers);
 				break;
 
 			case 259: // Make-Your-Own FOF!
@@ -7720,3 +7683,39 @@ static void P_SpawnPushers(void)
 				break;
 		}
 }
+
+static void P_SearchForDisableLinedefs(void)
+{
+	size_t i;
+	INT32 j;
+
+	// Look for disable linedefs
+	for (i = 0; i < numlines; i++)
+	{
+		if (lines[i].special == 6)
+		{
+			// Remove special
+			// Do *not* remove tag. That would mess with the tag lists
+			// that P_InitTagLists literally just created!
+			lines[i].special = 0;
+
+			// Ability flags can disable disable linedefs now, lol
+			if (netgame || multiplayer)
+			{
+				// future: nonet flag?
+			}
+			else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY)
+				continue; // Net-only never triggers in single player
+			else if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC))
+				continue;
+			else if (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS))
+				continue;
+			else if (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX))
+				continue;
+
+			// Disable any linedef specials with our tag.
+			for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;)
+				lines[j].special = 0;
+		}
+	}
+}
diff --git a/src/p_tick.c b/src/p_tick.c
index 3b7d3683bfa70bc81ca7898d418a9416a42e40ad..2973505f3c71fc4b564ceff566a741481b52ba95 100644
--- a/src/p_tick.c
+++ b/src/p_tick.c
@@ -587,7 +587,7 @@ void P_Ticker(boolean run)
 	}
 
 	// Check for pause or menu up in single player
-	if (paused || P_MenuActivePause())
+	if (paused || P_AutoPause())
 		return;
 
 	postimgtype = postimgtype2 = postimg_none;
diff --git a/src/p_user.c b/src/p_user.c
index 8070a67bdaf5143f4726d1bba474f24c66a26399..6844d2cba37560905f15a2ab13b99ab3df7e0081 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -160,15 +160,17 @@ fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move)
 	return FixedMul(move, FINESINE(angle));
 }
 
-boolean P_MenuActivePause(void)
+//
+// P_AutoPause
+// Returns true when gameplay should be halted even if the game isn't necessarily paused.
+//
+boolean P_AutoPause(void)
 {
-	if (netgame || !menuactive)
+	// Don't pause even on menu-up or focus-lost in netgames or record attack
+	if (netgame || modeattacking)
 		return false;
 
-	if (modeattacking)
-		return false;
-
-	return true;
+	return (menuactive || window_notinfocus);
 }
 
 //
@@ -328,14 +330,10 @@ void P_GiveEmerald(boolean spawnObj)
 //
 // P_ResetScore
 //
-// This is called when your chain is reset. If in
-// Chaos mode, it displays what chain you got.
+// This is called when your chain is reset.
 void P_ResetScore(player_t *player)
 {
-#ifdef CHAOSISNOTDEADYET
-	if (gametype == GT_CHAOS && player->scoreadd >= 5)
-		CONS_Printf(M_GetText("%s got a chain of %u!\n"), player_names[player-players], player->scoreadd);
-#endif
+	// Formally a host for Chaos mode behavior
 
 	player->scoreadd = 0;
 }
@@ -2540,6 +2538,7 @@ static void P_DoClimbing(player_t *player)
 			thinker_t *think;
 			scroll_t *scroller;
 			angle_t sideangle;
+			fixed_t dx, dy;
 
 			for (think = thinkercap.next; think != &thinkercap; think = think->next)
 			{
@@ -2554,14 +2553,25 @@ static void P_DoClimbing(player_t *player)
 				if (scroller->affectee != player->lastsidehit)
 					continue;
 
+				if (scroller->accel)
+				{
+					dx = scroller->vdx;
+					dy = scroller->vdy;
+				}
+				else
+				{
+					dx = scroller->dx;
+					dy = scroller->dy;
+				}
+
 				if (cmd->forwardmove != 0)
 				{
-					player->mo->momz += scroller->dy;
+					player->mo->momz += dy;
 					climb = true;
 				}
 				else
 				{
-					player->mo->momz = scroller->dy;
+					player->mo->momz = dy;
 					climb = false;
 				}
 
@@ -2569,12 +2579,12 @@ static void P_DoClimbing(player_t *player)
 
 				if (cmd->sidemove != 0)
 				{
-					P_Thrust(player->mo, sideangle, scroller->dx);
+					P_Thrust(player->mo, sideangle, dx);
 					climb = true;
 				}
 				else
 				{
-					P_InstaThrust(player->mo, sideangle, scroller->dx);
+					P_InstaThrust(player->mo, sideangle, dx);
 					climb = false;
 				}
 			}
@@ -2652,6 +2662,125 @@ static void P_DoClimbing(player_t *player)
 	}
 }
 
+//
+// PIT_CheckSolidsTeeter
+// AKA: PIT_HacksToStopPlayersTeeteringOnGargoyles
+//
+
+static mobj_t *teeterer; // the player checking for teetering
+static boolean solidteeter; // saves whether the player can teeter on this or not
+static fixed_t highesttop; // highest floor found so far
+// reserved for standing on multiple objects
+static boolean couldteeter;
+static fixed_t teeterxl, teeterxh;
+static fixed_t teeteryl, teeteryh;
+
+static boolean PIT_CheckSolidsTeeter(mobj_t *thing)
+{
+	fixed_t blockdist;
+	fixed_t tiptop = FixedMul(MAXSTEPMOVE, teeterer->scale);
+	fixed_t thingtop = thing->z + thing->height;
+	fixed_t teeterertop = teeterer->z + teeterer->height;
+
+	if (!teeterer || !thing)
+		return true;
+
+	if (!(thing->flags & MF_SOLID))
+		return true;
+
+	if (thing->flags & MF_NOCLIP)
+		return true;
+
+	if (thing == teeterer)
+		return true;
+
+	if (thing->player && cv_tailspickup.value && gametype != GT_HIDEANDSEEK)
+		return true;
+
+	blockdist = teeterer->radius + thing->radius;
+
+	if (abs(thing->x - teeterer->x) >= blockdist || abs(thing->y - teeterer->y) >= blockdist)
+		return true; // didn't hit it
+
+	if (teeterer->eflags & MFE_VERTICALFLIP)
+	{
+		if (thingtop < teeterer->z)
+			return true;
+		if (thing->z > highesttop)
+			return true;
+		highesttop = thing->z;
+		if (thing->z > teeterertop + tiptop)
+		{
+			solidteeter = true;
+			return true;
+		}
+	}
+	else
+	{
+		if (thing->z > teeterertop)
+			return true;
+		if (thingtop < highesttop)
+			return true;
+		highesttop = thingtop;
+		if (thingtop < teeterer->z - tiptop)
+		{
+			solidteeter = true;
+			return true;
+		}
+	}
+
+	// are you standing on this?
+	if ((teeterer->eflags & MFE_VERTICALFLIP && thing->z - FixedMul(FRACUNIT, teeterer->scale) == teeterertop)
+	|| (!(teeterer->eflags & MFE_VERTICALFLIP) && thingtop + FixedMul(FRACUNIT, teeterer->scale) == teeterer->z))
+	{
+		fixed_t teeterdist = thing->radius - FixedMul(5*FRACUNIT, teeterer->scale);
+		// how far are you from the edge?
+		if (abs(teeterer->x - thing->x) > teeterdist || abs(teeterer->y - thing->y) > teeterdist)
+		{
+			if (couldteeter) // player is standing on another object already, see if we can stand on both and not teeter!
+			{
+				if (thing->x - teeterdist < teeterxl)
+					teeterxl = thing->x - teeterdist;
+				if (thing->x + teeterdist > teeterxh)
+					teeterxh = thing->x + teeterdist;
+				if (thing->y - teeterdist < teeteryl)
+					teeteryl = thing->y - teeterdist;
+				if (thing->y + teeterdist > teeteryh)
+					teeteryh = thing->y + teeterdist;
+
+				if (teeterer->x < teeterxl)
+					return true;
+				if (teeterer->x > teeterxh)
+					return true;
+				if (teeterer->y < teeteryl)
+					return true;
+				if (teeterer->y > teeteryh)
+					return true;
+
+				solidteeter = false; // you can stop teetering now!
+				couldteeter = false; // just in case...
+				return false;
+			}
+			else
+			{
+				// too far! don't change teeter status though
+				// save teeter x/y limits to bring up later
+				teeterxl = thing->x - teeterdist;
+				teeterxh = thing->x + teeterdist;
+				teeteryl = thing->y - teeterdist;
+				teeteryh = thing->y + teeterdist;
+			}
+			couldteeter = true;
+			return true;
+		}
+		solidteeter = false;
+		couldteeter = false;
+		return false; // you're definitely not teetering, that's the end of the matter
+	}
+	solidteeter = false;
+	return true; // you're not teetering but it's not neccessarily over, YET
+}
+
 //
 // P_DoTeeter
 //
@@ -2826,18 +2955,18 @@ static void P_DoTeeter(player_t *player)
 		}
 	}
 
-#ifdef POLYOBJECTS
-	// Polyobjects
 	{
 		INT32 bx, by, xl, xh, yl, yh;
 
-		validcount++;
-
 		yh = (unsigned)(player->mo->y + player->mo->radius - bmaporgy)>>MAPBLOCKSHIFT;
 		yl = (unsigned)(player->mo->y - player->mo->radius - bmaporgy)>>MAPBLOCKSHIFT;
 		xh = (unsigned)(player->mo->x + player->mo->radius - bmaporgx)>>MAPBLOCKSHIFT;
 		xl = (unsigned)(player->mo->x - player->mo->radius - bmaporgx)>>MAPBLOCKSHIFT;
 
+	// Polyobjects
+#ifdef POLYOBJECTS
+		validcount++;
+
 		for (by = yl; by <= yh; by++)
 			for (bx = xl; bx <= xh; bx++)
 			{
@@ -2898,16 +3027,12 @@ static void P_DoTeeter(player_t *player)
 							}
 
 							if (polybottom > player->mo->z + player->mo->height + tiptop
-									|| (polybottom < player->mo->z
-									&& player->mo->z + player->mo->height < player->mo->ceilingz - tiptop))
-							{
+							|| (polybottom < player->mo->z
+							&& player->mo->z + player->mo->height < player->mo->ceilingz - tiptop))
 								teeter = true;
-								roverfloor = true;
-							}
 							else
 							{
 								teeter = false;
-								roverfloor = true;
 								break;
 							}
 						}
@@ -2920,16 +3045,12 @@ static void P_DoTeeter(player_t *player)
 							}
 
 							if (polytop < player->mo->z - tiptop
-									|| (polytop > player->mo->z + player->mo->height
-									&& player->mo->z > player->mo->floorz + tiptop))
-							{
+							|| (polytop > player->mo->z + player->mo->height
+							&& player->mo->z > player->mo->floorz + tiptop))
 								teeter = true;
-								roverfloor = true;
-							}
 							else
 							{
 								teeter = false;
-								roverfloor = true;
 								break;
 							}
 						}
@@ -2937,8 +3058,27 @@ static void P_DoTeeter(player_t *player)
 					plink = (polymaplink_t *)(plink->link.next);
 				}
 			}
-	}
 #endif
+		if (teeter) // only bother with objects as a last resort if you were already teetering
+		{
+			mobj_t *oldtmthing = tmthing;
+			tmthing = teeterer = player->mo;
+			teeterxl = teeterxh = player->mo->x;
+			teeteryl = teeteryh = player->mo->y;
+			couldteeter = false;
+			solidteeter = teeter;
+			for (by = yl; by <= yh; by++)
+				for (bx = xl; bx <= xh; bx++)
+				{
+					highesttop = INT32_MIN;
+					if (!P_BlockThingsIterator(bx, by, PIT_CheckSolidsTeeter))
+						goto teeterdone; // we've found something that stops us teetering at all, how about we stop already
+				}
+teeterdone:
+			teeter = solidteeter;
+			tmthing = oldtmthing; // restore old tmthing, goodness knows what the game does with this before mobj thinkers
+		}
+	}
 	if (teeter)
 	{
 		if ((player->mo->state == &states[S_PLAY_STND] || player->mo->state == &states[S_PLAY_TAP1] || player->mo->state == &states[S_PLAY_TAP2] || player->mo->state == &states[S_PLAY_SUPERSTAND]))
diff --git a/src/r_bsp.c b/src/r_bsp.c
index e5e0942e3909f27c1a47b22ab473ecf95e04c149..e967e28cef3e194ebb5e43dcf652f9e2f91061e5 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -572,8 +572,8 @@ static boolean R_CheckBBox(fixed_t *bspcoord)
 	py2 = bspcoord[checkcoord[boxpos][3]];
 
 	// check clip list for an open space
-	angle1 = R_PointToAngle(px1, py1) - viewangle;
-	angle2 = R_PointToAngle(px2, py2) - viewangle;
+	angle1 = R_PointToAngle2(viewx>>1, viewy>>1, px1>>1, py1>>1) - viewangle;
+	angle2 = R_PointToAngle2(viewx>>1, viewy>>1, px2>>1, py2>>1) - viewangle;
 
 	span = angle1 - angle2;
 
@@ -702,21 +702,62 @@ static int R_PolysegCompare(const void *p1, const void *p2)
 {
 	const seg_t *seg1 = *(const seg_t * const *)p1;
 	const seg_t *seg2 = *(const seg_t * const *)p2;
-	fixed_t dist1, dist2;
+	fixed_t dist1v1, dist1v2, dist2v1, dist2v2;
 
 	// TODO might be a better way to get distance?
-#define vxdist(v) FixedMul(R_PointToDist(v->x, v->y), FINECOSINE((R_PointToAngle(v->x, v->y)-viewangle)>>ANGLETOFINESHIFT))+0xFFFFFFF
+#define pdist(x, y) (FixedMul(R_PointToDist(x, y), FINECOSINE((R_PointToAngle(x, y)-viewangle)>>ANGLETOFINESHIFT))+0xFFFFFFF)
+#define vxdist(v) pdist(v->x, v->y)
 
-	dist1 = min(vxdist(seg1->v1), vxdist(seg1->v2));
-	dist2 = min(vxdist(seg2->v1), vxdist(seg2->v2));
+	dist1v1 = vxdist(seg1->v1);
+	dist1v2 = vxdist(seg1->v2);
+	dist2v1 = vxdist(seg2->v1);
+	dist2v2 = vxdist(seg2->v2);
 
-	if (dist1 == dist2) { // Segs connect toward the front, so use the back verts to determine order!
-		dist1 = max(vxdist(seg1->v1), vxdist(seg1->v2));
-		dist2 = max(vxdist(seg2->v1), vxdist(seg2->v2));
+	if (min(dist1v1, dist1v2) != min(dist2v1, dist2v2))
+		return min(dist1v1, dist1v2) - min(dist2v1, dist2v2);
+
+	{ // That didn't work, so now let's try this.......
+		fixed_t delta1, delta2, x1, y1, x2, y2;
+		vertex_t *near1, *near2, *far1, *far2; // wherever you are~
+
+		delta1 = R_PointToDist2(seg1->v1->x, seg1->v1->y, seg1->v2->x, seg1->v2->y);
+		delta2 = R_PointToDist2(seg2->v1->x, seg2->v1->y, seg2->v2->x, seg2->v2->y);
+
+		delta1 = FixedDiv(128<<FRACBITS, delta1);
+		delta2 = FixedDiv(128<<FRACBITS, delta2);
+
+		if (dist1v1 < dist1v2)
+		{
+			near1 = seg1->v1;
+			far1 = seg1->v2;
+		}
+		else
+		{
+			near1 = seg1->v2;
+			far1 = seg1->v1;
+		}
+
+		if (dist2v1 < dist2v2)
+		{
+			near2 = seg2->v1;
+			far2 = seg2->v2;
+		}
+		else
+		{
+			near2 = seg2->v2;
+			far2 = seg2->v1;
+		}
+
+		x1 = near1->x + FixedMul(far1->x-near1->x, delta1);
+		y1 = near1->y + FixedMul(far1->y-near1->y, delta1);
+
+		x2 = near2->x + FixedMul(far2->x-near2->x, delta2);
+		y2 = near2->y + FixedMul(far2->y-near2->y, delta2);
+
+		return pdist(x1, y1)-pdist(x2, y2);
 	}
 #undef vxdist
-
-	return dist1-dist2;
+#undef pdist
 }
 
 //
@@ -835,6 +876,7 @@ static void R_Subsector(size_t num)
 
 	numffloors = 0;
 	ffloor[numffloors].plane = NULL;
+	ffloor[numffloors].polyobj = NULL;
 	if (frontsector->ffloors)
 	{
 		ffloor_t *rover;
@@ -854,6 +896,7 @@ static void R_Subsector(size_t num)
 			}
 
 			ffloor[numffloors].plane = NULL;
+			ffloor[numffloors].polyobj = NULL;
 			if (*rover->bottomheight <= frontsector->ceilingheight
 				&& *rover->bottomheight >= frontsector->floorheight
 				&& ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES))
@@ -872,6 +915,7 @@ static void R_Subsector(size_t num)
 			if (numffloors >= MAXFFLOORS)
 				break;
 			ffloor[numffloors].plane = NULL;
+			ffloor[numffloors].polyobj = NULL;
 			if (*rover->topheight >= frontsector->floorheight
 				&& *rover->topheight <= frontsector->ceilingheight
 				&& ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES))
diff --git a/src/r_data.c b/src/r_data.c
index 930b70bf5d03d563ea6749d68b86e7e754d2dbd1..0aba427505e4ad9083ec991902fb13818a6d118f 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -946,10 +946,12 @@ static void R_InitExtraColormaps(void)
 	CONS_Printf(M_GetText("Number of Extra Colormaps: %s\n"), sizeu1(numcolormaplumps));
 }
 
+// 12/14/14 -- only take flats in F_START/F_END
 lumpnum_t R_GetFlatNumForName(const char *name)
 {
-	lumpnum_t lump = W_CheckNumForName(name);
-
+	lumpnum_t lump = W_CheckNumForNameInBlock(name, "F_START", "F_END");
+	if (lump == LUMPERROR)
+		lump = W_CheckNumForNameInBlock(name, "FF_START", "FF_END"); // deutex, some other old things
 	if (lump == LUMPERROR)
 	{
 		if (strcmp(name, SKYFLATNAME))
diff --git a/src/r_main.c b/src/r_main.c
index f2c641f6af914669e9a2d7b60a16760db90649d1..ffd4d5d504c3b6c98e9c02894c41ec1ca0340d7c 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -162,6 +162,7 @@ consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NU
 consvar_t cv_showhud = {"showhud", "Yes", CV_CALL,  CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 
+consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_drawdist_nights = {"drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
@@ -1406,6 +1407,7 @@ void R_RegisterEngineStuff(void)
 		return;
 
 	CV_RegisterVar(&cv_precipdensity);
+	CV_RegisterVar(&cv_translucency);
 	CV_RegisterVar(&cv_drawdist);
 	CV_RegisterVar(&cv_drawdist_nights);
 	CV_RegisterVar(&cv_drawdist_precip);
diff --git a/src/r_main.h b/src/r_main.h
index 0d3f2def5222b8e60340ed6d8ab662ef0d3f2aae..13383451daf6ad3ffc16428d30e38b500575f2ab 100644
--- a/src/r_main.h
+++ b/src/r_main.h
@@ -88,6 +88,7 @@ extern consvar_t cv_homremoval;
 extern consvar_t cv_chasecam, cv_chasecam2;
 extern consvar_t cv_flipcam, cv_flipcam2;
 extern consvar_t cv_shadow, cv_shadowoffs;
+extern consvar_t cv_translucency;
 extern consvar_t cv_precipdensity, cv_drawdist, cv_drawdist_nights, cv_drawdist_precip;
 extern consvar_t cv_skybox;
 extern consvar_t cv_tailspickup;
diff --git a/src/r_segs.c b/src/r_segs.c
index c73cfdf9faeceb9445c22b4538e7798f00000056..7467f532472ae35d9eca14373ee9faf95e2e7b45 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -528,7 +528,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 						else
 							xwalllights = scalelight[rlight->lightnum];
 
-						pindex = spryscale>>LIGHTSCALESHIFT;
+						pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
 
 						if (pindex >= MAXLIGHTSCALE)
 							pindex = MAXLIGHTSCALE - 1;
@@ -573,7 +573,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 				}
 
 				// calculate lighting
-				pindex = spryscale>>LIGHTSCALESHIFT;
+				pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
 
 				if (pindex >= MAXLIGHTSCALE)
 					pindex = MAXLIGHTSCALE - 1;
@@ -1130,8 +1130,8 @@ static void R_RenderSegLoop (void)
 			for (i = 0; i < numffloors; i++)
 			{
 #ifdef POLYOBJECTS_PLANES
-				//if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
-					//continue; // Causes issues with FOF planes in The Wall -Red
+				if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg))
+					continue;
 
 				// FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red
 				if (curline->polyseg) {
@@ -1203,7 +1203,7 @@ static void R_RenderSegLoop (void)
 		if (segtextured)
 		{
 			// calculate lighting
-			pindex = rw_scale>>LIGHTSCALESHIFT;
+			pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
 
 			if (pindex >=  MAXLIGHTSCALE)
 				pindex = MAXLIGHTSCALE-1;
@@ -1238,7 +1238,7 @@ static void R_RenderSegLoop (void)
 				else
 					xwalllights = scalelight[lightnum];
 
-				pindex = rw_scale>>LIGHTSCALESHIFT;
+				pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT;
 
 				if (pindex >=  MAXLIGHTSCALE)
 					pindex = MAXLIGHTSCALE-1;
@@ -1359,9 +1359,9 @@ static void R_RenderSegLoop (void)
 
 		for (i = 0; i < numffloors; i++)
 		{
-#if 0 //#ifdef POLYOBJECTS_PLANES
-			if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
-				continue; // Causes issues with FOF planes in The Wall -Red
+#ifdef POLYOBJECTS_PLANES
+			if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg))
+				continue;
 #endif
 
 			ffloor[i].f_frac += ffloor[i].f_step;
@@ -1371,9 +1371,9 @@ static void R_RenderSegLoop (void)
 		{
 			INT32 y_w;
 
-#if 0 //#ifdef POLYOBJECTS_PLANES
-			if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
-				continue; // Causes issues with FOF planes in The Wall -Red
+#ifdef POLYOBJECTS_PLANES
+			if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg))
+				continue;
 #endif
 			y_w = ffloor[i].b_frac >> HEIGHTBITS;
 
@@ -1520,9 +1520,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	{
 		for (i = 0; i < numffloors; i++)
 		{
-#if 0 //#ifdef POLYOBJECTS_PLANES
-			if (ds_p->curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != ds_p->curline->polyseg))
-				continue; // Causes issues with FOF planes in The Wall -Red
+#ifdef POLYOBJECTS_PLANES
+			if (ffloor[i].polyobj && (!ds_p->curline->polyseg || ffloor[i].polyobj != ds_p->curline->polyseg))
+				continue;
 #endif
 			ffloor[i].f_pos = ffloor[i].height - viewz;
 		}
@@ -2021,9 +2021,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	{
 		for (i = 0; i < numffloors; i++)
 		{
-#if 0 //#ifdef POLYOBJECTS_PLANES
-			if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
-				continue; // Causes issues with FOF planes in The Wall -Red
+#ifdef POLYOBJECTS_PLANES
+			if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg))
+				continue;
 #endif
 
 			ffloor[i].f_pos >>= 4;
@@ -2126,7 +2126,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 #ifdef POLYOBJECTS_PLANES
 			if (curline->polyseg && frontsector && (curline->polyseg->flags & POF_RENDERPLANES))
 			{
-				if (i < MAXFFLOORS && backsector->floorheight <= frontsector->ceilingheight &&
+				while (i < numffloors && ffloor[i].polyobj != curline->polyseg) i++;
+				if (i < numffloors && backsector->floorheight <= frontsector->ceilingheight &&
 					backsector->floorheight >= frontsector->floorheight &&
 					(viewz < backsector->floorheight))
 				{
@@ -2142,7 +2143,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
 					i++;
 				}
-				if (i < MAXFFLOORS && backsector->ceilingheight >= frontsector->floorheight &&
+				if (i < numffloors && backsector->ceilingheight >= frontsector->floorheight &&
 					backsector->ceilingheight <= frontsector->ceilingheight &&
 					(viewz > backsector->ceilingheight))
 				{
diff --git a/src/r_things.c b/src/r_things.c
index 6372ddb4c06f122b06499864d2ec39528aa98590..9a8b1319bd1ee226c5f238fae706233152d28483 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -1293,7 +1293,9 @@ static void R_ProjectSprite(mobj_t *thing)
 	vis->transmap = NULL;
 
 	// specific translucency
-	if (thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility)
+	if (!cv_translucency.value)
+		; // no translucency
+	else if (thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility)
 		vis->transmap = ((tr_trans80-1)<<FF_TRANSSHIFT) + transtables; // because now the translucency is set through FF_TRANSMASK
 	else if (thing->frame & FF_TRANSMASK)
 		vis->transmap = (thing->frame & FF_TRANSMASK) - 0x10000 + transtables;
diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c
index 1c438e0834f97aed1c15d962c9e982c246892921..976f7eb35760360129128616437c73fd903ea1ef 100644
--- a/src/sdl/i_main.c
+++ b/src/sdl/i_main.c
@@ -195,15 +195,15 @@ int main(int argc, char **argv)
 
 #ifdef LOGMESSAGES
 #if defined(_WIN32_WCE) || defined(GP2X)
-	logstream = fopen(va("%s.log",argv[0]), "a");
+	logstream = fopen(va("%s.log",argv[0]), "wt");
 #elif defined (_WII)
-	logstream = fopen(va("%s/srb2log.txt",logdir), "a");
+	logstream = fopen(va("%s/log.txt",logdir), "wt");
 #elif defined (DEFAULTDIR)
 	if (logdir)
-		logstream = fopen(va("%s/"DEFAULTDIR"/srb2log.txt",logdir), "a");
+		logstream = fopen(va("%s/"DEFAULTDIR"/log.txt",logdir), "wt");
 	else
 #endif
-		logstream = fopen("./srb2log.txt", "a");
+		logstream = fopen("./log.txt", "wt");
 #endif
 
 	//I_OutputMsg("I_StartupSystem() ...\n");
@@ -228,9 +228,9 @@ int main(int argc, char **argv)
 #endif
 #endif
 	// startup SRB2
-	CONS_Printf("%s", M_GetText("Setting up SRB2...\n"));
+	CONS_Printf("Setting up SRB2...\n");
 	D_SRB2Main();
-	CONS_Printf("%s", M_GetText("Entering main game loop...\n"));
+	CONS_Printf("Entering main game loop...\n");
 	// never return
 	D_SRB2Loop();
 
diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c
index a1e91ec754b83815e8cb48cb0b950b5b2065a836..9c13b716c15e84fc7854d38e0b245adcc4aa0616 100644
--- a/src/sdl/i_system.c
+++ b/src/sdl/i_system.c
@@ -301,6 +301,7 @@ SDL_bool framebuffer = SDL_FALSE;
 
 UINT8 keyboard_started = false;
 
+#if !defined (DC)
 FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num)
 {
 	//static char msg[] = "oh no! back to reality!\r\n";
@@ -318,7 +319,7 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num)
 		sigmsg = "SIGILL - illegal instruction - invalid function image";
 		break;
 	case SIGFPE:
-		sigmsg = "SIGFPE - floating point exception";
+		sigmsg = "SIGFPE - mathematical exception";
 		break;
 	case SIGSEGV:
 		sigmsg = "SIGSEGV - segment violation";
@@ -339,7 +340,7 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num)
 		sigmsg = sigdef;
 	}
 
-	I_OutputMsg("signal_handler() error: %s\n", sigmsg);
+	I_OutputMsg("\nsignal_handler() error: %s\n", sigmsg);
 
 	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
 		"Signal caught",
@@ -350,7 +351,6 @@ FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num)
 	I_Quit();
 }
 
-#if !defined (DC)
 FUNCNORETURN static ATTRNORETURN void quit_handler(int num)
 {
 	signal(num, SIG_DFL); //default signal action
@@ -743,24 +743,15 @@ static inline void I_ShutdownConsole(void){}
 void I_StartupKeyboard (void)
 {
 #if !defined (DC)
-#ifdef SIGILL
-	signal(SIGILL , signal_handler);
-#endif
-#ifdef SIGINT
+	// If these defines don't exist,
+	// then compilation would have failed above us...
 	signal(SIGINT , quit_handler);
-#endif
-#ifdef SIGSEGV
-	signal(SIGSEGV , signal_handler);
-#endif
-#ifdef SIGBREAK
 	signal(SIGBREAK , quit_handler);
-#endif
-#ifdef SIGABRT
-	signal(SIGABRT , signal_handler);
-#endif
-#ifdef SIGTERM
 	signal(SIGTERM , quit_handler);
-#endif
+	signal(SIGILL , signal_handler);
+	signal(SIGSEGV , signal_handler);
+	signal(SIGABRT , signal_handler);
+	signal(SIGFPE , signal_handler);
 #endif
 }
 
@@ -2375,62 +2366,38 @@ void I_Error(const char *error, ...)
 		}
 		if (errorcount > 20)
 		{
-#ifdef MAC_ALERT
 			va_start(argptr, error);
 			vsprintf(buffer, error, argptr);
 			va_end(argptr);
-			// 2004-03-03 AJR Since the Mac user is most likely double clicking to run the game, give them a panel.
-			MacShowAlert("Recursive Error", buffer, "Quit", NULL, NULL);
-#elif (defined (_WIN32) || (defined (_WIN32_WCE)) && !defined (__GNUC__)) && !defined (_XBOX)
-			va_start(argptr,error);
-			vsprintf(buffer, error, argptr);
-			va_end(argptr);
-#ifndef _WIN32_WCE
-			{
-				HANDLE co = GetStdHandle(STD_OUTPUT_HANDLE);
-				DWORD bytesWritten;
-				if (co != INVALID_HANDLE_VALUE)
-				{
-					if (GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &bytesWritten))
-						WriteConsoleA(co, buffer, (DWORD)strlen(buffer), NULL, NULL);
-					else
-						WriteFile(co, buffer, (DWORD)strlen(buffer), &bytesWritten, NULL);
-				}
-			}
-#endif
-			OutputDebugStringA(buffer);
-			MessageBoxA(vid.WndParent, buffer, "SRB2 Recursive Error", MB_OK|MB_ICONERROR);
-#else
-			// Don't print garbage
-			va_start(argptr, error);
-			if (!framebuffer)
-				vfprintf (stderr, error, argptr);
-			va_end(argptr);
-#endif
+			// Implement message box with SDL_ShowSimpleMessageBox,
+			// which should fail gracefully if it can't put a message box up
+			// on the target system
+			SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
+				"SRB2 "VERSIONSTRING" Recursive Error",
+				buffer, NULL);
+
 			W_Shutdown();
+
 #ifdef GP2X
 			chdir("/usr/gp2x");
 			execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
 #endif
+
 			exit(-1); // recursive errors detected
 		}
 	}
+
 	shutdowning = true;
-	I_ShutdownConsole();
-#ifndef MAC_ALERT
-	// Message first.
-	va_start(argptr,error);
-	if (!framebuffer)
-	{
-		fprintf(stderr, "Error: ");
-		vfprintf(stderr,error,argptr);
-		fprintf(stderr, "\n");
-	}
+
+	// Display error message in the console before we start shutting it down
+	va_start(argptr, error);
+	vsprintf(buffer, error, argptr);
 	va_end(argptr);
+	I_OutputMsg("\nI_Error(): %s\n", buffer);
+	// ---
+
+	I_ShutdownConsole();
 
-	if (!framebuffer)
-		fflush(stderr);
-#endif
 	M_SaveConfig(NULL); // save game config, cvars..
 #ifndef NONET
 	D_SaveBan(); // save the ban list
@@ -2454,21 +2421,30 @@ void I_Error(const char *error, ...)
 #ifndef _arch_dreamcast
 	SDL_Quit();
 #endif
-#ifdef MAC_ALERT
-	va_start(argptr, error);
-	vsprintf(buffer, error, argptr);
-	va_end(argptr);
-	// 2004-03-03 AJR Since the Mac user is most likely double clicking to run the game, give them a panel.
-	MacShowAlert("Critical Error", buffer, "Quit", NULL, NULL);
-#endif
+
+	// Implement message box with SDL_ShowSimpleMessageBox,
+	// which should fail gracefully if it can't put a message box up
+	// on the target system
+	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
+		"SRB2 "VERSIONSTRING" Error",
+		buffer, NULL);
+	// Note that SDL_ShowSimpleMessageBox does *not* require SDL to be
+	// initialized at the time, so calling it after SDL_Quit() is
+	// perfectly okay! In addition, we do this on purpose so the
+	// fullscreen window is closed before displaying the error message
+	// in case the fullscreen window blocks it for some absurd reason.
+
 	W_Shutdown();
+
 #if defined (PARANOIA) && defined (__CYGWIN__)
-		*(INT32 *)2 = 4; //Alam: Debug!
+	*(INT32 *)2 = 4; //Alam: Debug!
 #endif
+
 #ifdef GP2X
 	chdir("/usr/gp2x");
 	execl("/usr/gp2x/gp2xmenu", "/usr/gp2x/gp2xmenu", NULL);
 #endif
+
 	exit(-1);
 }
 
@@ -2534,6 +2510,7 @@ void I_ShutdownSystem(void)
 #ifdef  LOGMESSAGES
 	if (logstream)
 	{
+		I_OutputMsg("I_ShutdownSystem(): end of logstream.\n");
 		fclose(logstream);
 		logstream = NULL;
 	}
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 660263b3fb3424b72a41ba24fa080cda2d08589a..cddc9e83d520180494b4b249a87c1636efe4f5b8 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -667,31 +667,28 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
 
 	if (mousefocus && kbfocus)
 	{
+		// Tell game we got focus back, resume music if necessary
+		window_notinfocus = false;
+		if (!paused)
+			I_ResumeSong(0); //resume it
+
 		if (!firsttimeonmouse)
 		{
 			if (cv_usemouse.value) I_StartupMouse();
 		}
 		//else firsttimeonmouse = SDL_FALSE;
-		if (gamestate == GS_LEVEL)
-		{
-			if (!paused) I_ResumeSong(0); //resume it
-		}
 	}
 	else if (!mousefocus && !kbfocus)
 	{
+		// Tell game we lost focus, pause music
+		window_notinfocus = true;
+		I_PauseSong(0);
+
 		if (!disable_mouse)
 		{
 			SDLforceUngrabMouse();
 		}
-		if (!netgame && gamestate == GS_LEVEL && !demoplayback && !demorecording && !modeattacking)
-		{
-			paused = true;
-		}
 		memset(gamekeydown, 0, NUMKEYS); // TODO this is a scary memset
-		if (gamestate == GS_LEVEL)
-		{
-			I_PauseSong(0);
-		}
 
 		if (MOUSE_MENU)
 		{
@@ -1570,7 +1567,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 #ifdef HWRENDER
 	if (rendermode == render_opengl)
 	{
-		window = SDL_CreateWindow("SRB2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+		window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
 				realwidth, realheight, flags | SDL_WINDOW_OPENGL);
 		if (window != NULL)
 		{
@@ -1590,7 +1587,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 #endif
 	if (rendermode == render_soft)
 	{
-		window = SDL_CreateWindow("SRB2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+		window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
 				realwidth, realheight, flags);
 		if (window != NULL)
 		{
@@ -1775,7 +1772,7 @@ void I_StartupGraphics(void)
 
 	// Create window
 	//Impl_CreateWindow(USE_FULLSCREEN);
-	//Impl_SetWindowName("SRB2");
+	//Impl_SetWindowName("SRB2 "VERSIONSTRING);
 	VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT));
 
 	vid.buffer = NULL;  // For software mode
@@ -1835,12 +1832,17 @@ void I_ShutdownGraphics(void)
 		bufSurface = NULL;
 	}
 
+	I_OutputMsg("I_ShutdownGraphics(): ");
+
 	// was graphics initialized anyway?
 	if (!graphics_started)
+	{
+		I_OutputMsg("graphics never started\n");
 		return;
-	CONS_Printf("I_ShutdownGraphics: ");
+	}
 	graphics_started = false;
-	CONS_Printf("%s", M_GetText("shut down\n"));
+	I_OutputMsg("shut down\n");
+
 #ifdef HWRENDER
 	if (GLUhandle)
 		hwClose(GLUhandle);
diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
index a205d30cea0940f91ac87bf8d268f7bd835cdc62..98599fb60b7ad0a89046d317f63292bc461dbae3 100644
--- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
+++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj
@@ -1214,7 +1214,7 @@
 		C01FCF4B08A954540054247B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				CURRENT_PROJECT_VERSION = 2.1.12;
+				CURRENT_PROJECT_VERSION = 2.1.14;
 				GCC_PREPROCESSOR_DEFINITIONS = (
 					"$(inherited)",
 					NORMALSRB2,
@@ -1226,7 +1226,7 @@
 		C01FCF4C08A954540054247B /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				CURRENT_PROJECT_VERSION = 2.1.12;
+				CURRENT_PROJECT_VERSION = 2.1.14;
 				GCC_ENABLE_FIX_AND_CONTINUE = NO;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_PREPROCESSOR_DEFINITIONS = (
diff --git a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj
index a205d30cea0940f91ac87bf8d268f7bd835cdc62..98599fb60b7ad0a89046d317f63292bc461dbae3 100644
--- a/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj
+++ b/src/sdl12/macosx/Srb2mac.xcodeproj/project.pbxproj
@@ -1214,7 +1214,7 @@
 		C01FCF4B08A954540054247B /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				CURRENT_PROJECT_VERSION = 2.1.12;
+				CURRENT_PROJECT_VERSION = 2.1.14;
 				GCC_PREPROCESSOR_DEFINITIONS = (
 					"$(inherited)",
 					NORMALSRB2,
@@ -1226,7 +1226,7 @@
 		C01FCF4C08A954540054247B /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
-				CURRENT_PROJECT_VERSION = 2.1.12;
+				CURRENT_PROJECT_VERSION = 2.1.14;
 				GCC_ENABLE_FIX_AND_CONTINUE = NO;
 				GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
 				GCC_PREPROCESSOR_DEFINITIONS = (
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 0d0cb1aefd2ca2fa310472c234750031fbd641c4..a9bdacf7152f3a7683345ccd2ece8c0ed1b3e523 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -203,7 +203,7 @@ void ST_doPaletteStuff(void)
 {
 	INT32 palette;
 
-	if (paused || P_MenuActivePause())
+	if (paused || P_AutoPause())
 		palette = 0;
 	else if (stplyr && stplyr->flashcount)
 		palette = stplyr->flashpal;
@@ -1576,15 +1576,6 @@ static inline void ST_drawTeamName(void)
 		V_DrawString(244, (splitscreen) ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "SPECTATOR");
 }
 
-#ifdef CHAOSISNOTDEADYET
-static inline void ST_drawChaosHUD(void)
-{
-	char chains[33];
-	sprintf(chains, "CHAINS: %u", stplyr->scoreadd);
-	V_DrawString(8, STRINGY(184), V_HUDTRANSHALF, chains);
-}
-#endif
-
 static void ST_drawSpecialStageHUD(void)
 {
 	if (totalrings > 0)
@@ -1667,7 +1658,7 @@ static void ST_doHuntIconsAndSound(void)
 			interval = newinterval;
 	}
 
-	if (!(P_MenuActivePause() || paused) && interval > 0 && leveltime && leveltime % interval == 0)
+	if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0)
 		S_StartSound(NULL, sfx_emfind);
 }
 
@@ -1727,7 +1718,7 @@ static void ST_doItemFinderIconsAndSound(void)
 		}
 	}
 
-	if (!(P_MenuActivePause() || paused) && interval > 0 && leveltime && leveltime % interval == 0)
+	if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0)
 		S_StartSound(NULL, sfx_emfind);
 }
 
@@ -1814,12 +1805,6 @@ static void ST_overlayDrawer(void)
 		if (G_GametypeHasTeams())
 			ST_drawTeamName();
 
-		// Chaos HUD Stuff
-#ifdef CHAOSISNOTDEADYET
-		else if (gametype == GT_CHAOS)
-			ST_drawChaosHUD();
-#endif
-
 		// Special Stage HUD
 		if (!useNightsSS && G_IsSpecialStage(gamemap) && stplyr == &players[displayplayer])
 			ST_drawSpecialStageHUD();
diff --git a/src/w_wad.c b/src/w_wad.c
index adcbb4811cca1670cc9f62a23c9f1e624efd7edd..79ed1f478b67741dd625418e10ef1ece6813c556 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -662,6 +662,32 @@ lumpnum_t W_GetNumForName(const char *name)
 	return i;
 }
 
+//
+// W_CheckNumForNameInBlock
+// Checks only in blocks from blockstart lump to blockend lump
+//
+lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend)
+{
+	INT32 i;
+	lumpnum_t bsid, beid;
+	lumpnum_t check = INT16_MAX;
+
+	// scan wad files backwards so patch lump files take precedence
+	for (i = numwadfiles - 1; i >= 0; i--)
+	{
+		bsid = W_CheckNumForNamePwad(blockstart,(UINT16)i,0);
+		if (bsid == INT16_MAX)
+			continue; // block doesn't exist, keep going
+		beid = W_CheckNumForNamePwad(blockend,(UINT16)i,0);
+		// if block end doesn't exist, just search through everything
+
+		check = W_CheckNumForNamePwad(name,(UINT16)i,bsid);
+		if (check < beid)
+			return (i<<16)+check; // found it, in our constraints
+	}
+	return LUMPERROR;
+}
+
 // Used by Lua. Case sensitive lump checking, quickly...
 #include "fastcmp.h"
 UINT8 W_LumpExists(const char *name)
diff --git a/src/w_wad.h b/src/w_wad.h
index 76f52b0043cb9299b07f954d22ef6e29e92d546f..614b7e4aec8c8b9bc4c16c9703c9735ed84006f8 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -102,6 +102,7 @@ const char *W_CheckNameForNum(lumpnum_t lumpnum);
 UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump); // checks only in one pwad
 lumpnum_t W_CheckNumForName(const char *name);
 lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR
+lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend);
 UINT8 W_LumpExists(const char *name); // Lua uses this.
 
 size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump);
diff --git a/src/y_inter.c b/src/y_inter.c
index 498afa7cfeddc5cd9e580c728a69b7dd77acc242..2f2edf7ca71eef368671f501c88db3e745f52959 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -588,7 +588,7 @@ void Y_Ticker(void)
 		return;
 
 	// Check for pause or menu up in single player
-	if (paused || P_MenuActivePause())
+	if (paused || P_AutoPause())
 		return;
 
 	intertic++;
@@ -907,11 +907,7 @@ void Y_StartIntermission(void)
 			intertype = int_teammatch;
 		else if (gametype == GT_MATCH
 		 || gametype == GT_TAG
-		 || gametype == GT_HIDEANDSEEK
-#ifdef CHAOSISNOTDEADYET
-		 || gametype == GT_CHAOS
-#endif
-		)
+		 || gametype == GT_HIDEANDSEEK)
 			intertype = int_match;
 		else if (gametype == GT_RACE)
 			intertype = int_race;
diff --git a/src/y_inter.h b/src/y_inter.h
index 67ab4f4e2029480505b2d5b62ec9cbe1fa5c8f3f..a3620cea74a8a1d1adde6c649abafdc0d4a36c3a 100644
--- a/src/y_inter.h
+++ b/src/y_inter.h
@@ -25,9 +25,6 @@ typedef enum
 	int_teammatch,// Team Match
 //	int_tag,      // Tag
 	int_ctf,      // CTF
-#ifdef CHAOSISNOTDEADYET
-	int_chaos,    // Chaos
-#endif
 	int_spec,     // Special Stage
 	int_nights,   // NiGHTS into Dreams
 	int_nightsspec,// NiGHTS special stage