diff --git a/SRB2.cbp b/SRB2.cbp
index 99a71226467e07aeb3e6f01f01cb99608bea6cf7..88dc400fee58d949fe3f59eb968662e45702ffd1 100644
--- a/SRB2.cbp
+++ b/SRB2.cbp
@@ -14,7 +14,7 @@ If you are compiling for Windows, use Mingw targets
 Interface Defines:
 _WINDOWS for DirectX Interface
 SDL for SDL Interface
-HAVE_MIXER for SDL_Mixer
+HAVE_MIXER for SDL2_mixer
 
 HAVE_PNG for PNG support (for APNG support. compile libs/libpng-src)
 HWRENDER for hardware render support
@@ -31,7 +31,7 @@ HW3SOUND for 3D hardware sound  support
 				<Option compiler="gcc" />
 				<Compiler>
 					<Add option="-g" />
-					<Add option="`sdl-config --cflags`" />
+					<Add option="`sdl2-config --cflags`" />
 					<Add option="-DDIRECTFULLSCREEN" />
 					<Add option="-DHAVE_SDL" />
 					<Add option="-DPARANOIA" />
@@ -41,8 +41,8 @@ HW3SOUND for 3D hardware sound  support
 					<Add option="-DHAVE_BLUA" />
 				</Compiler>
 				<Linker>
-					<Add option="`sdl-config --libs`" />
-					<Add library="SDL_mixer" />
+					<Add option="`sdl2-config --libs`" />
+					<Add library="SDL2_mixer" />
 				</Linker>
 			</Target>
 			<Target title="Release Native/SDL">
@@ -54,7 +54,7 @@ HW3SOUND for 3D hardware sound  support
 				<Compiler>
 					<Add option="-O2" />
 					<Add option="-g" />
-					<Add option="`sdl-config --cflags`" />
+					<Add option="`sdl2-config --cflags`" />
 					<Add option="-DDIRECTFULLSCREEN" />
 					<Add option="-DHAVE_SDL" />
 					<Add option="-DNDEBUG" />
@@ -62,8 +62,8 @@ HW3SOUND for 3D hardware sound  support
 					<Add option="-DHAVE_BLUA" />
 				</Compiler>
 				<Linker>
-					<Add option="`sdl-config --libs`" />
-					<Add library="SDL_mixer" />
+					<Add option="`sdl2-config --libs`" />
+					<Add library="SDL2_mixer" />
 				</Linker>
 			</Target>
 			<Target title="Debug Linux/SDL">
@@ -74,7 +74,7 @@ HW3SOUND for 3D hardware sound  support
 				<Option compiler="gcc" />
 				<Compiler>
 					<Add option="-g" />
-					<Add option="`sdl-config --cflags`" />
+					<Add option="`sdl2-config --cflags`" />
 					<Add option="`libpng-config --cflags`" />
 					<Add option="-DDIRECTFULLSCREEN" />
 					<Add option="-DHAVE_SDL" />
@@ -89,9 +89,9 @@ HW3SOUND for 3D hardware sound  support
 					<Add option="-DHAVE_BLUA" />
 				</Compiler>
 				<Linker>
-					<Add option="`sdl-config --libs`" />
+					<Add option="`sdl2-config --libs`" />
 					<Add option="`libpng-config --libs`" />
-					<Add library="SDL_mixer" />
+					<Add library="SDL2_mixer" />
 					<Add library="rt" />
 				</Linker>
 			</Target>
@@ -104,7 +104,7 @@ HW3SOUND for 3D hardware sound  support
 				<Compiler>
 					<Add option="-O2" />
 					<Add option="-g" />
-					<Add option="`sdl-config --cflags`" />
+					<Add option="`sdl2-config --cflags`" />
 					<Add option="`libpng-config --cflags`" />
 					<Add option="-DDIRECTFULLSCREEN" />
 					<Add option="-DHAVE_SDL" />
@@ -117,9 +117,9 @@ HW3SOUND for 3D hardware sound  support
 					<Add option="-DHAVE_BLUA" />
 				</Compiler>
 				<Linker>
-					<Add option="`sdl-config --libs`" />
+					<Add option="`sdl2-config --libs`" />
 					<Add option="`libpng-config --libs`" />
-					<Add library="SDL_mixer" />
+					<Add library="SDL2_mixer" />
 					<Add library="rt" />
 				</Linker>
 			</Target>
@@ -152,6 +152,8 @@ HW3SOUND for 3D hardware sound  support
 					<Add directory="libs/libpng-src" />
 					<Add directory="libs/zlib" />
 					<Add directory="libs/gme/include" />
+					<Add directory="libs/SDL2/include" />
+					<Add directory="libs/SDL2_mixer/include" />
 				</Compiler>
 				<Linker>
 					<Add library="SDL2" />
@@ -167,6 +169,8 @@ HW3SOUND for 3D hardware sound  support
 					<Add directory="libs/zlib/win32" />
 					<Add directory="libs/libpng-src/projects" />
 					<Add directory="libs/gme/win32" />
+					<Add directory="libs/SDL2/lib/x86" />
+					<Add directory="libs/SDL2_mixer/lib/x86" />
 				</Linker>
 			</Target>
 			<Target title="Release Mingw/SDL">
@@ -198,6 +202,8 @@ HW3SOUND for 3D hardware sound  support
 					<Add directory="libs/libpng-src" />
 					<Add directory="libs/zlib" />
 					<Add directory="libs/gme/include" />
+					<Add directory="libs/SDL2/include" />
+					<Add directory="libs/SDL2_mixer/include" />
 				</Compiler>
 				<Linker>
 					<Add library="SDL2" />
@@ -213,6 +219,8 @@ HW3SOUND for 3D hardware sound  support
 					<Add directory="libs/zlib/win32" />
 					<Add directory="libs/libpng-src/projects" />
 					<Add directory="libs/gme/win32" />
+					<Add directory="libs/SDL2/lib/x86" />
+					<Add directory="libs/SDL2_mixer/lib/x86" />
 				</Linker>
 			</Target>
 			<Target title="Debug Mingw/DirectX">
@@ -567,7 +575,7 @@ HW3SOUND for 3D hardware sound  support
 				<Linker>
 					<Add option="-g" />
 					<Add library="SDL" />
-					<Add library="SDL_mixer" />
+					<Add library="SDL2_mixer" />
 					<Add library="advapi32" />
 					<Add library="kernel32" />
 					<Add library="msvcrt" />
@@ -606,7 +614,7 @@ HW3SOUND for 3D hardware sound  support
 				<Linker>
 					<Add option="-g" />
 					<Add library="SDL" />
-					<Add library="SDL_mixer" />
+					<Add library="SDL2_mixer" />
 					<Add library="advapi32" />
 					<Add library="kernel32" />
 					<Add library="msvcrt" />
@@ -884,6 +892,206 @@ HW3SOUND for 3D hardware sound  support
 		<Unit filename="cpdebug.mk" />
 		<Unit filename="src/am_map.c">
 			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/am_map.h" />
+		<Unit filename="src/b_bot.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/b_bot.h" />
+		<Unit filename="src/blua/lapi.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lapi.h" />
+		<Unit filename="src/blua/lauxlib.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lauxlib.h" />
+		<Unit filename="src/blua/lbaselib.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lcode.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lcode.h" />
+		<Unit filename="src/blua/ldebug.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/ldebug.h" />
+		<Unit filename="src/blua/ldo.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/ldo.h" />
+		<Unit filename="src/blua/ldump.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lfunc.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lfunc.h" />
+		<Unit filename="src/blua/lgc.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lgc.h" />
+		<Unit filename="src/blua/linit.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/llex.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/llex.h" />
+		<Unit filename="src/blua/llimits.h" />
+		<Unit filename="src/blua/lmem.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lmem.h" />
+		<Unit filename="src/blua/lobject.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lobject.h" />
+		<Unit filename="src/blua/lopcodes.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lopcodes.h" />
+		<Unit filename="src/blua/lparser.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lparser.h" />
+		<Unit filename="src/blua/lstate.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lstate.h" />
+		<Unit filename="src/blua/lstring.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lstring.h" />
+		<Unit filename="src/blua/lstrlib.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/ltable.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/ltable.h" />
+		<Unit filename="src/blua/ltablib.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/ltm.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/ltm.h" />
+		<Unit filename="src/blua/lua.h" />
+		<Unit filename="src/blua/luaconf.h" />
+		<Unit filename="src/blua/lualib.h" />
+		<Unit filename="src/blua/lundump.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lundump.h" />
+		<Unit filename="src/blua/lvm.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lvm.h" />
+		<Unit filename="src/blua/lzio.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/blua/lzio.h" />
+		<Unit filename="src/byteptr.h" />
+		<Unit filename="src/command.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/command.h" />
+		<Unit filename="src/comptime.c">
+			<Option compilerVar="CC" />
+			<Option weight="100" />
+		</Unit>
+		<Unit filename="src/comptime.h" />
+		<Unit filename="src/console.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/console.h" />
+		<Unit filename="src/d_clisrv.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/d_clisrv.h" />
+		<Unit filename="src/d_event.h" />
+		<Unit filename="src/d_main.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/d_main.h" />
+		<Unit filename="src/d_net.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/d_net.h" />
+		<Unit filename="src/d_netcmd.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/d_netcmd.h" />
+		<Unit filename="src/d_netfil.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/d_netfil.h" />
+		<Unit filename="src/d_player.h" />
+		<Unit filename="src/d_think.h" />
+		<Unit filename="src/d_ticcmd.h" />
+		<Unit filename="src/dehacked.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/dehacked.h" />
+		<Unit filename="src/doomdata.h" />
+		<Unit filename="src/doomdef.h" />
+		<Unit filename="src/doomstat.h" />
+		<Unit filename="src/doomtype.h" />
+		<Unit filename="src/dummy/i_cdmus.c">
+			<Option compilerVar="CC" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
+		</Unit>
+		<Unit filename="src/dummy/i_main.c">
+			<Option compilerVar="CC" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
+		</Unit>
+		<Unit filename="src/dummy/i_net.c">
+			<Option compilerVar="CC" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
+		</Unit>
+		<Unit filename="src/dummy/i_sound.c">
+			<Option compilerVar="CC" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
+		</Unit>
+		<Unit filename="src/dummy/i_system.c">
+			<Option compilerVar="CC" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
+		</Unit>
+		<Unit filename="src/dummy/i_video.c">
+			<Option compilerVar="CC" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
+		</Unit>
+		<Unit filename="src/endian.h" />
+		<Unit filename="src/f_finale.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/f_finale.h" />
+		<Unit filename="src/f_wipe.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/fastcmp.h" />
+		<Unit filename="src/filesrch.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/filesrch.h" />
+		<Unit filename="src/g_game.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/g_game.h" />
+		<Unit filename="src/g_input.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/g_input.h" />
+		<Unit filename="src/g_state.h" />
+		<Unit filename="src/hardware/hw3dsdrv.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
@@ -899,7 +1107,8 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/am_map.h">
+		<Unit filename="src/hardware/hw3sound.c">
+			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
@@ -915,8 +1124,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/b_bot.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/hw3sound.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
@@ -932,24 +1140,24 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/b_bot.h" />
-		<Unit filename="src/blua/lapi.c">
+		<Unit filename="src/hardware/hw_bsp.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
+			<Option target="Debug Linux/SDL" />
+			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
 			<Option target="Release Mingw64/SDL" />
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lapi.h" />
-		<Unit filename="src/blua/lauxlib.c">
+		<Unit filename="src/hardware/hw_cache.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -957,6 +1165,8 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -964,15 +1174,15 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lauxlib.h" />
-		<Unit filename="src/blua/lbaselib.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/hw_data.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -980,14 +1190,15 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lcode.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/hw_defs.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -995,15 +1206,15 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lcode.h" />
-		<Unit filename="src/blua/ldebug.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/hw_dll.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1011,8 +1222,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/ldebug.h" />
-		<Unit filename="src/blua/ldo.c">
+		<Unit filename="src/hardware/hw_draw.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -1020,6 +1230,8 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1027,15 +1239,15 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/ldo.h" />
-		<Unit filename="src/blua/ldump.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/hw_drv.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1043,14 +1255,15 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lfunc.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/hw_glide.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1058,15 +1271,15 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lfunc.h" />
-		<Unit filename="src/blua/lgc.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/hw_glob.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1074,8 +1287,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lgc.h" />
-		<Unit filename="src/blua/linit.c">
+		<Unit filename="src/hardware/hw_light.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -1083,6 +1295,8 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1090,14 +1304,15 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/llex.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/hw_light.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1105,9 +1320,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/llex.h" />
-		<Unit filename="src/blua/llimits.h" />
-		<Unit filename="src/blua/lmem.c">
+		<Unit filename="src/hardware/hw_main.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -1115,6 +1328,8 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1122,15 +1337,15 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lmem.h" />
-		<Unit filename="src/blua/lobject.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/hw_main.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1138,8 +1353,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lobject.h" />
-		<Unit filename="src/blua/lopcodes.c">
+		<Unit filename="src/hardware/hw_md2.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -1147,6 +1361,8 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1154,15 +1370,15 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lopcodes.h" />
-		<Unit filename="src/blua/lparser.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/hw_md2.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1170,8 +1386,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lparser.h" />
-		<Unit filename="src/blua/lstate.c">
+		<Unit filename="src/hardware/hw_trick.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -1179,6 +1394,8 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1186,15 +1403,15 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lstate.h" />
-		<Unit filename="src/blua/lstring.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/hws_data.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 			<Option target="Debug Mingw/DirectX" />
 			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
@@ -1202,2963 +1419,324 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw64/DirectX" />
 			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/blua/lstring.h" />
-		<Unit filename="src/blua/lstrlib.c">
+		<Unit filename="src/hardware/r_minigl/r_minigl.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+			<Option target="Debug Mingw R_MiniGL" />
+			<Option target="Release Mingw R_MiniGL" />
+			<Option target="Debug Mingw64 R_MiniGL" />
+			<Option target="Release Mingw64 R_MiniGL" />
 		</Unit>
-		<Unit filename="src/blua/ltable.c">
+		<Unit filename="src/hardware/r_opengl/ogl_win.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+			<Option target="Debug Mingw R_OpenGL" />
+			<Option target="Release Mingw R_OpenGL" />
+			<Option target="Debug Mingw64 R_OpenGL" />
+			<Option target="Release Mingw64 R_OpenGL" />
 		</Unit>
-		<Unit filename="src/blua/ltable.h" />
-		<Unit filename="src/blua/ltablib.c">
+		<Unit filename="src/hardware/r_opengl/r_opengl.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/blua/ltm.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
+			<Option target="Debug Mingw R_OpenGL" />
+			<Option target="Release Mingw R_OpenGL" />
 			<Option target="Debug Mingw64/SDL" />
 			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+			<Option target="Debug Mingw64 R_OpenGL" />
+			<Option target="Release Mingw64 R_OpenGL" />
 		</Unit>
-		<Unit filename="src/blua/ltm.h" />
-		<Unit filename="src/blua/lua.h" />
-		<Unit filename="src/blua/luaconf.h" />
-		<Unit filename="src/blua/lualib.h" />
-		<Unit filename="src/blua/lundump.c">
-			<Option compilerVar="CC" />
+		<Unit filename="src/hardware/r_opengl/r_opengl.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
+			<Option target="Debug Any/Dummy" />
+			<Option target="Release Any/Dummy" />
+			<Option target="Debug Mingw R_OpenGL" />
+			<Option target="Release Mingw R_OpenGL" />
+			<Option target="Debug Mingw R_MiniGL" />
+			<Option target="Release Mingw R_MiniGL" />
 			<Option target="Debug Linux/SDL" />
 			<Option target="Release Linux/SDL" />
 			<Option target="Debug Mingw64/SDL" />
 			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+			<Option target="Debug Mingw64 R_OpenGL" />
+			<Option target="Release Mingw64 R_OpenGL" />
+			<Option target="Debug Mingw64 R_MiniGL" />
+			<Option target="Release Mingw64 R_MiniGL" />
 		</Unit>
-		<Unit filename="src/blua/lundump.h" />
-		<Unit filename="src/blua/lvm.c">
+		<Unit filename="src/hardware/s_ds3d/s_ds3d.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+			<Option target="Debug Mingw S_DS3D" />
+			<Option target="Release Mingw S_DS3D" />
+			<Option target="Debug Mingw64 S_DS3D" />
+			<Option target="Release Mingw64 S_DS3D" />
 		</Unit>
-		<Unit filename="src/blua/lvm.h" />
-		<Unit filename="src/blua/lzio.c">
+		<Unit filename="src/hardware/s_fmod/s_fmod.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+			<Option target="Debug Mingw S_FMOD" />
+			<Option target="Release Mingw S_FMOD" />
+			<Option target="Debug Mingw64 S_FMOD" />
+			<Option target="Release Mingw64 S_FMOD" />
 		</Unit>
-		<Unit filename="src/blua/lzio.h" />
-		<Unit filename="src/byteptr.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/hardware/s_openal/s_openal.c">
+			<Option compilerVar="CC" />
+			<Option target="Debug Mingw S_OpenAL" />
+			<Option target="Release Mingw S_OpenAL" />
+			<Option target="Debug Shared S_OpenAL" />
+			<Option target="Release Shared S_OpenAL" />
+			<Option target="Debug Mingw64 S_OpenAL" />
+			<Option target="Release Mingw64 S_OpenAL" />
 		</Unit>
-		<Unit filename="src/command.c">
+		<Unit filename="src/hu_stuff.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/command.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/hu_stuff.h" />
+		<Unit filename="src/i_addrinfo.c">
+			<Option compilerVar="CC" />
+			<Option compile="0" />
+			<Option link="0" />
 		</Unit>
-		<Unit filename="src/comptime.c">
+		<Unit filename="src/i_addrinfo.h" />
+		<Unit filename="src/i_joy.h" />
+		<Unit filename="src/i_net.h" />
+		<Unit filename="src/i_sound.h" />
+		<Unit filename="src/i_system.h" />
+		<Unit filename="src/i_tcp.c">
 			<Option compilerVar="CC" />
-			<Option weight="100" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/console.c">
+		<Unit filename="src/i_tcp.h" />
+		<Unit filename="src/i_video.h" />
+		<Unit filename="src/info.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/console.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/info.h" />
+		<Unit filename="src/keys.h" />
+		<Unit filename="src/lua_baselib.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/d_clisrv.c">
+		<Unit filename="src/lua_blockmaplib.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_clisrv.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_event.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_main.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_main.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_net.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_net.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_netcmd.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_netcmd.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_netfil.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_netfil.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_player.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_think.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/d_ticcmd.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/dehacked.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/dehacked.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/doomdata.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/doomdef.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/doomstat.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/doomtype.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/dummy/i_cdmus.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-		</Unit>
-		<Unit filename="src/dummy/i_main.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-		</Unit>
-		<Unit filename="src/dummy/i_net.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-		</Unit>
-		<Unit filename="src/dummy/i_sound.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-		</Unit>
-		<Unit filename="src/dummy/i_system.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-		</Unit>
-		<Unit filename="src/dummy/i_video.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-		</Unit>
-		<Unit filename="src/f_finale.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/f_finale.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/f_wipe.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/fastcmp.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/filesrch.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/filesrch.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/g_game.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/g_game.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/g_input.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/g_input.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/g_state.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw3dsdrv.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw3sound.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw3sound.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_bsp.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_cache.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_data.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_defs.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_dll.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_draw.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_drv.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_glide.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_glob.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_light.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_light.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_main.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_main.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_md2.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_md2.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hw_trick.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/hws_data.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hardware/r_minigl/r_minigl.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Mingw R_MiniGL" />
-			<Option target="Release Mingw R_MiniGL" />
-			<Option target="Debug Mingw64 R_MiniGL" />
-			<Option target="Release Mingw64 R_MiniGL" />
-		</Unit>
-		<Unit filename="src/hardware/r_opengl/ogl_win.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Mingw R_OpenGL" />
-			<Option target="Release Mingw R_OpenGL" />
-			<Option target="Debug Mingw64 R_OpenGL" />
-			<Option target="Release Mingw64 R_OpenGL" />
-		</Unit>
-		<Unit filename="src/hardware/r_opengl/r_opengl.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw R_OpenGL" />
-			<Option target="Release Mingw R_OpenGL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64 R_OpenGL" />
-			<Option target="Release Mingw64 R_OpenGL" />
-		</Unit>
-		<Unit filename="src/hardware/r_opengl/r_opengl.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Mingw R_OpenGL" />
-			<Option target="Release Mingw R_OpenGL" />
-			<Option target="Debug Mingw R_MiniGL" />
-			<Option target="Release Mingw R_MiniGL" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64 R_OpenGL" />
-			<Option target="Release Mingw64 R_OpenGL" />
-			<Option target="Debug Mingw64 R_MiniGL" />
-			<Option target="Release Mingw64 R_MiniGL" />
-		</Unit>
-		<Unit filename="src/hardware/s_ds3d/s_ds3d.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Mingw S_DS3D" />
-			<Option target="Release Mingw S_DS3D" />
-			<Option target="Debug Mingw64 S_DS3D" />
-			<Option target="Release Mingw64 S_DS3D" />
-		</Unit>
-		<Unit filename="src/hardware/s_fmod/s_fmod.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Mingw S_FMOD" />
-			<Option target="Release Mingw S_FMOD" />
-			<Option target="Debug Mingw64 S_FMOD" />
-			<Option target="Release Mingw64 S_FMOD" />
-		</Unit>
-		<Unit filename="src/hardware/s_openal/s_openal.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Mingw S_OpenAL" />
-			<Option target="Release Mingw S_OpenAL" />
-			<Option target="Debug Shared S_OpenAL" />
-			<Option target="Release Shared S_OpenAL" />
-			<Option target="Debug Mingw64 S_OpenAL" />
-			<Option target="Release Mingw64 S_OpenAL" />
-		</Unit>
-		<Unit filename="src/hu_stuff.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/hu_stuff.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/i_joy.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/i_net.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/i_sound.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/i_system.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/i_tcp.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/i_tcp.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/i_video.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/info.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/info.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/keys.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_baselib.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_consolelib.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_hook.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_hooklib.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_hud.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_hudlib.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_infolib.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_libs.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_maplib.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_mathlib.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_mobjlib.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_playerlib.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_script.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_script.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_skinlib.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lua_thinkerlib.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lzf.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/lzf.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_aatree.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_aatree.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_anigif.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_anigif.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_argv.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_argv.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_bbox.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_bbox.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_cheat.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_cheat.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_cond.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_cond.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_dllist.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_fixed.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_fixed.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_menu.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_menu.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_misc.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_misc.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_queue.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_queue.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_random.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_random.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/m_swap.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/md5.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/md5.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/mserv.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/mserv.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/p5prof.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/p_ceilng.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/p_enemy.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/p_floor.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/p_inter.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/p_lights.c">
-			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/p_local.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/p_map.c">
+		<Unit filename="src/lua_consolelib.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/p_maputl.c">
+		<Unit filename="src/lua_hook.h" />
+		<Unit filename="src/lua_hooklib.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/p_maputl.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/lua_hud.h" />
+		<Unit filename="src/lua_hudlib.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/p_mobj.c">
+		<Unit filename="src/lua_infolib.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/p_mobj.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/lua_libs.h" />
+		<Unit filename="src/lua_maplib.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/p_polyobj.c">
+		<Unit filename="src/lua_mathlib.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/p_polyobj.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/lua_mobjlib.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/p_pspr.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/lua_playerlib.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/p_saveg.c">
+		<Unit filename="src/lua_script.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/p_saveg.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/lua_script.h" />
+		<Unit filename="src/lua_skinlib.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/p_setup.c">
+		<Unit filename="src/lua_thinkerlib.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/p_setup.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/lzf.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/p_sight.c">
+		<Unit filename="src/lzf.h" />
+		<Unit filename="src/m_aatree.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/p_spec.c">
+		<Unit filename="src/m_aatree.h" />
+		<Unit filename="src/m_anigif.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/p_spec.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/m_anigif.h" />
+		<Unit filename="src/m_argv.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/p_telept.c">
+		<Unit filename="src/m_argv.h" />
+		<Unit filename="src/m_bbox.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/m_bbox.h" />
+		<Unit filename="src/m_cheat.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/p_tick.c">
+		<Unit filename="src/m_cheat.h" />
+		<Unit filename="src/m_cond.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/p_tick.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/m_cond.h" />
+		<Unit filename="src/m_dllist.h" />
+		<Unit filename="src/m_fixed.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/p_user.c">
+		<Unit filename="src/m_fixed.h" />
+		<Unit filename="src/m_menu.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_bsp.c">
+		<Unit filename="src/m_menu.h" />
+		<Unit filename="src/m_misc.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_bsp.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/m_misc.h" />
+		<Unit filename="src/m_queue.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/r_data.c">
+		<Unit filename="src/m_queue.h" />
+		<Unit filename="src/m_random.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_data.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/m_random.h" />
+		<Unit filename="src/m_swap.h" />
+		<Unit filename="src/md5.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/r_defs.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/md5.h" />
+		<Unit filename="src/mserv.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/r_draw.c">
+		<Unit filename="src/mserv.h" />
+		<Unit filename="src/p5prof.h" />
+		<Unit filename="src/p_ceilng.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_draw.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/p_enemy.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/r_draw16.c">
+		<Unit filename="src/p_floor.c">
 			<Option compilerVar="CC" />
-			<Option compile="0" />
-			<Option link="0" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_draw8.c">
+		<Unit filename="src/p_inter.c">
 			<Option compilerVar="CC" />
-			<Option compile="0" />
-			<Option link="0" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_local.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/p_lights.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/r_main.c">
+		<Unit filename="src/p_local.h" />
+		<Unit filename="src/p_map.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_main.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/p_maputl.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/r_plane.c">
+		<Unit filename="src/p_maputl.h" />
+		<Unit filename="src/p_mobj.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_plane.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/p_mobj.h" />
+		<Unit filename="src/p_polyobj.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/r_segs.c">
+		<Unit filename="src/p_polyobj.h" />
+		<Unit filename="src/p_pspr.h" />
+		<Unit filename="src/p_saveg.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_segs.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/p_saveg.h" />
+		<Unit filename="src/p_setup.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/r_sky.c">
+		<Unit filename="src/p_setup.h" />
+		<Unit filename="src/p_sight.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_sky.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/p_slopes.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/r_splats.c">
+		<Unit filename="src/p_slopes.h" />
+		<Unit filename="src/p_spec.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_splats.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/p_spec.h" />
+		<Unit filename="src/p_telept.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/r_state.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/p_tick.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/r_things.c">
+		<Unit filename="src/p_tick.h" />
+		<Unit filename="src/p_user.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/r_things.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/r_bsp.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/s_sound.c">
+		<Unit filename="src/r_bsp.h" />
+		<Unit filename="src/r_data.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/s_sound.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/r_data.h" />
+		<Unit filename="src/r_defs.h" />
+		<Unit filename="src/r_draw.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/screen.c">
+		<Unit filename="src/r_draw.h" />
+		<Unit filename="src/r_draw16.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+			<Option compile="0" />
+			<Option link="0" />
 		</Unit>
-		<Unit filename="src/screen.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/r_draw8.c">
+			<Option compilerVar="CC" />
+			<Option compile="0" />
+			<Option link="0" />
+		</Unit>
+		<Unit filename="src/r_local.h" />
+		<Unit filename="src/r_main.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/r_main.h" />
+		<Unit filename="src/r_plane.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/r_plane.h" />
+		<Unit filename="src/r_segs.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/r_segs.h" />
+		<Unit filename="src/r_sky.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/r_sky.h" />
+		<Unit filename="src/r_splats.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/r_splats.h" />
+		<Unit filename="src/r_state.h" />
+		<Unit filename="src/r_things.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/r_things.h" />
+		<Unit filename="src/s_sound.c">
+			<Option compilerVar="CC" />
+		</Unit>
+		<Unit filename="src/s_sound.h" />
+		<Unit filename="src/screen.c">
+			<Option compilerVar="CC" />
 		</Unit>
-		<Unit filename="src/sdl2/IMG_xpm.c">
+		<Unit filename="src/screen.h" />
+		<Unit filename="src/sdl/IMG_xpm.c">
 			<Option compilerVar="CC" />
+			<Option compile="0" />
+			<Option link="0" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Linux/SDL" />
@@ -4166,7 +1744,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/SDL_icon.xpm">
+		<Unit filename="src/sdl/SDL_icon.xpm">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Linux/SDL" />
@@ -4174,7 +1752,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/dosstr.c">
+		<Unit filename="src/sdl/dosstr.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4183,7 +1761,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/endtxt.c">
+		<Unit filename="src/sdl/endtxt.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4192,7 +1770,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/endtxt.h">
+		<Unit filename="src/sdl/endtxt.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Linux/SDL" />
@@ -4200,7 +1778,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/hwsym_sdl.c">
+		<Unit filename="src/sdl/hwsym_sdl.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4209,7 +1787,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/hwsym_sdl.h">
+		<Unit filename="src/sdl/hwsym_sdl.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Linux/SDL" />
@@ -4217,7 +1795,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/i_cdmus.c">
+		<Unit filename="src/sdl/i_cdmus.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4226,7 +1804,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/i_main.c">
+		<Unit filename="src/sdl/i_main.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4235,7 +1813,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/i_net.c">
+		<Unit filename="src/sdl/i_net.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4244,7 +1822,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/i_system.c">
+		<Unit filename="src/sdl/i_system.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4253,7 +1831,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/i_ttf.c">
+		<Unit filename="src/sdl/i_ttf.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4262,7 +1840,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/i_ttf.h">
+		<Unit filename="src/sdl/i_ttf.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Linux/SDL" />
@@ -4270,7 +1848,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/i_video.c">
+		<Unit filename="src/sdl/i_video.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4279,7 +1857,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/mixer_sound.c">
+		<Unit filename="src/sdl/mixer_sound.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4288,7 +1866,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/ogl_sdl.c">
+		<Unit filename="src/sdl/ogl_sdl.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4297,7 +1875,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/ogl_sdl.h">
+		<Unit filename="src/sdl/ogl_sdl.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Linux/SDL" />
@@ -4305,7 +1883,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/sdl_sound.c">
+		<Unit filename="src/sdl/sdl_sound.c">
 			<Option compilerVar="CC" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
@@ -4314,7 +1892,7 @@ HW3SOUND for 3D hardware sound  support
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
 		</Unit>
-		<Unit filename="src/sdl2/sdlmain.h">
+		<Unit filename="src/sdl/sdlmain.h">
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Linux/SDL" />
@@ -4324,120 +1902,39 @@ HW3SOUND for 3D hardware sound  support
 		</Unit>
 		<Unit filename="src/sounds.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/sounds.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
+		<Unit filename="src/sounds.h" />
 		<Unit filename="src/st_stuff.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/st_stuff.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
+		<Unit filename="src/st_stuff.h" />
 		<Unit filename="src/string.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
-		<Unit filename="src/tables.c">
+		<Unit filename="src/t_facon.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+			<Option compile="0" />
+			<Option link="0" />
 		</Unit>
-		<Unit filename="src/tables.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
+		<Unit filename="src/t_fsin.c">
+			<Option compilerVar="CC" />
+			<Option compile="0" />
+			<Option link="0" />
+		</Unit>
+		<Unit filename="src/t_ftan.c">
+			<Option compilerVar="CC" />
+			<Option compile="0" />
+			<Option link="0" />
+		</Unit>
+		<Unit filename="src/t_tan2a.c">
+			<Option compilerVar="CC" />
+			<Option compile="0" />
+			<Option link="0" />
+		</Unit>
+		<Unit filename="src/tables.c">
+			<Option compilerVar="CC" />
 		</Unit>
+		<Unit filename="src/tables.h" />
 		<Unit filename="src/tmap.nas">
 			<Option target="Debug Mingw/SDL" />
 			<Option target="Release Mingw/SDL" />
@@ -4460,46 +1957,17 @@ HW3SOUND for 3D hardware sound  support
 		</Unit>
 		<Unit filename="src/v_video.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/v_video.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
+		<Unit filename="src/v_video.h" />
 		<Unit filename="src/vid_copy.s">
 			<Option compilerVar="CC" />
-			<Option compiler="gcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
-			<Option compiler="ppcgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
+			<Option compiler="avrgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
 			<Option compiler="gnu_gcc_compiler_for_mingw32" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
+			<Option compiler="gnu_gcc_compiler_for_mingw64" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
 			<Option compiler="armelfgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
 			<Option compiler="tricoregcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
-			<Option compiler="avrgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
-			<Option compiler="gnu_gcc_compiler_for_mingw64" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
+			<Option compiler="ppcgcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
+			<Option compiler="gcc" use="1" buildCommand="$compiler $options -x assembler-with-cpp -c $file -o $object" />
 			<Option target="Debug Native/SDL" />
 			<Option target="Release Native/SDL" />
 			<Option target="Debug Linux/SDL" />
@@ -4511,37 +1979,8 @@ HW3SOUND for 3D hardware sound  support
 		</Unit>
 		<Unit filename="src/w_wad.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/w_wad.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
+		<Unit filename="src/w_wad.h" />
 		<Unit filename="src/win32/Srb2win.rc">
 			<Option compilerVar="WINDRES" />
 			<Option target="Debug Mingw/DirectX" />
@@ -4667,70 +2106,12 @@ HW3SOUND for 3D hardware sound  support
 		</Unit>
 		<Unit filename="src/y_inter.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/y_inter.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
+		<Unit filename="src/y_inter.h" />
 		<Unit filename="src/z_zone.c">
 			<Option compilerVar="CC" />
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
-		</Unit>
-		<Unit filename="src/z_zone.h">
-			<Option target="Debug Native/SDL" />
-			<Option target="Release Native/SDL" />
-			<Option target="Debug Mingw/SDL" />
-			<Option target="Release Mingw/SDL" />
-			<Option target="Debug Mingw/DirectX" />
-			<Option target="Release Mingw/DirectX" />
-			<Option target="Debug Any/Dummy" />
-			<Option target="Release Any/Dummy" />
-			<Option target="Debug Linux/SDL" />
-			<Option target="Release Linux/SDL" />
-			<Option target="Debug Mingw64/SDL" />
-			<Option target="Release Mingw64/SDL" />
-			<Option target="Debug Mingw64/DirectX" />
-			<Option target="Release Mingw64/DirectX" />
 		</Unit>
+		<Unit filename="src/z_zone.h" />
 		<Extensions>
 			<envvars />
 			<code_completion />
diff --git a/debian/docs b/debian/docs
index f3d4ef20e5a4ce3dd58bd8cf313bd95fcd7ec564..b43bf86b50fd8d3529a0dc062c30006ed38f309e 100644
--- a/debian/docs
+++ b/debian/docs
@@ -1,2 +1 @@
-readme.txt
-readme.txt
+README.md
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ba354c2899870ccb7d4d850863b6a20ebd618110..cc728a61363ae095ee6746cc36811c1d7f981731 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -231,6 +231,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
 	add_definitions(-DHAVE_BLUA)
 	set(SRB2_LUA_SOURCES
 		lua_baselib.c
+		lua_blockmaplib.c
 		lua_consolelib.c
 		lua_hooklib.c
 		lua_hudlib.c
diff --git a/src/Makefile b/src/Makefile
index ce4b569eebd7dcc94cfc8858daea7bf4f38dd287..76f013c5285aaf684c2517cb0cf05a0069f08d42 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -179,6 +179,9 @@ endif
 
 ifdef LINUX
 UNIXCOMMON=1
+ifndef NOGME
+HAVE_LIBGME=1
+endif
 endif
 
 ifdef SOLARIS
@@ -315,6 +318,13 @@ LIBS+=$(PNG_LDFLAGS)
 CFLAGS+=$(PNG_CFLAGS)
 endif
 
+ZLIB_PKGCONFIG?=zlib
+ZLIB_CFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --cflags)
+ZLIB_LDFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --libs)
+
+LIBS+=$(ZLIB_LDFLAGS)
+CFLAGS+=$(ZLIB_CFLAGS)
+
 ifdef HAVE_LIBGME
 OPTS+=-DHAVE_LIBGME
 
@@ -366,6 +376,14 @@ endif
 
 	OPTS:=-fno-exceptions $(OPTS)
 
+ifdef MOBJCONSISTANCY
+	OPTS+=-DMOBJCONSISTANCY
+endif
+
+ifdef PACKETDROP
+	OPTS+=-DPACKETDROP
+endif
+
 ifdef DEBUGMODE
 
 	# build with debugging information
@@ -375,7 +393,7 @@ ifdef GCC48
 else
 	CFLAGS+=-O0
 endif
-	CFLAGS+= -Wall -DPARANOIA -DRANGECHECK
+	CFLAGS+= -Wall -DPARANOIA -DRANGECHECK -DPACKETDROP -DMOBJCONSISTANCY
 else
 
 
diff --git a/src/blua/Makefile.cfg b/src/blua/Makefile.cfg
index e3fb3df4664e4943aff54361dd32be4500675bdd..8d2e7371428db75ced4042be0f33167a594d65f3 100644
--- a/src/blua/Makefile.cfg
+++ b/src/blua/Makefile.cfg
@@ -48,4 +48,5 @@ OBJS:=$(OBJS) \
 	$(OBJDIR)/lua_skinlib.o \
 	$(OBJDIR)/lua_thinkerlib.o \
 	$(OBJDIR)/lua_maplib.o \
+	$(OBJDIR)/lua_blockmaplib.o \
 	$(OBJDIR)/lua_hudlib.o
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 7ea95cfb8f0e7a11e01a5eedf11b200b68b85128..b5f36ad4206cf912fcd53e75b3eacd0218da08ed 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -58,14 +58,14 @@
 // NETWORKING
 //
 // gametic is the tic about to (or currently being) run
-// maketic is the tic that hasn't had control made for it yet
-// server:
+// Server:
+//   maketic is the tic that hasn't had control made for it yet
 //   nettics is the tic for each node
 //   firstticstosend is the lowest value of nettics
-// client:
-//   neededtic is the tic needed by the client for run the game
+// Client:
+//   neededtic is the tic needed by the client to run the game
 //   firstticstosend is used to optimize a condition
-// normally maketic >= gametic > 0
+// Normally maketic >= gametic > 0
 
 #define PREDICTIONQUEUE BACKUPTICS
 #define PREDICTIONMASK (PREDICTIONQUEUE-1)
@@ -151,12 +151,6 @@ static consvar_t cv_showjoinaddress = {"showjoinaddress", "On", 0, CV_OnOff, NUL
 static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}};
 consvar_t cv_playbackspeed = {"playbackspeed", "1", 0, playbackspeed_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
 
-void D_ResetTiccmds(void)
-{
-	memset(&localcmds, 0, sizeof(ticcmd_t));
-	memset(&localcmds2, 0, sizeof(ticcmd_t));
-}
-
 static inline void *G_DcpyTiccmd(void* dest, const ticcmd_t* src, const size_t n)
 {
 	const size_t d = n / sizeof(ticcmd_t);
@@ -185,11 +179,17 @@ static inline void *G_ScpyTiccmd(ticcmd_t* dest, void* src, const size_t n)
 
 
 
-// some software don't support largest packet
-// (original sersetup, not exactely, but the probabylity of sending a packet
-// of 512 octet is like 0.1)
+// Some software don't support largest packet
+// (original sersetup, not exactely, but the probability of sending a packet
+// of 512 bytes is like 0.1)
 UINT16 software_MAXPACKETLENGTH;
 
+/** Guesses the value of a tic from its lowest byte and from maketic
+  *
+  * \param low The lowest byte of the tic value
+  * \return The full tic value
+  *
+  */
 tic_t ExpandTics(INT32 low)
 {
 	INT32 delta;
@@ -214,7 +214,7 @@ void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum))
 {
 #ifdef PARANOIA
 	if (id >= MAXNETXCMD)
-		I_Error("command id %d too big", id);
+		I_Error("Command id %d too big", id);
 	if (listnetxcmd[id] != 0)
 		I_Error("Command id %d already used", id);
 #endif
@@ -378,7 +378,7 @@ static void ExtraDataTicker(void)
 					{
 						const UINT8 id = *curpos;
 						curpos++;
-						DEBFILE(va("executing x_cmd %u ply %u ", id, i));
+						DEBFILE(va("executing x_cmd %s ply %u ", netxcmdnames[id - 1], i));
 						(listnetxcmd[id])(&curpos, i);
 						DEBFILE("done\n");
 					}
@@ -401,7 +401,11 @@ static void ExtraDataTicker(void)
 			}
 		}
 
-	D_FreeTextcmd(gametic);
+	// If you are a client, you can safely forget the net commands for this tic
+	// If you are the server, you need to remember them until every client has been aknowledged,
+	// because if you need to resend a PT_SERVERTICS packet, you need to put the commands in it
+	if (!server)
+		D_FreeTextcmd(gametic);
 }
 
 static void D_Clearticcmd(tic_t tic)
@@ -416,6 +420,19 @@ static void D_Clearticcmd(tic_t tic)
 	DEBFILE(va("clear tic %5u (%2u)\n", tic, tic%BACKUPTICS));
 }
 
+void D_ResetTiccmds(void)
+{
+	INT32 i;
+
+	memset(&localcmds, 0, sizeof(ticcmd_t));
+	memset(&localcmds2, 0, sizeof(ticcmd_t));
+
+	// Reset the net command list
+	for (i = 0; i < TEXTCMD_HASH_SIZE; i++)
+		while (textcmds[i])
+			D_Clearticcmd(textcmds[i]->tic);
+}
+
 // -----------------------------------------------------------------
 // end of extra data function
 // -----------------------------------------------------------------
@@ -858,12 +875,13 @@ static inline void resynch_write_others(resynchend_pak *rst)
 {
 	UINT8 i;
 
-	rst->ingame = rst->ctfteam = 0;
+	rst->ingame = 0;
 
 	for (i = 0; i < MAXPLAYERS; ++i)
 	{
 		if (!playeringame[i])
 		{
+			rst->ctfteam[i] = 0;
 			rst->score[i] = 0;
 			rst->numboxes[i] = 0;
 			rst->totalring[i] = 0;
@@ -873,11 +891,8 @@ static inline void resynch_write_others(resynchend_pak *rst)
 		}
 
 		if (!players[i].spectator)
-		{
 			rst->ingame |= (1<<i);
-			if (players[i].ctfteam > 1)
-				rst->ctfteam |= (1<<i);
-		}
+		rst->ctfteam[i] = (INT32)LONG(players[i].ctfteam);
 		rst->score[i] = (UINT32)LONG(players[i].score);
 		rst->numboxes[i] = SHORT(players[i].numboxes);
 		rst->totalring[i] = SHORT(players[i].totalring);
@@ -887,28 +902,18 @@ static inline void resynch_write_others(resynchend_pak *rst)
 
 	// endian safeness
 	rst->ingame = (UINT32)LONG(rst->ingame);
-	rst->ctfteam = (UINT32)LONG(rst->ctfteam);
 }
 
 static inline void resynch_read_others(resynchend_pak *p)
 {
 	UINT8 i;
 	UINT32 loc_ingame = (UINT32)LONG(p->ingame);
-	UINT32 loc_ctfteam = (UINT32)LONG(p->ctfteam);
 
 	for (i = 0; i < MAXPLAYERS; ++i)
 	{
 		// We don't care if they're in the game or not, just write all the data.
-		if (loc_ingame & (1<<i))
-		{
-			players[i].spectator = false;
-			players[i].ctfteam = (loc_ctfteam & (1<<i)) ? 2 : 1;
-		}
-		else
-		{
-			players[i].spectator = true;
-			players[i].ctfteam = 0;
-		}
+		players[i].spectator = !(loc_ingame & i<<i);
+		players[i].ctfteam = (INT32)LONG(p->ctfteam[i]); // no, 0 does not mean spectator, at least not in Match
 		players[i].score = (UINT32)LONG(p->score[i]);
 		players[i].numboxes = SHORT(p->numboxes[i]);
 		players[i].totalring = SHORT(p->totalring[i]);
@@ -1041,20 +1046,20 @@ static INT16 Consistancy(void);
 
 typedef enum
 {
-	cl_searching,
-	cl_downloadfiles,
-	cl_askjoin,
-	cl_waitjoinresponse,
+	CL_SEARCHING,
+	CL_DOWNLOADFILES,
+	CL_ASKJOIN,
+	CL_WAITJOINRESPONSE,
 #ifdef JOININGAME
-	cl_downloadsavegame,
+	CL_DOWNLOADSAVEGAME,
 #endif
-	cl_connected,
-	cl_aborted
+	CL_CONNECTED,
+	CL_ABORTED
 } cl_mode_t;
 
 static void GetPackets(void);
 
-static cl_mode_t cl_mode = cl_searching;
+static cl_mode_t cl_mode = CL_SEARCHING;
 
 // Player name send/load
 
@@ -1107,10 +1112,10 @@ static inline void CL_DrawConnectionStatus(void)
 	M_DrawTextBox(BASEVIDWIDTH/2-128-8, BASEVIDHEIGHT-24-8, 32, 1);
 	V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24-24, V_YELLOWMAP, "Press ESC to abort");
 
-	if (cl_mode != cl_downloadfiles)
+	if (cl_mode != CL_DOWNLOADFILES)
 	{
 		INT32 i, animtime = ((ccstime / 4) & 15) + 16;
-		UINT8 palstart = (cl_mode == cl_searching) ? 32 : 96;
+		UINT8 palstart = (cl_mode == CL_SEARCHING) ? 32 : 96;
 		// 15 pal entries total.
 		const char *cltext;
 
@@ -1120,7 +1125,7 @@ static inline void CL_DrawConnectionStatus(void)
 		switch (cl_mode)
 		{
 #ifdef JOININGAME
-			case cl_downloadsavegame:
+			case CL_DOWNLOADSAVEGAME:
 				cltext = M_GetText("Downloading game state...");
 				Net_GetNetStat();
 				V_DrawString(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, V_20TRANS|V_MONOSPACE,
@@ -1129,8 +1134,8 @@ static inline void CL_DrawConnectionStatus(void)
 					va("%3.1fK/s ", ((double)getbps)/1024));
 				break;
 #endif
-			case cl_askjoin:
-			case cl_waitjoinresponse:
+			case CL_ASKJOIN:
+			case CL_WAITJOINRESPONSE:
 				cltext = M_GetText("Requesting to join...");
 				break;
 			default:
@@ -1164,11 +1169,16 @@ static inline void CL_DrawConnectionStatus(void)
 }
 #endif
 
-//
-// CL_SendJoin
-//
-// send a special packet for declare how many player in local
-// used only in arbitratrenetstart()
+/** Sends a special packet to declare how many players in local
+  * Used only in arbitratrenetstart()
+  * Sends a PT_CLIENTJOIN packet to the server
+  *
+  * \return True if the packet was successfully sent
+  * \todo Improve the description...
+  *       Because to be honest, I have no idea what arbitratrenetstart is...
+  *       Is it even used...?
+  *
+  */
 static boolean CL_SendJoin(void)
 {
 	UINT8 localplayers = 1;
@@ -1303,6 +1313,12 @@ static void SV_SendPlayerInfo(INT32 node)
 	HSendPacket(node, false, 0, sizeof(plrinfo) * MAXPLAYERS);
 }
 
+/** Sends a PT_SERVERCFG packet
+  *
+  * \param node The destination
+  * \return True if the packet was successfully sent
+  *
+  */
 static boolean SV_SendServerConfig(INT32 node)
 {
 	INT32 i;
@@ -1435,7 +1451,7 @@ static void SV_SendSaveGame(INT32 node)
 		WRITEUINT32(savebuffer, 0);
 	}
 
-	SendRam(node, buffertosend, length, SF_RAM, 0);
+	SV_SendRam(node, buffertosend, length, SF_RAM, 0);
 	save_p = NULL;
 }
 
@@ -1530,7 +1546,7 @@ static void CL_LoadReceivedSavegame(void)
 		{
 			CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl);
 			if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
-				CONS_Printf(M_GetText("ZONE"));
+				CONS_Printf(M_GetText(" ZONE"));
 			if (actnum > 0)
 				CONS_Printf(" %2d", actnum);
 		}
@@ -1686,11 +1702,252 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
 
 #endif // ifndef NONET
 
-// use adaptive send using net_bandwidth and stat.sendbytes
+/** Called by CL_ServerConnectionTicker
+  *
+  * \param viams ???
+  * \param asksent ???
+  * \return False if the connection was aborted
+  * \sa CL_ServerConnectionTicker
+  * \sa CL_ConnectToServer
+  *
+  */
+static boolean CL_ServerConnectionSearchTicker(boolean viams, tic_t *asksent)
+{
+#ifndef NONET
+	INT32 i;
+#endif
+
+#ifndef NONET
+	// serverlist is updated by GetPacket function
+	if (serverlistcount > 0)
+	{
+		// this can be a responce to our broadcast request
+		if (servernode == -1 || servernode >= MAXNETNODES)
+		{
+			i = 0;
+			servernode = serverlist[i].node;
+			CONS_Printf(M_GetText("Found, "));
+		}
+		else
+		{
+			i = SL_SearchServer(servernode);
+			if (i < 0)
+				return true;
+		}
+
+		// Quit here rather than downloading files and being refused later.
+		if (serverlist[i].info.numberofplayer >= serverlist[i].info.maxplayer)
+		{
+			D_QuitNetGame();
+			CL_Reset();
+			D_StartTitle();
+			M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING);
+			return false;
+		}
+
+		if (!server)
+		{
+			D_ParseFileneeded(serverlist[i].info.fileneedednum,
+				serverlist[i].info.fileneeded);
+			CONS_Printf(M_GetText("Checking files...\n"));
+			i = CL_CheckFiles();
+			if (i == 2) // cannot join for some reason
+			{
+				D_QuitNetGame();
+				CL_Reset();
+				D_StartTitle();
+				M_StartMessage(M_GetText(
+					"You have WAD files loaded or have\n"
+					"modified the game in some way, and\n"
+					"your file list does not match\n"
+					"the server's file list.\n"
+					"Please restart SRB2 before connecting.\n\n"
+					"Press ESC\n"
+				), NULL, MM_NOTHING);
+				return false;
+			}
+			else if (i == 1)
+				cl_mode = CL_ASKJOIN;
+			else
+			{
+				// must download something
+				// can we, though?
+				if (!CL_CheckDownloadable()) // nope!
+				{
+					D_QuitNetGame();
+					CL_Reset();
+					D_StartTitle();
+					M_StartMessage(M_GetText(
+						"You cannot connect to this server\n"
+						"because you cannot download the files\n"
+						"that you are missing from the server.\n\n"
+						"See the console or log file for\n"
+						"more details.\n\n"
+						"Press ESC\n"
+					), NULL, MM_NOTHING);
+					return false;
+				}
+				// no problem if can't send packet, we will retry later
+				if (CL_SendRequestFile())
+					cl_mode = CL_DOWNLOADFILES;
+			}
+		}
+		else
+			cl_mode = CL_ASKJOIN; // files need not be checked for the server.
+
+		return true;
+	}
+
+	// Ask the info to the server (askinfo packet)
+	if (*asksent + NEWTICRATE < I_GetTime())
+	{
+		SendAskInfo(servernode, viams);
+		*asksent = I_GetTime();
+	}
+#else
+	(void)viams;
+	(void)asksent;
+	// No netgames, so we skip this state.
+	cl_mode = CL_ASKJOIN;
+#endif // ifndef NONET/else
+
+	return true;
+}
+
+/** Called by CL_ConnectToServer
+  *
+  * \param viams ???
+  * \param tmpsave The name of the gamestate file???
+  * \param oldtic Used for knowing when to poll events and redraw
+  * \param asksent ???
+  * \return False if the connection was aborted
+  * \sa CL_ServerConnectionSearchTicker
+  * \sa CL_ConnectToServer
+  *
+  */
+static boolean CL_ServerConnectionTicker(boolean viams, const char *tmpsave, tic_t *oldtic, tic_t *asksent)
+{
+	boolean waitmore;
+	INT32 i;
+
+#ifdef NONET
+	(void)tmpsave;
+#endif
+
+	switch (cl_mode)
+	{
+		case CL_SEARCHING:
+			if (!CL_ServerConnectionSearchTicker(viams, asksent))
+				return false;
+			break;
+
+		case CL_DOWNLOADFILES:
+			waitmore = false;
+			for (i = 0; i < fileneedednum; i++)
+				if (fileneeded[i].status == FS_DOWNLOADING
+					|| fileneeded[i].status == FS_REQUESTED)
+				{
+					waitmore = true;
+					break;
+				}
+			if (waitmore)
+				break; // exit the case
+
+			cl_mode = CL_ASKJOIN; // don't break case continue to cljoin request now
+
+		case CL_ASKJOIN:
+			CL_LoadServerFiles();
+#ifdef JOININGAME
+			// prepare structures to save the file
+			// WARNING: this can be useless in case of server not in GS_LEVEL
+			// but since the network layer doesn't provide ordered packets...
+			CL_PrepareDownloadSaveGame(tmpsave);
+#endif
+			if (CL_SendJoin())
+				cl_mode = CL_WAITJOINRESPONSE;
+			break;
+
+#ifdef JOININGAME
+		case CL_DOWNLOADSAVEGAME:
+			// At this state, the first (and only) needed file is the gamestate
+			if (fileneeded[0].status == FS_FOUND)
+			{
+				// Gamestate is now handled within CL_LoadReceivedSavegame()
+				CL_LoadReceivedSavegame();
+				cl_mode = CL_CONNECTED;
+			} // don't break case continue to CL_CONNECTED
+			else
+				break;
+#endif
+
+		case CL_WAITJOINRESPONSE:
+		case CL_CONNECTED:
+		default:
+			break;
+
+		// Connection closed by cancel, timeout or refusal.
+		case CL_ABORTED:
+			cl_mode = CL_SEARCHING;
+			return false;
+
+	}
+
+	GetPackets();
+	Net_AckTicker();
+
+	// Call it only once by tic
+	if (*oldtic != I_GetTime())
+	{
+		INT32 key;
+
+		I_OsPolling();
+		key = I_GetKey();
+		if (key == KEY_ESCAPE)
+		{
+			CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
+//				M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
+			D_QuitNetGame();
+			CL_Reset();
+			D_StartTitle();
+			return false;
+		}
+
+		// why are these here? this is for servers, we're a client
+		//if (key == 's' && server)
+		//	doomcom->numnodes = (INT16)pnumnodes;
+		//SV_FileSendTicker();
+		*oldtic = I_GetTime();
+
+#ifdef CLIENT_LOADINGSCREEN
+		if (!server && cl_mode != CL_CONNECTED && cl_mode != CL_ABORTED)
+		{
+			F_TitleScreenTicker(true);
+			F_TitleScreenDrawer();
+			CL_DrawConnectionStatus();
+			I_UpdateNoVsync(); // page flip or blit buffer
+			if (moviemode)
+				M_SaveFrame();
+		}
+#else
+		CON_Drawer();
+		I_UpdateNoVsync();
+#endif
+	}
+	else
+		I_Sleep();
+
+	return true;
+}
+
+/** Use adaptive send using net_bandwidth and stat.sendbytes
+  *
+  * \param viams ???
+  * \todo Better description...
+  *
+  */
 static void CL_ConnectToServer(boolean viams)
 {
 	INT32 pnumnodes, nodewaited = doomcom->numnodes, i;
-	boolean waitmore;
 	tic_t oldtic;
 #ifndef NONET
 	tic_t asksent;
@@ -1701,14 +1958,14 @@ static void CL_ConnectToServer(boolean viams)
 	sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
 #endif
 
-	cl_mode = cl_searching;
+	cl_mode = CL_SEARCHING;
 
 #ifdef CLIENT_LOADINGSCREEN
 	lastfilenum = 0;
 #endif
 
 #ifdef JOININGAME
-	// don't get a corrupt savegame error because tmpsave already exists
+	// Don't get a corrupt savegame error because tmpsave already exists
 	if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1)
 		I_Error("Can't delete %s\n", tmpsave);
 #endif
@@ -1732,7 +1989,7 @@ static void CL_ConnectToServer(boolean viams)
 	pnumnodes = 1;
 	oldtic = I_GetTime() - 1;
 #ifndef NONET
-	asksent = (tic_t)-TICRATE;
+	asksent = (tic_t) - TICRATE;
 
 	i = SL_SearchServer(servernode);
 
@@ -1759,197 +2016,23 @@ static void CL_ConnectToServer(boolean viams)
 
 	do
 	{
-		switch (cl_mode)
-		{
-			case cl_searching:
+		// If the connection was aborted for some reason, leave
 #ifndef NONET
-				// serverlist is updated by GetPacket function
-				if (serverlistcount > 0)
-				{
-					// this can be a responce to our broadcast request
-					if (servernode == -1 || servernode >= MAXNETNODES)
-					{
-						i = 0;
-						servernode = serverlist[i].node;
-						CONS_Printf(M_GetText("Found, "));
-					}
-					else
-					{
-						i = SL_SearchServer(servernode);
-						if (i < 0)
-							break; // the case
-					}
-
-					// Quit here rather than downloading files and being refused later.
-					if (serverlist[i].info.numberofplayer >= serverlist[i].info.maxplayer)
-					{
-						D_QuitNetGame();
-						CL_Reset();
-						D_StartTitle();
-						M_StartMessage(va(M_GetText("Maximum players reached: %d\n\nPress ESC\n"), serverlist[i].info.maxplayer), NULL, MM_NOTHING);
-						return;
-					}
-
-					if (!server)
-					{
-						D_ParseFileneeded(serverlist[i].info.fileneedednum,
-							serverlist[i].info.fileneeded);
-						CONS_Printf(M_GetText("Checking files...\n"));
-						i = CL_CheckFiles();
-						if (i == 2) // cannot join for some reason
-						{
-							D_QuitNetGame();
-							CL_Reset();
-							D_StartTitle();
-							M_StartMessage(M_GetText(
-								"You have WAD files loaded or have\n"
-								"modified the game in some way, and\n"
-								"your file list does not match\n"
-								"the server's file list.\n"
-								"Please restart SRB2 before connecting.\n\n"
-								"Press ESC\n"
-							), NULL, MM_NOTHING);
-							return;
-						}
-						else if (i == 1)
-							cl_mode = cl_askjoin;
-						else
-						{
-							// must download something
-							// can we, though?
-							if (!CL_CheckDownloadable()) // nope!
-							{
-								D_QuitNetGame();
-								CL_Reset();
-								D_StartTitle();
-								M_StartMessage(M_GetText(
-									"You cannot conect to this server\n"
-									"because you cannot download the files\n"
-									"that you are missing from the server.\n\n"
-									"See the console or log file for\n"
-									"more details.\n\n"
-									"Press ESC\n"
-								), NULL, MM_NOTHING);
-								return;
-							}
-							// no problem if can't send packet, we will retry later
-							if (CL_SendRequestFile())
-								cl_mode = cl_downloadfiles;
-						}
-					}
-					else
-						cl_mode = cl_askjoin; // files need not be checked for the server.
-					break;
-				}
-				// ask the info to the server (askinfo packet)
-				if (asksent + NEWTICRATE < I_GetTime())
-				{
-					SendAskInfo(servernode, viams);
-					asksent = I_GetTime();
-				}
-#else
-				(void)viams;
-				// No netgames, so we skip this state.
-				cl_mode = cl_askjoin;
-#endif // ifndef NONET/else
-				break;
-			case cl_downloadfiles:
-				waitmore = false;
-				for (i = 0; i < fileneedednum; i++)
-					if (fileneeded[i].status == FS_DOWNLOADING
-						|| fileneeded[i].status == FS_REQUESTED)
-					{
-						waitmore = true;
-						break;
-					}
-				if (waitmore)
-					break; // exit the case
-
-				cl_mode = cl_askjoin; // don't break case continue to cljoin request now
-			case cl_askjoin:
-				CL_LoadServerFiles();
-#ifdef JOININGAME
-				// prepare structures to save the file
-				// WARNING: this can be useless in case of server not in GS_LEVEL
-				// but since the network layer doesn't provide ordered packets...
-				CL_PrepareDownloadSaveGame(tmpsave);
-#endif
-				if (CL_SendJoin())
-					cl_mode = cl_waitjoinresponse;
-				break;
-#ifdef JOININGAME
-			case cl_downloadsavegame:
-				if (fileneeded[0].status == FS_FOUND)
-				{
-					// Gamestate is now handled within CL_LoadReceivedSavegame()
-					CL_LoadReceivedSavegame();
-					cl_mode = cl_connected;
-				} // don't break case continue to cl_connected
-				else
-					break;
-#endif
-			case cl_waitjoinresponse:
-			case cl_connected:
-			default:
-				break;
-
-			// Connection closed by cancel, timeout or refusal.
-			case cl_aborted:
-				cl_mode = cl_searching;
-				return;
-		}
-
-		GetPackets();
-		Net_AckTicker();
-
-		// call it only one by tic
-		if (oldtic != I_GetTime())
-		{
-			INT32 key;
-
-			I_OsPolling();
-			key = I_GetKey();
-			if (key == KEY_ESCAPE)
-			{
-				CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
-//				M_StartMessage(M_GetText("Network game synchronization aborted.\n\nPress ESC\n"), NULL, MM_NOTHING);
-				D_QuitNetGame();
-				CL_Reset();
-				D_StartTitle();
-				return;
-			}
-
-			// why are these here? this is for servers, we're a client
-			//if (key == 's' && server)
-			//	doomcom->numnodes = (INT16)pnumnodes;
-			//FiletxTicker();
-			oldtic = I_GetTime();
-
-#ifdef CLIENT_LOADINGSCREEN
-			if (!server && cl_mode != cl_connected && cl_mode != cl_aborted)
-			{
-				F_TitleScreenTicker(true);
-				F_TitleScreenDrawer();
-				CL_DrawConnectionStatus();
-				I_UpdateNoVsync(); // page flip or blit buffer
-				if (moviemode)
-					M_SaveFrame();
-			}
+		if (!CL_ServerConnectionTicker(viams, tmpsave, &oldtic, &asksent))
 #else
-			CON_Drawer();
-			I_UpdateNoVsync();
+		if (!CL_ServerConnectionTicker(viams, (char*)NULL, &oldtic, (tic_t *)NULL))
 #endif
-		}
-		else I_Sleep();
+			return;
 
 		if (server)
 		{
 			pnumnodes = 0;
 			for (i = 0; i < MAXNETNODES; i++)
-				if (nodeingame[i]) pnumnodes++;
+				if (nodeingame[i])
+					pnumnodes++;
 		}
 	}
-	while (!(cl_mode == cl_connected && (!server || (server && nodewaited <= pnumnodes))));
+	while (!(cl_mode == CL_CONNECTED && (!server || (server && nodewaited <= pnumnodes))));
 
 	DEBFILE(va("Synchronisation Finished\n"));
 
@@ -2206,7 +2289,6 @@ void CL_ClearPlayer(INT32 playernum)
 			P_RemoveMobj(players[playernum].mo->tracer);
 		P_RemoveMobj(players[playernum].mo);
 	}
-	players[playernum].mo = NULL;
 	memset(&players[playernum], 0, sizeof (player_t));
 }
 
@@ -2718,6 +2800,10 @@ void D_ClientServerInit(void)
 	COM_AddCommand("reloadbans", Command_ReloadBan);
 	COM_AddCommand("connect", Command_connect);
 	COM_AddCommand("nodes", Command_Nodes);
+#ifdef PACKETDROP
+	COM_AddCommand("drop", Command_Drop);
+	COM_AddCommand("droprate", Command_Droprate);
+#endif
 #endif
 
 	RegisterNetXCmd(XD_KICK, Got_KickCmd);
@@ -2761,7 +2847,7 @@ void SV_ResetServer(void)
 
 	// +1 because this command will be executed in com_executebuffer in
 	// tryruntic so gametic will be incremented, anyway maketic > gametic
-	// is not a issue
+	// is not an issue
 
 	maketic = gametic + 1;
 	neededtic = maketic;
@@ -2815,7 +2901,7 @@ static inline void SV_GenContext(void)
 	for (i = 0; i < 8; i++)
 	{
 		const char a = M_RandomKey(26*2);
-		if (a <= 26) // uppercase
+		if (a < 26) // uppercase
 			server_context[i] = 'A'+a;
 		else // lowercase
 			server_context[i] = 'a'+(a-26);
@@ -2850,7 +2936,7 @@ void D_QuitNetGame(void)
 		if (serverrunning && ms_RoomId > 0)
 			UnregisterServer();
 	}
-	else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode]!=0)
+	else if (servernode > 0 && servernode < MAXNETNODES && nodeingame[(UINT8)servernode])
 	{
 		netbuffer->packettype = PT_CLIENTQUIT;
 		HSendPacket(servernode, true, 0, 0);
@@ -2871,12 +2957,12 @@ void D_QuitNetGame(void)
 #endif
 }
 
-// add a node to the game (player will follow at map change or at savegame....)
+// Adds a node to the game (player will follow at map change or at savegame....)
 static inline void SV_AddNode(INT32 node)
 {
 	nettics[node] = gametic;
 	supposedtics[node] = gametic;
-	// little hack because the server connect to itself and put
+	// little hack because the server connects to itself and puts
 	// nodeingame when connected not here
 	if (node)
 		nodeingame[node] = true;
@@ -3026,7 +3112,7 @@ static boolean SV_AddWaitingPlayers(void)
 
 void CL_AddSplitscreenPlayer(void)
 {
-	if (cl_mode == cl_connected)
+	if (cl_mode == CL_CONNECTED)
 		CL_SendJoin();
 }
 
@@ -3034,7 +3120,7 @@ void CL_RemoveSplitscreenPlayer(void)
 {
 	XBOXSTATIC UINT8 buf[2];
 
-	if (cl_mode != cl_connected)
+	if (cl_mode != CL_CONNECTED)
 		return;
 
 	buf[0] = (UINT8)secondarydisplayplayer;
@@ -3045,7 +3131,7 @@ void CL_RemoveSplitscreenPlayer(void)
 // is there a game running
 boolean Playing(void)
 {
-	return (server && serverrunning) || (!server && cl_mode == cl_connected);
+	return (server && serverrunning) || (!server && cl_mode == CL_CONNECTED);
 }
 
 boolean SV_SpawnServer(void)
@@ -3093,7 +3179,7 @@ void SV_StopServer(void)
 		D_Clearticcmd(i);
 
 	consoleplayer = 0;
-	cl_mode = cl_searching;
+	cl_mode = CL_SEARCHING;
 	maketic = gametic+1;
 	neededtic = maketic;
 	serverrunning = false;
@@ -3139,6 +3225,11 @@ static size_t TotalTextCmdPerTic(tic_t tic)
 	return total;
 }
 
+/** Called when a PT_CLIENTJOIN packet is received
+  *
+  * \param node The packet sender
+  *
+  */
 static void HandleConnect(SINT8 node)
 {
 	if (bannednode && bannednode[node])
@@ -3170,6 +3261,9 @@ static void HandleConnect(SINT8 node)
 #endif
 			SV_AddNode(node);
 
+			/// \note Wait what???
+			///       What if the gamestate takes more than one second to get downloaded?
+			///       Or if a lagspike happens?
 			// you get a free second before desynch checks. use it wisely.
 			SV_InitResynchVars(node);
 
@@ -3178,6 +3272,7 @@ static void HandleConnect(SINT8 node)
 			if (!SV_SendServerConfig(node))
 			{
 				G_SetGamestate(backupstate);
+				/// \note Shouldn't SV_SendRefuse be called before ResetNode?
 				ResetNode(node);
 				SV_SendRefuse(node, M_GetText("Server couldn't send info, please try again"));
 				/// \todo fix this !!!
@@ -3208,6 +3303,11 @@ static void HandleConnect(SINT8 node)
 	}
 }
 
+/** Called when a PT_SERVERSHUTDOWN packet is received
+  *
+  * \param node The packet sender (should be the server)
+  *
+  */
 static void HandleShutdown(SINT8 node)
 {
 	(void)node;
@@ -3217,6 +3317,11 @@ static void HandleShutdown(SINT8 node)
 	M_StartMessage(M_GetText("Server has shutdown\n\nPress Esc\n"), NULL, MM_NOTHING);
 }
 
+/** Called when a PT_NODETIMEOUT packet is received
+  *
+  * \param node The packet sender (should be the server)
+  *
+  */
 static void HandleTimeout(SINT8 node)
 {
 	(void)node;
@@ -3227,6 +3332,12 @@ static void HandleTimeout(SINT8 node)
 }
 
 #ifndef NONET
+/** Called when a PT_SERVERINFO packet is received
+  *
+  * \param node The packet sender
+  * \note What happens if the packet comes from a client or something like that?
+  *
+  */
 static void HandleServerInfo(SINT8 node)
 {
 	// compute ping in ms
@@ -3240,527 +3351,570 @@ static void HandleServerInfo(SINT8 node)
 }
 #endif
 
-/**	\brief GetPackets
-
-  \todo  break this 300 line function into multiple functions
-*/
-static void GetPackets(void)
-{FILESTAMP
-	XBOXSTATIC INT32 netconsole;
-	XBOXSTATIC SINT8 node;
-	XBOXSTATIC tic_t realend,realstart;
-	XBOXSTATIC UINT8 *pak, *txtpak, numtxtpak;
-FILESTAMP
-
-	player_joining = false;
+/** Handles a packet received from a node that isn't in game
+  *
+  * \param node The packet sender
+  * \todo Choose a better name, as the packet can also come from the server apparently?
+  * \sa HandlePacketFromPlayer
+  * \sa GetPackets
+  *
+  */
+static void HandlePacketFromAwayNode(SINT8 node)
+{
+	if (node != servernode)
+		DEBFILE(va("Received packet from unknown host %d\n", node));
 
-	while (HGetPacket())
+	switch (netbuffer->packettype)
 	{
-		node = (SINT8)doomcom->remotenode;
-		if (netbuffer->packettype == PT_CLIENTJOIN && server)
-		{
-			HandleConnect(node);
-			continue;
-		}
-		if (netbuffer->packettype == PT_SERVERSHUTDOWN && node == servernode
-			&& !server && cl_mode != cl_searching)
-		{
-			HandleShutdown(node);
-			continue;
-		}
-		if (netbuffer->packettype == PT_NODETIMEOUT && node == servernode
-			&& !server && cl_mode != cl_searching)
-		{
-			HandleTimeout(node);
-			continue;
-		}
+		case PT_ASKINFOVIAMS:
+			if (server && serverrunning)
+			{
+				INT32 clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr);
+				SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time));
+				SV_SendPlayerInfo(clientnode); // Send extra info
+				Net_CloseConnection(clientnode);
+				// Don't close connection to MS.
+			}
+			break;
 
-#ifndef NONET
-		if (netbuffer->packettype == PT_SERVERINFO)
-		{
-			HandleServerInfo(node);
-			continue;
-		}
-#endif
+		case PT_ASKINFO:
+			if (server && serverrunning)
+			{
+				SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time));
+				SV_SendPlayerInfo(node); // Send extra info
+				Net_CloseConnection(node);
+			}
+			break;
 
-		if (netbuffer->packettype == PT_PLAYERINFO)
-			continue; // We do nothing with PLAYERINFO, that's for the MS browser.
-
-		if (!nodeingame[node])
-		{
-			if (node != servernode)
-				DEBFILE(va("Received packet from unknown host %d\n", node));
-
-			// anyone trying to join
-			switch (netbuffer->packettype)
+		case PT_SERVERREFUSE: // Negative response of client join request
+			if (server && serverrunning)
+			{ // But wait I thought I'm the server?
+				Net_CloseConnection(node);
+				break;
+			}
+			if (cl_mode == CL_WAITJOINRESPONSE)
 			{
-				case PT_ASKINFOVIAMS:
-					if (server && serverrunning)
-					{
-						INT32 clientnode = I_NetMakeNode(netbuffer->u.msaskinfo.clientaddr);
-						SV_SendServerInfo(clientnode, (tic_t)LONG(netbuffer->u.msaskinfo.time));
-						SV_SendPlayerInfo(clientnode); // send extra info
-						Net_CloseConnection(clientnode);
-						// Don't close connection to MS.
-					}
-					break;
+				D_QuitNetGame();
+				CL_Reset();
+				D_StartTitle();
 
-				case PT_ASKINFO:
-					if (server && serverrunning)
-					{
-						SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time));
-						SV_SendPlayerInfo(node); // send extra info
-						Net_CloseConnection(node);
-					}
-					break;
-				case PT_SERVERREFUSE: // negative response of client join request
-					if (server && serverrunning)
-					{ // but wait I thought I'm the server?
-						Net_CloseConnection(node);
-						break;
-					}
-					if (cl_mode == cl_waitjoinresponse)
-					{
-						D_QuitNetGame();
-						CL_Reset();
-						D_StartTitle();
+				M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"),
+					netbuffer->u.serverrefuse.reason), NULL, MM_NOTHING);
 
-						M_StartMessage(va(M_GetText("Server refuses connection\n\nReason:\n%s"),
-							netbuffer->u.serverrefuse.reason), NULL, MM_NOTHING);
+				// Will be reset by caller. Signals refusal.
+				cl_mode = CL_ABORTED;
+			}
+			break;
 
-						// Will be reset by caller. Signals refusal.
-						cl_mode = cl_aborted;
-					}
-					break;
-				case PT_SERVERCFG: // positive response of client join request
-				{
-					INT32 j;
-					UINT8 *scp;
+		case PT_SERVERCFG: // Positive response of client join request
+		{
+			INT32 j;
+			UINT8 *scp;
 
-					if (server && serverrunning && node != servernode)
-					{ // but wait I thought I'm the server?
-						Net_CloseConnection(node);
-						break;
-					}
-					/// \note how would this happen? and is it doing the right thing if it does?
-					if (cl_mode != cl_waitjoinresponse)
-						break;
+			if (server && serverrunning && node != servernode)
+			{ // but wait I thought I'm the server?
+				Net_CloseConnection(node);
+				break;
+			}
+			/// \note how would this happen? and is it doing the right thing if it does?
+			if (cl_mode != CL_WAITJOINRESPONSE)
+				break;
 
-					if (!server)
-					{
-						maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic);
-						gametype = netbuffer->u.servercfg.gametype;
-						modifiedgame = netbuffer->u.servercfg.modifiedgame;
-						adminplayer = netbuffer->u.servercfg.adminplayer;
-						memcpy(server_context, netbuffer->u.servercfg.server_context, 8);
-					}
+			if (!server)
+			{
+				maketic = gametic = neededtic = (tic_t)LONG(netbuffer->u.servercfg.gametic);
+				gametype = netbuffer->u.servercfg.gametype;
+				modifiedgame = netbuffer->u.servercfg.modifiedgame;
+				adminplayer = netbuffer->u.servercfg.adminplayer;
+				memcpy(server_context, netbuffer->u.servercfg.server_context, 8);
+			}
 
-					nodeingame[(UINT8)servernode] = true;
-					serverplayer = netbuffer->u.servercfg.serverplayer;
-					doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum);
-					mynode = netbuffer->u.servercfg.clientnode;
-					if (serverplayer >= 0)
-						playernode[(UINT8)serverplayer] = servernode;
+			nodeingame[(UINT8)servernode] = true;
+			serverplayer = netbuffer->u.servercfg.serverplayer;
+			doomcom->numslots = SHORT(netbuffer->u.servercfg.totalslotnum);
+			mynode = netbuffer->u.servercfg.clientnode;
+			if (serverplayer >= 0)
+				playernode[(UINT8)serverplayer] = servernode;
 
-					if (netgame)
+			if (netgame)
 #ifdef JOININGAME
-						CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n"));
+				CONS_Printf(M_GetText("Join accepted, waiting for complete game state...\n"));
 #else
-						CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n"));
+				CONS_Printf(M_GetText("Join accepted, waiting for next level change...\n"));
 #endif
-					DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode));
+			DEBFILE(va("Server accept join gametic=%u mynode=%d\n", gametic, mynode));
 
-					memset(playeringame, 0, sizeof(playeringame));
-					for (j = 0; j < MAXPLAYERS; j++)
-					{
-						if (netbuffer->u.servercfg.playerskins[j] == 0xFF
-						 && netbuffer->u.servercfg.playercolor[j] == 0xFF)
-							continue; // not in game
+			memset(playeringame, 0, sizeof(playeringame));
+			for (j = 0; j < MAXPLAYERS; j++)
+			{
+				if (netbuffer->u.servercfg.playerskins[j] == 0xFF
+				 && netbuffer->u.servercfg.playercolor[j] == 0xFF)
+					continue; // not in game
 
-						playeringame[j] = true;
-						SetPlayerSkinByNum(j, (INT32)netbuffer->u.servercfg.playerskins[j]);
-						players[j].skincolor = netbuffer->u.servercfg.playercolor[j];
-					}
+				playeringame[j] = true;
+				SetPlayerSkinByNum(j, (INT32)netbuffer->u.servercfg.playerskins[j]);
+				players[j].skincolor = netbuffer->u.servercfg.playercolor[j];
+			}
 
-					scp = netbuffer->u.servercfg.varlengthinputs;
-					CV_LoadPlayerNames(&scp);
-					CV_LoadNetVars(&scp);
+			scp = netbuffer->u.servercfg.varlengthinputs;
+			CV_LoadPlayerNames(&scp);
+			CV_LoadNetVars(&scp);
 #ifdef JOININGAME
-					if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* ||
-						netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/)
-						cl_mode = cl_downloadsavegame;
-					else
+			/// \note Wait. What if a Lua script uses some global custom variables synched with the NetVars hook?
+			///       Shouldn't them be downloaded even at intermission time?
+			///       Also, according to HandleConnect, the server will send the savegame even during intermission...
+			if (netbuffer->u.servercfg.gamestate == GS_LEVEL/* ||
+				netbuffer->u.servercfg.gamestate == GS_INTERMISSION*/)
+				cl_mode = CL_DOWNLOADSAVEGAME;
+			else
 #endif
-						cl_mode = cl_connected;
-					break;
-				}
-				// handled in d_netfil.c
-				case PT_FILEFRAGMENT:
-					if (server)
-					{ // but wait I thought I'm the server?
-						Net_CloseConnection(node);
-						break;
-					}
-					else
-						Got_Filetxpak();
-					break;
-				case PT_REQUESTFILE:
-					if (server)
-						Got_RequestFilePak(node);
-					break;
-				case PT_NODETIMEOUT:
-				case PT_CLIENTQUIT:
-					if (server)
-						Net_CloseConnection(node);
-					break;
-				case PT_CLIENTCMD:
-					break; // this is not an "unknown packet"
-				case PT_SERVERTICS:
-					// do not remove my own server (we have just get a out of order packet)
-					if (node == servernode)
-						break;
-				default:
-					DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype));
-					Net_CloseConnection(node);
-					break; // ignore it
-			} // switch
-			continue; //while
+				cl_mode = CL_CONNECTED;
+			break;
 		}
-		if (dedicated && node == 0) netconsole = 0;
-		else netconsole = nodetoplayer[node];
+
+		// Handled in d_netfil.c
+		case PT_FILEFRAGMENT:
+			if (server)
+			{ // But wait I thought I'm the server?
+				Net_CloseConnection(node);
+				break;
+			}
+			else
+				Got_Filetxpak();
+			break;
+
+		case PT_REQUESTFILE:
+			if (server)
+				Got_RequestFilePak(node);
+			break;
+
+		case PT_NODETIMEOUT:
+		case PT_CLIENTQUIT:
+			if (server)
+				Net_CloseConnection(node);
+			break;
+
+		case PT_CLIENTCMD:
+			break; // This is not an "unknown packet"
+
+		case PT_SERVERTICS:
+			// Do not remove my own server (we have just get a out of order packet)
+			if (node == servernode)
+				break;
+
+		default:
+			DEBFILE(va("unknown packet received (%d) from unknown host\n",netbuffer->packettype));
+			Net_CloseConnection(node);
+			break; // Ignore it
+
+	}
+}
+
+/** Handles a packet received from a node that is in game
+  *
+  * \param node The packet sender
+  * \todo Choose a better name
+  * \sa HandlePacketFromAwayNode
+  * \sa GetPackets
+  *
+  */
+static void HandlePacketFromPlayer(SINT8 node)
+{FILESTAMP
+	XBOXSTATIC INT32 netconsole;
+	XBOXSTATIC tic_t realend, realstart;
+	XBOXSTATIC UINT8 *pak, *txtpak, numtxtpak;
+FILESTAMP
+
+	txtpak = NULL;
+
+	if (dedicated && node == 0)
+		netconsole = 0;
+	else
+		netconsole = nodetoplayer[node];
 #ifdef PARANOIA
-		if (netconsole >= MAXPLAYERS)
-			I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole);
+	if (netconsole >= MAXPLAYERS)
+		I_Error("bad table nodetoplayer: node %d player %d", doomcom->remotenode, netconsole);
 #endif
 
-		txtpak = NULL;
-
-		switch (netbuffer->packettype)
-		{
+	switch (netbuffer->packettype)
+	{
 // -------------------------------------------- SERVER RECEIVE ----------
-			case PT_RESYNCHGET:
-				SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot);
+		case PT_RESYNCHGET:
+			SV_AcknowledgeResynchAck(netconsole, netbuffer->u.resynchgot);
+			break;
+		case PT_CLIENTCMD:
+		case PT_CLIENT2CMD:
+		case PT_CLIENTMIS:
+		case PT_CLIENT2MIS:
+		case PT_NODEKEEPALIVE:
+		case PT_NODEKEEPALIVEMIS:
+			if (!server)
 				break;
-			case PT_CLIENTCMD:
-			case PT_CLIENT2CMD:
-			case PT_CLIENTMIS:
-			case PT_CLIENT2MIS:
-			case PT_NODEKEEPALIVE:
-			case PT_NODEKEEPALIVEMIS:
-				if (!server)
-					break;
 
-				// ignore tics from those not synched
-				if (resynch_inprogress[node])
-					break;
+			// Ignore tics from those not synched
+			if (resynch_inprogress[node])
+				break;
 
-				// to save bytes, only the low byte of tic numbers are sent
-				// Figure out what the rest of the bytes are
-				realstart = ExpandTics(netbuffer->u.clientpak.client_tic);
-				realend = ExpandTics(netbuffer->u.clientpak.resendfrom);
+			// To save bytes, only the low byte of tic numbers are sent
+			// Use ExpandTics to figure out what the rest of the bytes are
+			realstart = ExpandTics(netbuffer->u.clientpak.client_tic);
+			realend = ExpandTics(netbuffer->u.clientpak.resendfrom);
 
-				if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS
-					|| netbuffer->packettype == PT_NODEKEEPALIVEMIS
-					|| supposedtics[node] < realend)
-				{
-					supposedtics[node] = realend;
-				}
-				// discard out of order packet
-				if (nettics[node] > realend)
-				{
-					DEBFILE(va("out of order ticcmd discarded nettics = %u\n", nettics[node]));
-					break;
-				}
+			if (netbuffer->packettype == PT_CLIENTMIS || netbuffer->packettype == PT_CLIENT2MIS
+				|| netbuffer->packettype == PT_NODEKEEPALIVEMIS
+				|| supposedtics[node] < realend)
+			{
+				supposedtics[node] = realend;
+			}
+			// Discard out of order packet
+			if (nettics[node] > realend)
+			{
+				DEBFILE(va("out of order ticcmd discarded nettics = %u\n", nettics[node]));
+				break;
+			}
 
-				// update the nettics
-				nettics[node] = realend;
+			// Update the nettics
+			nettics[node] = realend;
 
-				// don't do anything for packets of type NODEKEEPALIVE?
-				if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE
-					|| netbuffer->packettype == PT_NODEKEEPALIVEMIS)
-					break;
+			// Don't do anything for packets of type NODEKEEPALIVE?
+			if (netconsole == -1 || netbuffer->packettype == PT_NODEKEEPALIVE
+				|| netbuffer->packettype == PT_NODEKEEPALIVEMIS)
+				break;
 
-				// copy ticcmd
-				G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1);
+			// Copy ticcmd
+			G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1);
 
-				// check ticcmd for "speed hacks"
-				if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE
-					|| netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE)
-				{
-					XBOXSTATIC char buf[2];
-					CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value recieved from node %d\n"), netconsole);
-					//D_Clearticcmd(k);
+			// Check ticcmd for "speed hacks"
+			if (netcmds[maketic%BACKUPTICS][netconsole].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].forwardmove < -MAXPLMOVE
+				|| netcmds[maketic%BACKUPTICS][netconsole].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][netconsole].sidemove < -MAXPLMOVE)
+			{
+				XBOXSTATIC char buf[2];
+				CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), netconsole);
+				//D_Clearticcmd(k);
 
-					buf[0] = (char)netconsole;
-					buf[1] = KICK_MSG_CON_FAIL;
-					SendNetXCmd(XD_KICK, &buf, 2);
-					break;
-				}
+				buf[0] = (char)netconsole;
+				buf[1] = KICK_MSG_CON_FAIL;
+				SendNetXCmd(XD_KICK, &buf, 2);
+				break;
+			}
 
-				// splitscreen cmd
-				if (netbuffer->packettype == PT_CLIENT2CMD && nodetoplayer2[node] >= 0)
-					G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]],
-						&netbuffer->u.client2pak.cmd2, 1);
+			// Splitscreen cmd
+			if (netbuffer->packettype == PT_CLIENT2CMD && nodetoplayer2[node] >= 0)
+				G_MoveTiccmd(&netcmds[maketic%BACKUPTICS][(UINT8)nodetoplayer2[node]],
+					&netbuffer->u.client2pak.cmd2, 1);
 
-				// a delay before we check resynching
-				// used on join or just after a synch fail
-				if (resynch_delay[node])
+			// A delay before we check resynching
+			// Used on join or just after a synch fail
+			if (resynch_delay[node])
+			{
+				--resynch_delay[node];
+				break;
+			}
+			// Check player consistancy during the level
+			if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 && gamestate == GS_LEVEL
+				&& consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy))
+			{
+				SV_RequireResynch(node);
+
+				if (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250)
 				{
-					--resynch_delay[node];
+					if (cv_blamecfail.value)
+						CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"),
+							netconsole+1, player_names[netconsole],
+							consistancy[realstart%BACKUPTICS],
+							SHORT(netbuffer->u.clientpak.consistancy));
+					DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n",
+						netconsole, realstart, consistancy[realstart%BACKUPTICS],
+						SHORT(netbuffer->u.clientpak.consistancy)));
 					break;
 				}
-				// check player consistancy during the level
-				if (realstart <= gametic && realstart > gametic - BACKUPTICS+1 && gamestate == GS_LEVEL
-					&& consistancy[realstart%BACKUPTICS] != SHORT(netbuffer->u.clientpak.consistancy))
+				else
 				{
-					SV_RequireResynch(node);
+					XBOXSTATIC UINT8 buf[3];
 
-					if (cv_resynchattempts.value && resynch_score[node] <= (unsigned)cv_resynchattempts.value*250)
-					{
-						if (cv_blamecfail.value)
-							CONS_Printf(M_GetText("Synch failure for player %d (%s); expected %hd, got %hd\n"),
-								netconsole+1, player_names[netconsole],
-								consistancy[realstart%BACKUPTICS],
-								SHORT(netbuffer->u.clientpak.consistancy));
-						DEBFILE(va("Restoring player %d (synch failure) [%update] %d!=%d\n",
-							netconsole, realstart, consistancy[realstart%BACKUPTICS],
-							SHORT(netbuffer->u.clientpak.consistancy)));
-						break;
-					}
-					else
-					{
-						XBOXSTATIC UINT8 buf[3];
-
-						buf[0] = (UINT8)netconsole;
-						buf[1] = KICK_MSG_CON_FAIL;
-						SendNetXCmd(XD_KICK, &buf, 2);
-						DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n",
-							netconsole, realstart, consistancy[realstart%BACKUPTICS],
-							SHORT(netbuffer->u.clientpak.consistancy)));
-						break;
-					}
+					buf[0] = (UINT8)netconsole;
+					buf[1] = KICK_MSG_CON_FAIL;
+					SendNetXCmd(XD_KICK, &buf, 2);
+					DEBFILE(va("player %d kicked (synch failure) [%u] %d!=%d\n",
+						netconsole, realstart, consistancy[realstart%BACKUPTICS],
+						SHORT(netbuffer->u.clientpak.consistancy)));
+					break;
 				}
-				else if (resynch_score[node])
-					--resynch_score[node];
+			}
+			else if (resynch_score[node])
+				--resynch_score[node];
+			break;
+		case PT_TEXTCMD2: // splitscreen special
+			netconsole = nodetoplayer2[node];
+		case PT_TEXTCMD:
+			if (!server)
 				break;
-			case PT_TEXTCMD2: // splitscreen special
-				netconsole = nodetoplayer2[node];
-			case PT_TEXTCMD:
-				if (!server)
-					break;
 
-				if (netconsole < 0 || netconsole >= MAXPLAYERS)
-					Net_UnAcknowledgPacket(node);
-				else
+			if (netconsole < 0 || netconsole >= MAXPLAYERS)
+				Net_UnAcknowledgePacket(node);
+			else
+			{
+				size_t j;
+				tic_t tic = maketic;
+				UINT8 *textcmd;
+
+				// check if tic that we are making isn't too large else we cannot send it :(
+				// doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time
+				j = software_MAXPACKETLENGTH
+					- (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE
+					+ (doomcom->numslots+1)*sizeof(ticcmd_t));
+
+				// search a tic that have enougth space in the ticcmd
+				while ((textcmd = D_GetExistingTextcmd(tic, netconsole)),
+					(TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD)
+					&& tic < firstticstosend + BACKUPTICS)
+					tic++;
+
+				if (tic >= firstticstosend + BACKUPTICS)
 				{
-					size_t j;
-					tic_t tic = maketic;
-					UINT8 *textcmd;
-
-					// check if tic that we are making isn't too large else we cannot send it :(
-					// doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time
-					j = software_MAXPACKETLENGTH
-						- (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE
-						+ (doomcom->numslots+1)*sizeof(ticcmd_t));
-
-					// search a tic that have enougth space in the ticcmd
-					while ((textcmd = D_GetExistingTextcmd(tic, netconsole)),
-						(TotalTextCmdPerTic(tic) > j || netbuffer->u.textcmd[0] + (textcmd ? textcmd[0] : 0) > MAXTEXTCMD)
-						&& tic < firstticstosend + BACKUPTICS)
-						tic++;
-
-					if (tic >= firstticstosend + BACKUPTICS)
-					{
-						DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, "
-							"tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)),
-							maketic, firstticstosend, node, netconsole));
-						Net_UnAcknowledgPacket(node);
-						break;
-					}
+					DEBFILE(va("GetPacket: Textcmd too long (max %s, used %s, mak %d, "
+						"tosend %u, node %u, player %d)\n", sizeu1(j), sizeu2(TotalTextCmdPerTic(maketic)),
+						maketic, firstticstosend, node, netconsole));
+					Net_UnAcknowledgePacket(node);
+					break;
+				}
 
-					// Make sure we have a buffer
-					if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole);
+				// Make sure we have a buffer
+				if (!textcmd) textcmd = D_GetTextcmd(tic, netconsole);
 
-					DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n",
-						tic, textcmd[0]+1, netconsole, firstticstosend, maketic));
+				DEBFILE(va("textcmd put in tic %u at position %d (player %d) ftts %u mk %u\n",
+					tic, textcmd[0]+1, netconsole, firstticstosend, maketic));
 
-					M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]);
-					textcmd[0] += (UINT8)netbuffer->u.textcmd[0];
-				}
+				M_Memcpy(&textcmd[textcmd[0]+1], netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]);
+				textcmd[0] += (UINT8)netbuffer->u.textcmd[0];
+			}
+			break;
+		case PT_NODETIMEOUT:
+		case PT_CLIENTQUIT:
+			if (!server)
 				break;
-			case PT_NODETIMEOUT:
-			case PT_CLIENTQUIT:
-				if (!server)
-					break;
 
-				// nodeingame will be put false in the execution of kick command
-				// this allow to send some packets to the quitting client to have their ack back
-				nodewaiting[node] = 0;
-				if (netconsole != -1 && playeringame[netconsole])
+			// nodeingame will be put false in the execution of kick command
+			// this allow to send some packets to the quitting client to have their ack back
+			nodewaiting[node] = 0;
+			if (netconsole != -1 && playeringame[netconsole])
+			{
+				XBOXSTATIC UINT8 buf[2];
+				buf[0] = (UINT8)netconsole;
+				if (netbuffer->packettype == PT_NODETIMEOUT)
+					buf[1] = KICK_MSG_TIMEOUT;
+				else
+					buf[1] = KICK_MSG_PLAYER_QUIT;
+				SendNetXCmd(XD_KICK, &buf, 2);
+				nodetoplayer[node] = -1;
+				if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0
+					&& playeringame[(UINT8)nodetoplayer2[node]])
 				{
-					XBOXSTATIC UINT8 buf[2];
-					buf[0] = (UINT8)netconsole;
-					if (netbuffer->packettype == PT_NODETIMEOUT)
-						buf[1] = KICK_MSG_TIMEOUT;
-					else
-						buf[1] = KICK_MSG_PLAYER_QUIT;
+					buf[0] = nodetoplayer2[node];
 					SendNetXCmd(XD_KICK, &buf, 2);
-					nodetoplayer[node] = -1;
-					if (nodetoplayer2[node] != -1 && nodetoplayer2[node] >= 0
-						&& playeringame[(UINT8)nodetoplayer2[node]])
-					{
-						buf[0] = nodetoplayer2[node];
-						SendNetXCmd(XD_KICK, &buf, 2);
-						nodetoplayer2[node] = -1;
-					}
+					nodetoplayer2[node] = -1;
 				}
-				Net_CloseConnection(node);
-				nodeingame[node] = false;
-				break;
+			}
+			Net_CloseConnection(node);
+			nodeingame[node] = false;
+			break;
 // -------------------------------------------- CLIENT RECEIVE ----------
-			case PT_RESYNCHEND:
-				// Only accept PT_RESYNCHEND from the server.
-				if (node != servernode)
+		case PT_RESYNCHEND:
+			// Only accept PT_RESYNCHEND from the server.
+			if (node != servernode)
+			{
+				CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHEND", node);
+
+				if (server)
 				{
-					CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHEND", node);
+					XBOXSTATIC UINT8 buf[2];
+					buf[0] = (UINT8)node;
+					buf[1] = KICK_MSG_CON_FAIL;
+					SendNetXCmd(XD_KICK, &buf, 2);
+				}
 
-					if (server)
-					{
-						XBOXSTATIC UINT8 buf[2];
-						buf[0] = (UINT8)node;
-						buf[1] = KICK_MSG_CON_FAIL;
-						SendNetXCmd(XD_KICK, &buf, 2);
-					}
+				break;
+			}
+			resynch_local_inprogress = false;
 
-					break;
-				}
-				resynch_local_inprogress = false;
+			P_SetRandSeed(netbuffer->u.resynchend.randomseed);
 
-				P_SetRandSeed(netbuffer->u.resynchend.randomseed);
+			if (gametype == GT_CTF)
+				resynch_read_ctf(&netbuffer->u.resynchend);
+			resynch_read_others(&netbuffer->u.resynchend);
 
-				if (gametype == GT_CTF)
-					resynch_read_ctf(&netbuffer->u.resynchend);
-				resynch_read_others(&netbuffer->u.resynchend);
+			break;
+		case PT_SERVERTICS:
+			// Only accept PT_SERVERTICS from the server.
+			if (node != servernode)
+			{
+				CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_SERVERTICS", node);
 
-				break;
-			case PT_SERVERTICS:
-				// Only accept PT_SERVERTICS from the server.
-				if (node != servernode)
+				if (server)
 				{
-					CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_SERVERTICS", node);
+					XBOXSTATIC UINT8 buf[2];
+					buf[0] = (UINT8)node;
+					buf[1] = KICK_MSG_CON_FAIL;
+					SendNetXCmd(XD_KICK, &buf, 2);
+				}
 
-					if (server)
-					{
-						XBOXSTATIC UINT8 buf[2];
-						buf[0] = (UINT8)node;
-						buf[1] = KICK_MSG_CON_FAIL;
-						SendNetXCmd(XD_KICK, &buf, 2);
-					}
+				break;
+			}
 
-					break;
-				}
+			realstart = ExpandTics(netbuffer->u.serverpak.starttic);
+			realend = realstart + netbuffer->u.serverpak.numtics;
 
-				realstart = ExpandTics(netbuffer->u.serverpak.starttic);
-				realend = realstart + netbuffer->u.serverpak.numtics;
+			if (!txtpak)
+				txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots
+					* netbuffer->u.serverpak.numtics];
 
-				if (!txtpak)
-					txtpak = (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots
-						* netbuffer->u.serverpak.numtics];
+			if (realend > gametic + BACKUPTICS)
+				realend = gametic + BACKUPTICS;
+			cl_packetmissed = realstart > neededtic;
 
-				if (realend > gametic + BACKUPTICS)
-					realend = gametic + BACKUPTICS;
-				cl_packetmissed = realstart > neededtic;
+			if (realstart <= neededtic && realend > neededtic)
+			{
+				tic_t i, j;
+				pak = (UINT8 *)&netbuffer->u.serverpak.cmds;
 
-				if (realstart <= neededtic && realend > neededtic)
+				for (i = realstart; i < realend; i++)
 				{
-					tic_t i, j;
-					pak = (UINT8 *)&netbuffer->u.serverpak.cmds;
-
-					for (i = realstart; i < realend; i++)
-					{
-						// clear first
-						D_Clearticcmd(i);
+					// clear first
+					D_Clearticcmd(i);
 
-						// copy the tics
-						pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak,
-							netbuffer->u.serverpak.numslots*sizeof (ticcmd_t));
+					// copy the tics
+					pak = G_ScpyTiccmd(netcmds[i%BACKUPTICS], pak,
+						netbuffer->u.serverpak.numslots*sizeof (ticcmd_t));
 
-						// copy the textcmds
-						numtxtpak = *txtpak++;
-						for (j = 0; j < numtxtpak; j++)
-						{
-							INT32 k = *txtpak++; // playernum
-							const size_t txtsize = txtpak[0]+1;
+					// copy the textcmds
+					numtxtpak = *txtpak++;
+					for (j = 0; j < numtxtpak; j++)
+					{
+						INT32 k = *txtpak++; // playernum
+						const size_t txtsize = txtpak[0]+1;
 
-							M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize);
-							txtpak += txtsize;
-						}
+						M_Memcpy(D_GetTextcmd(i, k), txtpak, txtsize);
+						txtpak += txtsize;
 					}
-
-					neededtic = realend;
 				}
-				else
-					DEBFILE(va("frame not in bound: %u\n", neededtic));
-				break;
-			case PT_RESYNCHING:
-				// Only accept PT_RESYNCHING from the server.
-				if (node != servernode)
-				{
-					CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHING", node);
 
-					if (server)
-					{
-						XBOXSTATIC char buf[2];
-						buf[0] = (char)node;
-						buf[1] = KICK_MSG_CON_FAIL;
-						SendNetXCmd(XD_KICK, &buf, 2);
-					}
+				neededtic = realend;
+			}
+			else
+				DEBFILE(va("frame not in bound: %u\n", neededtic));
+			break;
+		case PT_RESYNCHING:
+			// Only accept PT_RESYNCHING from the server.
+			if (node != servernode)
+			{
+				CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_RESYNCHING", node);
 
-					break;
+				if (server)
+				{
+					XBOXSTATIC char buf[2];
+					buf[0] = (char)node;
+					buf[1] = KICK_MSG_CON_FAIL;
+					SendNetXCmd(XD_KICK, &buf, 2);
 				}
-				resynch_local_inprogress = true;
-				CL_AcknowledgeResynch(&netbuffer->u.resynchpak);
+
 				break;
+			}
+			resynch_local_inprogress = true;
+			CL_AcknowledgeResynch(&netbuffer->u.resynchpak);
+			break;
 #ifdef NEWPING
-			case PT_PING:
-				// Only accept PT_PING from the server.
-				if (node != servernode)
-				{
-					CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_PING", node);
-
-					if (server)
-					{
-						XBOXSTATIC char buf[2];
-						buf[0] = (char)node;
-						buf[1] = KICK_MSG_CON_FAIL;
-						SendNetXCmd(XD_KICK, &buf, 2);
-					}
-
-					break;
-				}
+		case PT_PING:
+			// Only accept PT_PING from the server.
+			if (node != servernode)
+			{
+				CONS_Alert(CONS_WARNING, M_GetText("%s recieved from non-host %d\n"), "PT_PING", node);
 
-				//Update client ping table from the server.
-				if (!server)
+				if (server)
 				{
-					INT32 i;
-					for (i = 0; i < MAXNETNODES; i++)
-						if (playeringame[i])
-							playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i];
+					XBOXSTATIC char buf[2];
+					buf[0] = (char)node;
+					buf[1] = KICK_MSG_CON_FAIL;
+					SendNetXCmd(XD_KICK, &buf, 2);
 				}
 
 				break;
+			}
+
+			//Update client ping table from the server.
+			if (!server)
+			{
+				INT32 i;
+				for (i = 0; i < MAXNETNODES; i++)
+					if (playeringame[i])
+						playerpingtable[i] = (tic_t)netbuffer->u.pingtable[i];
+			}
+
+			break;
 #endif
-			case PT_SERVERCFG:
-				break;
-			case PT_FILEFRAGMENT:
-				if (!server)
-					Got_Filetxpak();
-				break;
-			default:
-				DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n",
-					netbuffer->packettype, node));
-		} // end switch
-	} // end while
+		case PT_SERVERCFG:
+			break;
+		case PT_FILEFRAGMENT:
+			if (!server)
+				Got_Filetxpak();
+			break;
+		default:
+			DEBFILE(va("UNKNOWN PACKET TYPE RECEIVED %d from host %d\n",
+				netbuffer->packettype, node));
+	} // end switch
+}
+
+/**	Handles all received packets, if any
+  *
+  * \todo Add details to this description (lol)
+  *
+  */
+static void GetPackets(void)
+{FILESTAMP
+	XBOXSTATIC SINT8 node; // The packet sender
+FILESTAMP
+
+	player_joining = false;
+
+	while (HGetPacket())
+	{
+		node = (SINT8)doomcom->remotenode;
+
+		if (netbuffer->packettype == PT_CLIENTJOIN && server)
+		{
+			HandleConnect(node);
+			continue;
+		}
+		if (netbuffer->packettype == PT_SERVERSHUTDOWN && node == servernode
+			&& !server && cl_mode != CL_SEARCHING)
+		{
+			HandleShutdown(node);
+			continue;
+		}
+		if (netbuffer->packettype == PT_NODETIMEOUT && node == servernode
+			&& !server && cl_mode != CL_SEARCHING)
+		{
+			HandleTimeout(node);
+			continue;
+		}
+
+#ifndef NONET
+		if (netbuffer->packettype == PT_SERVERINFO)
+		{
+			HandleServerInfo(node);
+			continue;
+		}
+#endif
+
+		if (netbuffer->packettype == PT_PLAYERINFO)
+			continue; // We do nothing with PLAYERINFO, that's for the MS browser.
+
+		// Packet received from someone already playing
+		if (nodeingame[node])
+			HandlePacketFromPlayer(node);
+		// Packet received from someone trying to join
+		else
+			HandlePacketFromAwayNode(node);
+	}
 }
 
 //
@@ -3775,6 +3929,10 @@ static INT16 Consistancy(void)
 {
 	INT32 i;
 	UINT32 ret = 0;
+#ifdef MOBJCONSISTANCY
+	thinker_t *th;
+	mobj_t *mo;
+#endif
 
 	DEBFILE(va("TIC %u ", gametic));
 
@@ -3796,6 +3954,77 @@ static INT16 Consistancy(void)
 	if (!G_PlatformGametype())
 		ret += P_GetRandSeed();
 
+#ifdef MOBJCONSISTANCY
+	if (!thinkercap.next)
+		return ret;
+	for (th = thinkercap.next; th != &thinkercap; th = th->next)
+	{
+		if (th->function.acp1 != (actionf_p1)P_MobjThinker)
+			continue;
+
+		mo = (mobj_t *)th;
+
+		if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY))
+		{
+			ret -= mo->type;
+			ret += mo->x;
+			ret -= mo->y;
+			ret += mo->z;
+			ret -= mo->momx;
+			ret += mo->momy;
+			ret -= mo->momz;
+			ret += mo->angle;
+			ret -= mo->flags;
+			ret += mo->flags2;
+			ret -= mo->eflags;
+			if (mo->target)
+			{
+				ret += mo->target->type;
+				ret -= mo->target->x;
+				ret += mo->target->y;
+				ret -= mo->target->z;
+				ret += mo->target->momx;
+				ret -= mo->target->momy;
+				ret += mo->target->momz;
+				ret -= mo->target->angle;
+				ret += mo->target->flags;
+				ret -= mo->target->flags2;
+				ret += mo->target->eflags;
+				ret -= mo->target->state - states;
+				ret += mo->target->tics;
+				ret -= mo->target->sprite;
+				ret += mo->target->frame;
+			}
+			else
+				ret ^= 0x3333;
+			if (mo->tracer && mo->tracer->type != MT_OVERLAY)
+			{
+				ret += mo->tracer->type;
+				ret -= mo->tracer->x;
+				ret += mo->tracer->y;
+				ret -= mo->tracer->z;
+				ret += mo->tracer->momx;
+				ret -= mo->tracer->momy;
+				ret += mo->tracer->momz;
+				ret -= mo->tracer->angle;
+				ret += mo->tracer->flags;
+				ret -= mo->tracer->flags2;
+				ret += mo->tracer->eflags;
+				ret -= mo->tracer->state - states;
+				ret += mo->tracer->tics;
+				ret -= mo->tracer->sprite;
+				ret += mo->tracer->frame;
+			}
+			else
+				ret ^= 0xAAAA;
+			ret -= mo->state - states;
+			ret += mo->tics;
+			ret -= mo->sprite;
+			ret += mo->frame;
+		}
+	}
+#endif
+
 	return (INT16)(ret & 0xFFFF);
 }
 
@@ -3836,7 +4065,7 @@ static void CL_SendClientCmd(void)
 		HSendPacket(servernode, false, 0, packetsize);
 	}
 
-	if (cl_mode == cl_connected || dedicated)
+	if (cl_mode == CL_CONNECTED || dedicated)
 	{
 		// send extra data if needed
 		if (localtextcmd[0])
@@ -4219,12 +4448,12 @@ FILESTAMP
 	// client send the command after a receive of the server
 	// the server send before because in single player is beter
 
-	MasterClient_Ticker(); // acking the master server
+	MasterClient_Ticker(); // Acking the Master Server
 
 	if (!server)
 	{
 		if (!resynch_local_inprogress)
-			CL_SendClientCmd(); // send tic cmd
+			CL_SendClientCmd(); // Send tic cmd
 		hu_resynching = resynch_local_inprogress;
 	}
 	else
@@ -4250,21 +4479,21 @@ FILESTAMP
 					counts = -666;
 				}
 
-			// do not make tics while resynching
+			// Do not make tics while resynching
 			if (counts != -666)
 			{
 				if (maketic + counts >= firstticstosend + BACKUPTICS)
 					counts = firstticstosend+BACKUPTICS-maketic-1;
 
 				for (i = 0; i < counts; i++)
-					SV_Maketic(); // create missed tics and increment maketic
+					SV_Maketic(); // Create missed tics and increment maketic
 
-				for (; tictoclear < firstticstosend; tictoclear++) // clear only when acknoledged
-					D_Clearticcmd(tictoclear);                    // clear the maketic the new tic
+				for (; tictoclear < firstticstosend; tictoclear++) // Clear only when acknowledged
+					D_Clearticcmd(tictoclear);                    // Clear the maketic the new tic
 
 				SV_SendTics();
 
-				neededtic = maketic; // the server is a client too
+				neededtic = maketic; // The server is a client too
 			}
 			else
 				hu_resynching = true;
@@ -4278,7 +4507,7 @@ FILESTAMP
 		M_Ticker();
 		CON_Ticker();
 	}
-	FiletxTicker();
+	SV_FileSendTicker();
 }
 
 /** Returns the number of players playing.
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index 21ef3a46b204eeb5863f9a06176fd3c09a67e8cd..c5c53c585dbe5f0aa773e7bf1ba977f58e5cb703 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -59,7 +59,7 @@ typedef enum
 	// Add non-PT_CANFAIL packet types here to avoid breaking MS compatibility.
 
 	PT_CANFAIL,       // This is kind of a priority. Anything bigger than CANFAIL
-	                  // allows HSendPacket(,true,,) to return false.
+	                  // allows HSendPacket(*, true, *, *) to return false.
 	                  // In addition, this packet can't occupy all the available slots.
 
 	PT_FILEFRAGMENT = PT_CANFAIL, // A part of a file.
@@ -76,11 +76,16 @@ typedef enum
 	NUMPACKETTYPE
 } packettype_t;
 
+#ifdef PACKETDROP
+void Command_Drop(void);
+void Command_Droprate(void);
+#endif
+
 #if defined(_MSC_VER)
 #pragma pack(1)
 #endif
 
-// client to server packet
+// Client to server packet
 typedef struct
 {
 	UINT8 client_tic;
@@ -89,7 +94,7 @@ typedef struct
 	ticcmd_t cmd;
 } ATTRPACK clientcmd_pak;
 
-// splitscreen packet
+// Splitscreen packet
 // WARNING: must have the same format of clientcmd_pak, for more easy use
 typedef struct
 {
@@ -110,16 +115,16 @@ typedef struct
 	UINT8 starttic;
 	UINT8 numtics;
 	UINT8 numslots; // "Slots filled": Highest player number in use plus one.
-	ticcmd_t cmds[45]; // normally [BACKUPTIC][MAXPLAYERS] but too large
+	ticcmd_t cmds[45]; // Normally [BACKUPTIC][MAXPLAYERS] but too large
 } ATTRPACK servertics_pak;
 
-// sent to client when all consistency data
+// Sent to client when all consistency data
 // for players has been restored
 typedef struct
 {
 	UINT32 randomseed;
 
-	//ctf flag stuff
+	// CTF flag stuff
 	SINT8 flagplayer[2];
 	INT32 flagloose[2];
 	INT32 flagflags[2];
@@ -127,11 +132,11 @@ typedef struct
 	fixed_t flagy[2];
 	fixed_t flagz[2];
 
-	UINT32 ingame;  // spectator bit for each player
-	UINT32 ctfteam; // if not spectator, then which team?
+	UINT32 ingame;  // Spectator bit for each player
+	INT32 ctfteam[MAXPLAYERS]; // Which team? (can't be 1 bit, since in regular Match there are no teams)
 
 	// Resynch game scores and the like all at once
-	UINT32 score[MAXPLAYERS]; // Everyone's score.
+	UINT32 score[MAXPLAYERS]; // Everyone's score
 	INT16 numboxes[MAXPLAYERS];
 	INT16 totalring[MAXPLAYERS];
 	tic_t realtime[MAXPLAYERS];
@@ -140,14 +145,14 @@ typedef struct
 
 typedef struct
 {
-	//player stuff
+	// Player stuff
 	UINT8 playernum;
 
 	// Do not send anything visual related.
 	// Only send data that we need to know for physics.
-	UINT8 playerstate; //playerstate_t
-	UINT32 pflags; //pflags_t
-	UINT8 panim; //panim_t
+	UINT8 playerstate; // playerstate_t
+	UINT32 pflags; // pflags_t
+	UINT8 panim; // panim_t
 
 	angle_t aiming;
 	INT32 currentweapon;
@@ -176,9 +181,9 @@ typedef struct
 	UINT8 charability;
 	UINT8 charability2;
 	UINT32 charflags;
-	UINT32 thokitem; //mobjtype_t
-	UINT32 spinitem; //mobjtype_t
-	UINT32 revitem; //mobjtype_t
+	UINT32 thokitem; // mobjtype_t
+	UINT32 spinitem; // mobjtype_t
+	UINT32 revitem; // mobjtype_t
 	fixed_t actionspd;
 	fixed_t mindash;
 	fixed_t maxdash;
@@ -234,7 +239,7 @@ typedef struct
 	INT32 onconveyor;
 
 	//player->mo stuff
-	UINT8 hasmo; //boolean
+	UINT8 hasmo; // Boolean
 
 	INT32 health;
 	angle_t angle;
@@ -262,10 +267,10 @@ typedef struct
 
 typedef struct
 {
-	UINT8 version; // different versions don't work
-	UINT8 subversion; // contains build version
+	UINT8 version; // Different versions don't work
+	UINT8 subversion; // Contains build version
 
-	// server launch stuffs
+	// Server launch stuffs
 	UINT8 serverplayer;
 	UINT8 totalslotnum; // "Slots": highest player number in use plus one.
 
@@ -279,18 +284,18 @@ typedef struct
 
 	UINT8 gametype;
 	UINT8 modifiedgame;
-	SINT8 adminplayer; // needs to be signed
+	SINT8 adminplayer; // Needs to be signed
 
-	char server_context[8]; // unique context id, generated at server startup.
+	char server_context[8]; // Unique context id, generated at server startup.
 
-	UINT8 varlengthinputs[0]; // playernames and netvars
+	UINT8 varlengthinputs[0]; // Playernames and netvars
 } ATTRPACK serverconfig_pak;
 
 typedef struct {
 	UINT8 fileid;
 	UINT32 position;
 	UINT16 size;
-	UINT8 data[0]; // size is variable using hardware_MAXPACKETLENGTH
+	UINT8 data[0]; // Size is variable using hardware_MAXPACKETLENGTH
 } ATTRPACK filetx_pak;
 
 #ifdef _MSC_VER
@@ -299,14 +304,14 @@ typedef struct {
 
 typedef struct
 {
-	UINT8 version; // different versions don't work
-	UINT8 subversion; // contains build version
+	UINT8 version; // Different versions don't work
+	UINT8 subversion; // Contains build version
 	UINT8 localplayers;
 	UINT8 mode;
 } ATTRPACK clientconfig_pak;
 
 #define MAXSERVERNAME 32
-// this packet is too large
+// This packet is too large
 typedef struct
 {
 	UINT8 version;
@@ -372,45 +377,45 @@ typedef struct
 } ATTRPACK plrconfig;
 
 //
-// Network packet data.
+// Network packet data
 //
 typedef struct
 {
 	UINT32 checksum;
-	UINT8 ack; // if not null the node asks for acknowledgement, the receiver must resend the ack
-	UINT8 ackreturn; // the return of the ack number
+	UINT8 ack; // If not zero the node asks for acknowledgement, the receiver must resend the ack
+	UINT8 ackreturn; // The return of the ack number
 
 	UINT8 packettype;
-	UINT8 reserved; // padding
+	UINT8 reserved; // Padding
 	union
 	{
-		clientcmd_pak clientpak;    //      144 bytes
-		client2cmd_pak client2pak;  //      200 bytes
-		servertics_pak serverpak;   //   132495 bytes
-		serverconfig_pak servercfg; //      773 bytes
-		resynchend_pak resynchend;  //
-		resynch_pak resynchpak;     //
-		UINT8 resynchgot;           //
-		UINT8 textcmd[MAXTEXTCMD+1]; //   66049 bytes
-		filetx_pak filetxpak;       //      139 bytes
-		clientconfig_pak clientcfg; //      136 bytes
-		serverinfo_pak serverinfo;  //     1024 bytes
-		serverrefuse_pak serverrefuse; // 65025 bytes
-		askinfo_pak askinfo;        //       61 bytes
-		msaskinfo_pak msaskinfo;    //       22 bytes
-		plrinfo playerinfo[MAXPLAYERS]; // 1152 bytes
-		plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes
+		clientcmd_pak clientpak;            //         144 bytes
+		client2cmd_pak client2pak;          //         200 bytes
+		servertics_pak serverpak;           //      132495 bytes (more around 360, no?)
+		serverconfig_pak servercfg;         //         773 bytes
+		resynchend_pak resynchend;          //
+		resynch_pak resynchpak;             //
+		UINT8 resynchgot;                   //
+		UINT8 textcmd[MAXTEXTCMD+1];        //       66049 bytes (wut??? 64k??? More like 257 bytes...)
+		filetx_pak filetxpak;               //         139 bytes
+		clientconfig_pak clientcfg;         //         136 bytes
+		serverinfo_pak serverinfo;          //        1024 bytes
+		serverrefuse_pak serverrefuse;      //       65025 bytes (somehow I feel like those values are garbage...)
+		askinfo_pak askinfo;                //          61 bytes
+		msaskinfo_pak msaskinfo;            //          22 bytes
+		plrinfo playerinfo[MAXPLAYERS];     //        1152 bytes (I'd say 36~38)
+		plrconfig playerconfig[MAXPLAYERS]; // (up to) 896 bytes (welp they ARE)
 #ifdef NEWPING
-		UINT32 pingtable[MAXPLAYERS]; //    128 bytes
+		UINT32 pingtable[MAXPLAYERS];       //         128 bytes
 #endif
-	} u; // this is needed to pack diff packet types data together
+	} u; // This is needed to pack diff packet types data together
 } ATTRPACK doomdata_t;
 
 #if defined(_MSC_VER)
 #pragma pack()
 #endif
 
-#define MAXSERVERLIST 64 // depends only on the display
+#define MAXSERVERLIST 64 // Depends only on the display
 typedef struct
 {
 	SINT8 node;
@@ -421,7 +426,7 @@ extern serverelem_t serverlist[MAXSERVERLIST];
 extern UINT32 serverlistcount;
 extern INT32 mapchangepending;
 
-// points inside doomcom
+// Points inside doomcom
 extern doomdata_t *netbuffer;
 
 extern consvar_t cv_playbackspeed;
@@ -442,7 +447,7 @@ extern consvar_t cv_playbackspeed;
 #define KICK_MSG_CUSTOM_BAN  8
 
 extern boolean server;
-extern boolean dedicated; // for dedicated server
+extern boolean dedicated; // For dedicated server
 extern UINT16 software_MAXPACKETLENGTH;
 extern boolean acceptnewnode;
 extern SINT8 servernode;
@@ -457,11 +462,11 @@ extern UINT32 playerpingtable[MAXPLAYERS];
 
 extern consvar_t cv_joinnextround, cv_allownewplayer, cv_maxplayers, cv_resynchattempts, cv_blamecfail, cv_maxsend;
 
-// used in d_net, the only dependence
+// Used in d_net, the only dependence
 tic_t ExpandTics(INT32 low);
 void D_ClientServerInit(void);
 
-// initialise the other field
+// Initialise the other field
 void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum));
 void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam);
 void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam); // splitsreen player
@@ -479,14 +484,14 @@ void CL_RemoveSplitscreenPlayer(void);
 void CL_Reset(void);
 void CL_ClearPlayer(INT32 playernum);
 void CL_UpdateServerList(boolean internetsearch, INT32 room);
-// is there a game running
+// Is there a game running
 boolean Playing(void);
 
 // Broadcasts special packets to other players
 //  to notify of game exit
 void D_QuitNetGame(void);
 
-//? how many ticks to run?
+//? How many ticks to run?
 void TryRunTics(tic_t realtic);
 
 // extra data for lmps
diff --git a/src/d_net.c b/src/d_net.c
index 03e126b50156db43db88cb42fd5e7ce82f1875bd..6be1dbe5cd0fe506615828e5a377cfabc6888ca3 100644
--- a/src/d_net.c
+++ b/src/d_net.c
@@ -31,15 +31,15 @@
 //
 // NETWORKING
 //
-// gametic is the tic about to be (or currently being) run
-// server:
+// gametic is the tic about to (or currently being) run
+// Server:
 //   maketic is the tic that hasn't had control made for it yet
-//   nettics: is the tic for each node
-//   firsttictosend: is the lowest value of nettics
-// client:
-//   neededtic: is the tic needed by the client to run the game
-//   firsttictosend: is used to optimize a condition
-// normally maketic >= gametic > 0
+//   nettics is the tic for each node
+//   firstticstosend is the lowest value of nettics
+// Client:
+//   neededtic is the tic needed by the client to run the game
+//   firstticstosend is used to optimize a condition
+// Normally maketic >= gametic > 0
 
 #define FORCECLOSE 0x8000
 tic_t connectiontimeout = (15*TICRATE);
@@ -129,9 +129,9 @@ boolean Net_GetNetStat(void)
 // -----------------------------------------------------------------
 // Some structs and functions for acknowledgement of packets
 // -----------------------------------------------------------------
-#define MAXACKPACKETS 96 // minimum number of nodes
+#define MAXACKPACKETS 96 // Minimum number of nodes (wat)
 #define MAXACKTOSEND 96
-#define URGENTFREESLOTENUM 10
+#define URGENTFREESLOTNUM 10
 #define ACKTOSENDTIMEOUT (TICRATE/11)
 
 #ifndef NONET
@@ -139,10 +139,10 @@ typedef struct
 {
 	UINT8 acknum;
 	UINT8 nextacknum;
-	UINT8 destinationnode;
-	tic_t senttime;
-	UINT16 length;
-	UINT16 resentnum;
+	UINT8 destinationnode; // The node to send the ack to
+	tic_t senttime; // The time when the ack was sent
+	UINT16 length; // The packet size
+	UINT16 resentnum; // The number of
 	union {
 		SINT8 raw[MAXPACKETLENGTH];
 		doomdata_t data;
@@ -212,11 +212,16 @@ FUNCMATH static INT32 cmpack(UINT8 a, UINT8 b)
 	return d;
 }
 
-// return a free acknum and copy netbuffer in the ackpak table
+/** Sets freeack to a free acknum and copies the netbuffer in the ackpak table
+  *
+  * \param freeack  The address to store the free acknum at
+  * \param lowtimer ???
+  * \return True if a free acknum was found
+  */
 static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 {
 	node_t *node = &nodes[doomcom->remotenode];
-	INT32 i, numfreeslote = 0;
+	INT32 i, numfreeslot = 0;
 
 	if (cmpack((UINT8)((node->remotefirstack + MAXACKTOSEND) % 256), node->nextacknum) < 0)
 	{
@@ -227,10 +232,13 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 	for (i = 0; i < MAXACKPACKETS; i++)
 		if (!ackpak[i].acknum)
 		{
-			// for low priority packet, make sure let freeslotes so urgents packets can be sent
-			numfreeslote++;
-			if (netbuffer->packettype >= PT_CANFAIL && numfreeslote < URGENTFREESLOTENUM)
-				continue;
+			// For low priority packets, make sure to let freeslots so urgent packets can be sent
+			if (netbuffer->packettype >= PT_CANFAIL)
+			{
+				numfreeslot++;
+				if (numfreeslot <= URGENTFREESLOTNUM)
+					continue;
+			}
 
 			ackpak[i].acknum = node->nextacknum;
 			ackpak[i].nextacknum = node->nextacknum;
@@ -241,7 +249,7 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 			ackpak[i].length = doomcom->datalength;
 			if (lowtimer)
 			{
-				// lowtime mean can't be sent now so try it soon as possible
+				// Lowtime means can't be sent now so try it as soon as possible
 				ackpak[i].senttime = 0;
 				ackpak[i].resentnum = 1;
 			}
@@ -254,7 +262,7 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 
 			*freeack = ackpak[i].acknum;
 
-			sendackpacket++; // for stat
+			sendackpacket++; // For stat
 
 			return true;
 		}
@@ -266,14 +274,14 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
 	return false;
 }
 
-// Get a ack to send in the queu of this node
+// Get a ack to send in the queue of this node
 static UINT8 GetAcktosend(INT32 node)
 {
 	nodes[node].lasttimeacktosend_sent = I_GetTime();
 	return nodes[node].firstacktosend;
 }
 
-static void Removeack(INT32 i)
+static void RemoveAck(INT32 i)
 {
 	INT32 node = ackpak[i].destinationnode;
 #ifndef NEWPING
@@ -294,27 +302,27 @@ static void Removeack(INT32 i)
 		Net_CloseConnection(node);
 }
 
-// we have got a packet proceed the ack request and ack return
+// We have got a packet, proceed the ack request and ack return
 static boolean Processackpak(void)
 {
 	INT32 i;
 	boolean goodpacket = true;
 	node_t *node = &nodes[doomcom->remotenode];
 
-	// received an ack return, so remove the ack in the list
+	// Received an ack return, so remove the ack in the list
 	if (netbuffer->ackreturn && cmpack(node->remotefirstack, netbuffer->ackreturn) < 0)
 	{
 		node->remotefirstack = netbuffer->ackreturn;
-		// search the ackbuffer and free it
+		// Search the ackbuffer and free it
 		for (i = 0; i < MAXACKPACKETS; i++)
 			if (ackpak[i].acknum && ackpak[i].destinationnode == node - nodes
 				&& cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0)
 			{
-				Removeack(i);
+				RemoveAck(i);
 			}
 	}
 
-	// received a packet with ack, queue it to send the ack back
+	// Received a packet with ack, queue it to send the ack back
 	if (netbuffer->ack)
 	{
 		UINT8 ack = netbuffer->ack;
@@ -323,23 +331,23 @@ static boolean Processackpak(void)
 		{
 			DEBFILE(va("Discard(1) ack %d (duplicated)\n", ack));
 			duppacket++;
-			goodpacket = false; // discard packet (duplicate)
+			goodpacket = false; // Discard packet (duplicate)
 		}
 		else
 		{
-			// check if it is not already in the queue
+			// Check if it is not already in the queue
 			for (i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND)
 				if (node->acktosend[i] == ack)
 				{
 					DEBFILE(va("Discard(2) ack %d (duplicated)\n", ack));
 					duppacket++;
-					goodpacket = false; // discard packet (duplicate)
+					goodpacket = false; // Discard packet (duplicate)
 					break;
 				}
 			if (goodpacket)
 			{
-				// is a good packet so increment the acknowledge number,
-				// then search for a "hole" in the queue
+				// Is a good packet so increment the acknowledge number,
+				// Then search for a "hole" in the queue
 				UINT8 nextfirstack = (UINT8)(node->firstacktosend + 1);
 				if (!nextfirstack)
 					nextfirstack = 1;
@@ -383,10 +391,10 @@ static boolean Processackpak(void)
 						}
 					}
 				}
-				else // out of order packet
+				else // Out of order packet
 				{
-					// don't increment firsacktosend, put it in asktosend queue
-					// will be incremented when the nextfirstack comes (code above)
+					// Don't increment firsacktosend, put it in asktosend queue
+					// Will be incremented when the nextfirstack comes (code above)
 					UINT8 newhead = (UINT8)((node->acktosend_head+1) % MAXACKTOSEND);
 					DEBFILE(va("out of order packet (%d expected)\n", nextfirstack));
 					if (newhead != node->acktosend_tail)
@@ -394,8 +402,8 @@ static boolean Processackpak(void)
 						node->acktosend[node->acktosend_head] = ack;
 						node->acktosend_head = newhead;
 					}
-					else // buffer full discard packet, sender will resend it
-					{ // we can admit the packet but we will not detect the duplication after :(
+					else // Buffer full discard packet, sender will resend it
+					{ // We can admit the packet but we will not detect the duplication after :(
 						DEBFILE("no more freeackret\n");
 						goodpacket = false;
 					}
@@ -430,25 +438,24 @@ static void GotAcks(void)
 				if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode)
 				{
 					if (ackpak[i].acknum == netbuffer->u.textcmd[j])
-						Removeack(i);
-					else
-						// nextacknum is first equal to acknum, then when receiving bigger ack
-						// there is big chance the packet is lost
-						// when resent, nextacknum = nodes[node].nextacknum
-						//    will redo the same but with different value
-					if (cmpack(ackpak[i].nextacknum, netbuffer->u.textcmd[j]) <= 0
-						&& ackpak[i].senttime > 0)
-					{
-						ackpak[i].senttime--; // hurry up
-					}
+						RemoveAck(i);
+					// nextacknum is first equal to acknum, then when receiving bigger ack
+					// there is big chance the packet is lost
+					// When resent, nextacknum = nodes[node].nextacknum
+					// will redo the same but with different value
+					else if (cmpack(ackpak[i].nextacknum, netbuffer->u.textcmd[j]) <= 0
+							&& ackpak[i].senttime > 0)
+						{
+							ackpak[i].senttime--; // hurry up
+						}
 				}
 }
 #endif
 
 static inline void Net_ConnectionTimeout(INT32 node)
 {
-	// send a very special packet to self (hack the reboundstore queue)
-	// main code will handle it
+	// Send a very special packet to self (hack the reboundstore queue)
+	// Main code will handle it
 	reboundstore[rebound_head].packettype = PT_NODETIMEOUT;
 	reboundstore[rebound_head].ack = 0;
 	reboundstore[rebound_head].ackreturn = 0;
@@ -456,12 +463,12 @@ static inline void Net_ConnectionTimeout(INT32 node)
 	reboundsize[rebound_head] = (INT16)(BASEPACKETSIZE + 1);
 	rebound_head = (rebound_head+1) % MAXREBOUND;
 
-	// do not redo it quickly (if we do not close connection it is
+	// Do not redo it quickly (if we do not close connection it is
 	// for a good reason!)
 	nodes[node].lasttimepacketreceived = I_GetTime();
 }
 
-// resend the data if needed
+// Resend the data if needed
 void Net_AckTicker(void)
 {
 #ifndef NONET
@@ -497,7 +504,7 @@ void Net_AckTicker(void)
 			ackpak[i].senttime = I_GetTime();
 			ackpak[i].resentnum++;
 			ackpak[i].nextacknum = node->nextacknum;
-			retransmit++; // for stat
+			retransmit++; // For stat
 			HSendPacket((INT32)(node - nodes), false, ackpak[i].acknum,
 				(size_t)(ackpak[i].length - BASEPACKETSIZE));
 		}
@@ -505,11 +512,11 @@ void Net_AckTicker(void)
 
 	for (i = 1; i < MAXNETNODES; i++)
 	{
-		// this is something like node open flag
+		// This is something like node open flag
 		if (nodes[i].firstacktosend)
 		{
-			// we haven't sent a packet for a long time
-			// acknowledge packet if needed
+			// We haven't sent a packet for a long time
+			// Acknowledge packet if needed
 			if (nodes[i].lasttimeacktosend_sent + ACKTOSENDTIMEOUT < I_GetTime())
 				Net_SendAcks(i);
 
@@ -523,9 +530,9 @@ void Net_AckTicker(void)
 #endif
 }
 
-// remove last packet received ack before resending the ackret
+// Remove last packet received ack before resending the ackreturn
 // (the higher layer doesn't have room, or something else ....)
-void Net_UnAcknowledgPacket(INT32 node)
+void Net_UnAcknowledgePacket(INT32 node)
 {
 #ifdef NONET
 	(void)node;
@@ -564,20 +571,29 @@ void Net_UnAcknowledgPacket(INT32 node)
 #endif
 }
 
-boolean Net_AllAckReceived(void)
-{
 #ifndef NONET
+/** Checks if all acks have been received
+  *
+  * \return True if all acks have been received
+  *
+  */
+static boolean Net_AllAcksReceived(void)
+{
 	INT32 i;
 
 	for (i = 0; i < MAXACKPACKETS; i++)
 		if (ackpak[i].acknum)
 			return false;
-#endif
 
 	return true;
 }
+#endif
 
-// wait for all ackreturns with timeout in seconds
+/** Waits for all ackreturns
+  *
+  * \param timeout Timeout in seconds
+  *
+  */
 void Net_WaitAllAckReceived(UINT32 timeout)
 {
 #ifdef NONET
@@ -587,7 +603,7 @@ void Net_WaitAllAckReceived(UINT32 timeout)
 	timeout = tictac + timeout*NEWTICRATE;
 
 	HGetPacket();
-	while (timeout > I_GetTime() && !Net_AllAckReceived())
+	while (timeout > I_GetTime() && !Net_AllAcksReceived())
 	{
 		while (tictac == I_GetTime())
 			I_Sleep();
@@ -598,18 +614,18 @@ void Net_WaitAllAckReceived(UINT32 timeout)
 #endif
 }
 
-static void InitNode(INT32 node)
+static void InitNode(node_t *node)
 {
-	nodes[node].acktosend_head = nodes[node].acktosend_tail = 0;
+	node->acktosend_head = node->acktosend_tail = 0;
 #ifndef NEWPING
-	nodes[node].ping = PINGDEFAULT;
-	nodes[node].varping = VARPINGDEFAULT;
-	nodes[node].timeout = TIMEOUT(nodes[node].ping,nodes[node].varping);
+	node->ping = PINGDEFAULT;
+	node->varping = VARPINGDEFAULT;
+	node->timeout = TIMEOUT(node->ping, node->varping);
 #endif
-	nodes[node].firstacktosend = 0;
-	nodes[node].nextacknum = 1;
-	nodes[node].remotefirstack = 0;
-	nodes[node].flags = 0;
+	node->firstacktosend = 0;
+	node->nextacknum = 1;
+	node->remotefirstack = 0;
+	node->flags = 0;
 }
 
 static void InitAck(void)
@@ -622,9 +638,14 @@ static void InitAck(void)
 #endif
 
 	for (i = 0; i < MAXNETNODES; i++)
-		InitNode(i);
+		InitNode(&nodes[i]);
 }
 
+/** Removes all acks of a given packet type
+  *
+  * \param packettype The packet type to forget
+  *
+  */
 void Net_AbortPacketType(UINT8 packettype)
 {
 #ifdef NONET
@@ -676,8 +697,8 @@ void Net_CloseConnection(INT32 node)
 				ackpak[i].acknum = 0;
 		}
 
-	InitNode(node);
-	AbortSendFiles(node);
+	InitNode(&nodes[node]);
+	SV_AbortSendFiles(node);
 	I_NetFreeNodenum(node);
 #endif
 }
@@ -729,9 +750,15 @@ static void fprintfstring(char *s, size_t len)
 		}
 	if (mode)
 		fprintf(debugfile, "]");
+}
+
+static void fprintfstringnewline(char *s, size_t len)
+{
+	fprintfstring(s, len);
 	fprintf(debugfile, "\n");
 }
 
+/// \warning Keep this up-to-date if you add/remove/rename packet types
 static const char *packettypename[NUMPACKETTYPE] =
 {
 	"NOTHING",
@@ -749,15 +776,22 @@ static const char *packettypename[NUMPACKETTYPE] =
 
 	"ASKINFO",
 	"SERVERINFO",
+	"PLAYERINFO",
 	"REQUESTFILE",
 	"ASKINFOVIAMS",
 
-	"PLAYERCONFIGS",
+	"RESYNCHEND",
+	"RESYNCHGET",
+
 	"FILEFRAGMENT",
 	"TEXTCMD",
 	"TEXTCMD2",
 	"CLIENTJOIN",
 	"NODETIMEOUT",
+	"RESYNCHING",
+#ifdef NEWPING
+	"PING"
+#endif
 };
 
 static void DebugPrintpacket(const char *header)
@@ -770,20 +804,29 @@ static void DebugPrintpacket(const char *header)
 	{
 		case PT_ASKINFO:
 		case PT_ASKINFOVIAMS:
-			fprintf(debugfile, "    time %u\n", (tic_t)LONG(netbuffer->u.askinfo.time)				);
+			fprintf(debugfile, "    time %u\n", (tic_t)LONG(netbuffer->u.askinfo.time));
 			break;
 		case PT_CLIENTJOIN:
 			fprintf(debugfile, "    number %d mode %d\n", netbuffer->u.clientcfg.localplayers,
 				netbuffer->u.clientcfg.mode);
 			break;
 		case PT_SERVERTICS:
+		{
+			servertics_pak *serverpak = &netbuffer->u.serverpak;
+			ticcmd_t *cmd = &serverpak->cmds[serverpak->numslots * serverpak->numtics];
+			size_t ntxtcmd = &((UINT8 *)netbuffer)[doomcom->datalength] - (UINT8 *)cmd;
+
 			fprintf(debugfile, "    firsttic %u ply %d tics %d ntxtcmd %s\n    ",
-				(UINT32)ExpandTics(netbuffer->u.serverpak.starttic), netbuffer->u.serverpak.numslots,
-				netbuffer->u.serverpak.numtics,
-				sizeu1((size_t)(&((UINT8 *)netbuffer)[doomcom->datalength] - (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics])));
-			fprintfstring((char *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics],(size_t)(
-				&((UINT8 *)netbuffer)[doomcom->datalength] - (UINT8 *)&netbuffer->u.serverpak.cmds[netbuffer->u.serverpak.numslots*netbuffer->u.serverpak.numtics]));
+				(UINT32)ExpandTics(serverpak->starttic), serverpak->numslots, serverpak->numtics, sizeu1(ntxtcmd));
+			fprintfstring((char *)cmd, 3);
+			if (ntxtcmd > 4)
+			{
+				fprintf(debugfile, "[%s]", netxcmdnames[*(((UINT8 *)cmd) + 3) - 1]);
+				fprintfstring(((char *)cmd) + 4, ntxtcmd - 4);
+			}
+			fprintf(debugfile, "\n");
 			break;
+		}
 		case PT_CLIENTCMD:
 		case PT_CLIENT2CMD:
 		case PT_CLIENTMIS:
@@ -797,7 +840,8 @@ static void DebugPrintpacket(const char *header)
 		case PT_TEXTCMD:
 		case PT_TEXTCMD2:
 			fprintf(debugfile, "    length %d\n    ", netbuffer->u.textcmd[0]);
-			fprintfstring((char *)netbuffer->u.textcmd+1, netbuffer->u.textcmd[0]);
+			fprintf(debugfile, "[%s]", netxcmdnames[netbuffer->u.textcmd[1] - 1]);
+			fprintfstringnewline((char *)netbuffer->u.textcmd + 2, netbuffer->u.textcmd[0] - 1);
 			break;
 		case PT_SERVERCFG:
 			fprintf(debugfile, "    playerslots %d clientnode %d serverplayer %d "
@@ -813,7 +857,7 @@ static void DebugPrintpacket(const char *header)
 				netbuffer->u.serverinfo.maxplayer, netbuffer->u.serverinfo.mapname,
 				netbuffer->u.serverinfo.fileneedednum,
 				(UINT32)LONG(netbuffer->u.serverinfo.time));
-			fprintfstring((char *)netbuffer->u.serverinfo.fileneeded,
+			fprintfstringnewline((char *)netbuffer->u.serverinfo.fileneeded,
 				(UINT8)((UINT8 *)netbuffer + doomcom->datalength
 				- (UINT8 *)netbuffer->u.serverinfo.fileneeded));
 			break;
@@ -827,20 +871,100 @@ static void DebugPrintpacket(const char *header)
 			break;
 		case PT_REQUESTFILE:
 		default: // write as a raw packet
-			fprintfstring((char *)netbuffer->u.textcmd,
+			fprintfstringnewline((char *)netbuffer->u.textcmd,
 				(UINT8)((UINT8 *)netbuffer + doomcom->datalength - (UINT8 *)netbuffer->u.textcmd));
 			break;
 	}
 }
 #endif
 
+#ifdef PACKETDROP
+static INT32 packetdropquantity[NUMPACKETTYPE] = {0};
+static INT32 packetdroprate = 0;
+
+void Command_Drop(void)
+{
+	INT32 packetquantity;
+	const char *packetname;
+	size_t i;
+
+	if (COM_Argc() < 2)
+	{
+		CONS_Printf("drop <packettype> [quantity]: drop packets\n"
+					"drop reset: cancel all packet drops");
+		return;
+	}
+
+	if (!(stricmp(COM_Argv(1), "reset") && stricmp(COM_Argv(1), "cancel") && stricmp(COM_Argv(1), "stop")))
+	{
+		memset(packetdropquantity, 0, sizeof(packetdropquantity));
+		return;
+	}
+
+	if (COM_Argc() >= 3)
+	{
+		packetquantity = atoi(COM_Argv(2));
+		if (packetquantity <= 0 && COM_Argv(2)[0] != '0')
+		{
+			CONS_Printf("Invalid quantity\n");
+			return;
+		}
+	}
+	else
+		packetquantity = -1;
+
+	packetname = COM_Argv(1);
+
+	if (!(stricmp(packetname, "all") && stricmp(packetname, "any")))
+		for (i = 0; i < NUMPACKETTYPE; i++)
+			packetdropquantity[i] = packetquantity;
+	else
+	{
+		for (i = 0; i < NUMPACKETTYPE; i++)
+			if (!stricmp(packetname, packettypename[i]))
+			{
+				packetdropquantity[i] = packetquantity;
+				return;
+			}
+
+		CONS_Printf("Unknown packet name\n");
+	}
+}
+
+void Command_Droprate(void)
+{
+	INT32 droprate;
+
+	if (COM_Argc() < 2)
+	{
+		CONS_Printf("Packet drop rate: %d%%\n", packetdroprate);
+		return;
+	}
+
+	droprate = atoi(COM_Argv(1));
+	if ((droprate <= 0 && COM_Argv(1)[0] != '0') || droprate > 100)
+	{
+		CONS_Printf("Packet drop rate must be between 0 and 100!\n");
+		return;
+	}
+
+	packetdroprate = droprate;
+}
+
+static boolean ShouldDropPacket(void)
+{
+	return (packetdropquantity[netbuffer->packettype])
+		|| (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100;
+}
+#endif
+
 //
 // HSendPacket
 //
 boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlength)
 {
 	doomcom->datalength = (INT16)(packetlength + BASEPACKETSIZE);
-	if (node == 0) // packet is to go back to us
+	if (node == 0) // Packet is to go back to us
 	{
 		if ((rebound_head+1) % MAXREBOUND == rebound_tail)
 		{
@@ -871,7 +995,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
 	(void)reliable;
 	(void)acknum;
 #else
-	// do this before GetFreeAcknum because this function backup
+	// do this before GetFreeAcknum because this function backups
 	// the current packet
 	doomcom->remotenode = (INT16)node;
 	if (doomcom->datalength <= 0)
@@ -884,7 +1008,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
 		return false;
 	}
 
-	if (node < MAXNETNODES) // can be a broadcast
+	if (node < MAXNETNODES) // Can be a broadcast
 		netbuffer->ackreturn = GetAcktosend(node);
 	else
 		netbuffer->ackreturn = 0;
@@ -905,20 +1029,30 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
 		netbuffer->ack = acknum;
 
 	netbuffer->checksum = NetbufferChecksum();
-	sendbytes += packetheaderlength + doomcom->datalength; // for stat
+	sendbytes += packetheaderlength + doomcom->datalength; // For stat
 
-	// simulate internet :)
-	if (true || rand()<(INT32)RAND_MAX/5)
+#ifdef PACKETDROP
+	// Simulate internet :)
+	//if (rand() >= (INT32)(RAND_MAX * (PACKETLOSSRATE / 100.f)))
+	if (!ShouldDropPacket())
 	{
+#endif
 #ifdef DEBUGFILE
 		if (debugfile)
-			DebugPrintpacket("SEND");
+			DebugPrintpacket("SENT");
 #endif
 		I_NetSend();
+#ifdef PACKETDROP
 	}
+	else
+	{
+		if (packetdropquantity[netbuffer->packettype] > 0)
+			packetdropquantity[netbuffer->packettype]--;
 #ifdef DEBUGFILE
-	else if (debugfile)
-		DebugPrintpacket("NOTSEND");
+		if (debugfile)
+			DebugPrintpacket("NOT SENT");
+#endif
+	}
 #endif
 
 #endif // ndef NONET
@@ -933,7 +1067,7 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
 //
 boolean HGetPacket(void)
 {
-	// get a packet from self
+	// Get a packet from self
 	if (rebound_tail != rebound_head)
 	{
 		M_Memcpy(netbuffer, &reboundstore[rebound_tail], reboundsize[rebound_tail]);
@@ -963,11 +1097,11 @@ boolean HGetPacket(void)
 		if (doomcom->remotenode == -1)
 			return false;
 
-		getbytes += packetheaderlength + doomcom->datalength; // for stat
+		getbytes += packetheaderlength + doomcom->datalength; // For stat
 
 		if (doomcom->remotenode >= MAXNETNODES)
 		{
-			DEBFILE(va("receive packet from node %d !\n", doomcom->remotenode));
+			DEBFILE(va("Received packet from node %d!\n", doomcom->remotenode));
 			continue;
 		}
 
@@ -1230,4 +1364,6 @@ void D_CloseConnection(void)
 		netgame = false;
 		addedtogame = false;
 	}
+
+	D_ResetTiccmds();
 }
diff --git a/src/d_net.h b/src/d_net.h
index 285b44235b1f2758d671ead084de3f24fd26cc6e..190e07a60ecbaec72517d5ddf408dc0fae8d7219 100644
--- a/src/d_net.h
+++ b/src/d_net.h
@@ -18,10 +18,10 @@
 #ifndef __D_NET__
 #define __D_NET__
 
-// Max computers in a game.
+// Max computers in a game
 #define MAXNETNODES 32
 #define BROADCASTADDR MAXNETNODES
-#define MAXSPLITSCREENPLAYERS 2 // max number of players on a single computer
+#define MAXSPLITSCREENPLAYERS 2 // Max number of players on a single computer
 
 #define STATLENGTH (TICRATE*2)
 
@@ -32,17 +32,16 @@ extern float lostpercent, duppercent, gamelostpercent;
 extern INT32 packetheaderlength;
 boolean Net_GetNetStat(void);
 extern INT32 getbytes;
-extern INT64 sendbytes; // realtime updated
+extern INT64 sendbytes; // Realtime updated
 
 extern SINT8 nodetoplayer[MAXNETNODES];
-extern SINT8 nodetoplayer2[MAXNETNODES]; // say the numplayer for this node if any (splitscreen)
-extern UINT8 playerpernode[MAXNETNODES]; // used specialy for scplitscreen
-extern boolean nodeingame[MAXNETNODES]; // set false as nodes leave game
+extern SINT8 nodetoplayer2[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen)
+extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
+extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
 
 void Net_AckTicker(void);
-boolean Net_AllAckReceived(void);
 
-// if reliable return true if packet sent, 0 else
+// If reliable return true if packet sent, 0 else
 boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum,
 	size_t packetlength);
 boolean HGetPacket(void);
@@ -52,9 +51,10 @@ void D_SaveBan(void);
 #endif
 boolean D_CheckNetGame(void);
 void D_CloseConnection(void);
-void Net_UnAcknowledgPacket(INT32 node);
+void Net_UnAcknowledgePacket(INT32 node);
 void Net_CloseConnection(INT32 node);
 void Net_AbortPacketType(UINT8 packettype);
 void Net_SendAcks(INT32 node);
 void Net_WaitAllAckReceived(UINT32 timeout);
+
 #endif
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 784d07bcaee245f32ccae7b2754b8b479ac36eb0..c54c96f75ed64758b77b10ad173ad4ff43853461 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -365,6 +365,35 @@ boolean splitscreen = false;
 boolean circuitmap = false;
 INT32 adminplayer = -1;
 
+/// \warning Keep this up-to-date if you add/remove/rename net text commands
+const char *netxcmdnames[MAXNETXCMD - 1] =
+{
+	"NAMEANDCOLOR",
+	"WEAPONPREF",
+	"KICK",
+	"NETVAR",
+	"SAY",
+	"MAP",
+	"EXITLEVEL",
+	"ADDFILE",
+	"PAUSE",
+	"ADDPLAYER",
+	"TEAMCHANGE",
+	"CLEARSCORES",
+	"LOGIN",
+	"VERIFIED",
+	"RANDOMSEED",
+	"RUNSOC",
+	"REQADDFILE",
+	"DELFILE",
+	"SETMOTD",
+	"SUICIDE",
+#ifdef HAVE_BLUA
+	"LUACMD",
+	"LUAVAR"
+#endif
+};
+
 // =========================================================================
 //                           SERVER STARTUP
 // =========================================================================
@@ -3960,7 +3989,7 @@ static void Command_Archivetest_f(void)
 	}
 
 	// assign mobjnum
-	i = 0;
+	i = 1;
 	for (th = thinkercap.next; th != &thinkercap; th = th->next)
 		if (th->function.acp1 == (actionf_p1)P_MobjThinker)
 			((mobj_t *)th)->mobjnum = i++;
@@ -4055,8 +4084,7 @@ static void Skin_OnChange(void)
 	if (!Playing())
 		return; // do whatever you want
 
-	if (!(cv_debug || devparm) && !(multiplayer || netgame) // In single player.
-		&& (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_CONTINUING))
+	if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player.
 	{
 		CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
 		return;
diff --git a/src/d_netcmd.h b/src/d_netcmd.h
index c090699f125703b3fc154bd377b88289108533d2..08fc8b831a507bb0d4662fc9d61e4141820322a6 100644
--- a/src/d_netcmd.h
+++ b/src/d_netcmd.h
@@ -101,7 +101,6 @@ extern consvar_t cv_recycler;
 extern consvar_t cv_itemfinder;
 
 extern consvar_t cv_inttime, cv_advancemap, cv_playersforexit;
-extern consvar_t cv_soniccd;
 extern consvar_t cv_match_scoring;
 extern consvar_t cv_overtime;
 extern consvar_t cv_startinglives;
@@ -162,6 +161,8 @@ typedef enum
 	MAXNETXCMD
 } netxcmd_t;
 
+extern const char *netxcmdnames[MAXNETXCMD - 1];
+
 #if defined(_MSC_VER)
 #pragma pack(1)
 #endif
diff --git a/src/d_netfil.c b/src/d_netfil.c
index 85196217ff4551fbda4820fc6d4755ad5d65e1b4..4e3d70fa956f052f70eea5f999e32d3d98af65f9 100644
--- a/src/d_netfil.c
+++ b/src/d_netfil.c
@@ -62,34 +62,37 @@
 
 #include <errno.h>
 
-static void SendFile(INT32 node, const char *filename, UINT8 fileid);
+static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid);
 
-// sender structure
+// Sender structure
 typedef struct filetx_s
 {
 	INT32 ram;
-	char *filename; // name of the file or ptr of the data in ram
-	UINT32 size;
+	union {
+		char *filename; // Name of the file
+		char *ram; // Pointer to the data in RAM
+	} id;
+	UINT32 size; // Size of the file
 	UINT8 fileid;
-	INT32 node; // destination
-	struct filetx_s *next; // a queue
+	INT32 node; // Destination
+	struct filetx_s *next; // Next file in the list
 } filetx_t;
 
-// current transfers (one for each node)
+// Current transfers (one for each node)
 typedef struct filetran_s
 {
-	filetx_t *txlist;
-	UINT32 position;
-	FILE *currentfile;
+	filetx_t *txlist; // Linked list of all files for the node
+	UINT32 position; // The current position in the file
+	FILE *currentfile; // The file currently being sent/received
 } filetran_t;
 static filetran_t transfer[MAXNETNODES];
 
-// read time of file: stat _stmtime
-// write time of file: utime
+// Read time of file: stat _stmtime
+// Write time of file: utime
 
-// receiver structure
-INT32 fileneedednum;
-fileneeded_t fileneeded[MAX_WADFILES];
+// Receiver structure
+INT32 fileneedednum; // Number of files needed to join the server
+fileneeded_t fileneeded[MAX_WADFILES]; // List of needed files
 char downloaddir[256] = "DOWNLOAD";
 
 #ifdef CLIENT_LOADINGSCREEN
@@ -100,6 +103,7 @@ INT32 lastfilenum = 0;
 /** Fills a serverinfo packet with information about wad files loaded.
   *
   * \todo Give this function a better name since it is in global scope.
+  *
   */
 UINT8 *PutFileNeeded(void)
 {
@@ -111,19 +115,19 @@ UINT8 *PutFileNeeded(void)
 
 	for (i = 0; i < numwadfiles; i++)
 	{
-		// if it has only music/sound lumps, mark it as unimportant
+		// If it has only music/sound lumps, mark it as unimportant
 		if (W_VerifyNMUSlumps(wadfiles[i]->filename))
 			filestatus = 0;
 		else
-			filestatus = 1; // important
+			filestatus = 1; // Important
 
 		// Store in the upper four bits
 		if (!cv_downloading.value)
-			filestatus += (2 << 4); // won't send
+			filestatus += (2 << 4); // Won't send
 		else if ((wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024))
-			filestatus += (0 << 4); // won't send
+			filestatus += (0 << 4); // Won't send
 		else
-			filestatus += (1 << 4); // will send if requested
+			filestatus += (1 << 4); // Will send if requested
 
 		bytesused += (nameonlylength(wadfilename) + 22);
 
@@ -144,7 +148,12 @@ UINT8 *PutFileNeeded(void)
 	return p;
 }
 
-// parse the serverinfo packet and fill fileneeded table on client
+/** Parses the serverinfo packet and fills the fileneeded table on client
+  *
+  * \param fileneedednum_parm The number of files needed to join the server
+  * \param fileneededstr The memory block containing the list of needed files
+  *
+  */
 void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
 {
 	INT32 i;
@@ -155,14 +164,14 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
 	p = (UINT8 *)fileneededstr;
 	for (i = 0; i < fileneedednum; i++)
 	{
-		fileneeded[i].status = FS_NOTFOUND;
-		filestatus = READUINT8(p);
+		fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
+		filestatus = READUINT8(p); // The first byte is the file status
 		fileneeded[i].important = (UINT8)(filestatus & 3);
 		fileneeded[i].willsend = (UINT8)(filestatus >> 4);
-		fileneeded[i].totalsize = READUINT32(p);
-		fileneeded[i].phandle = NULL;
-		READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH);
-		READMEM(p, fileneeded[i].md5sum, 16);
+		fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
+		fileneeded[i].file = NULL; // The file isn't open yet
+		READSTRINGN(p, fileneeded[i].filename, MAX_WADPATH); // The next bytes are the file name
+		READMEM(p, fileneeded[i].md5sum, 16); // The last 16 bytes are the file checksum
 	}
 }
 
@@ -171,13 +180,16 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave)
 	fileneedednum = 1;
 	fileneeded[0].status = FS_REQUESTED;
 	fileneeded[0].totalsize = UINT32_MAX;
-	fileneeded[0].phandle = NULL;
+	fileneeded[0].file = NULL;
 	memset(fileneeded[0].md5sum, 0, 16);
 	strcpy(fileneeded[0].filename, tmpsave);
 }
 
 /** Checks the server to see if we CAN download all the files,
   * before starting to create them and requesting.
+  *
+  * \return True if we can download all the files
+  *
   */
 boolean CL_CheckDownloadable(void)
 {
@@ -239,8 +251,12 @@ boolean CL_CheckDownloadable(void)
 	return false;
 }
 
-/** Send requests for files in the ::fileneeded table with a status of
+/** Sends requests for files in the ::fileneeded table with a status of
   * ::FS_NOTFOUND.
+  *
+  * \return True if the packet was successfully sent
+  * \note Sends a PT_REQUESTFILE packet
+  *
   */
 boolean CL_SendRequestFile(void)
 {
@@ -298,11 +314,17 @@ void Got_RequestFilePak(INT32 node)
 		if (id == 0xFF)
 			break;
 		READSTRINGN(p, wad, MAX_WADPATH);
-		SendFile(node, wad, id);
+		SV_SendFile(node, wad, id);
 	}
 }
 
-// client check if the fileneeded aren't already loaded or on the disk
+/** Checks if the files needed aren't already loaded or on the disk
+  *
+  * \return 0 if some files are missing
+  *         1 if all files exist
+  *         2 if some already loaded files are not requested or are in a different order
+  *
+  */
 INT32 CL_CheckFiles(void)
 {
 	INT32 i, j;
@@ -333,7 +355,7 @@ INT32 CL_CheckFiles(void)
 			}
 			if (j < numwadfiles && W_VerifyNMUSlumps(wadfiles[j]->filename))
 			{
-				// unimportant on our side. still don't care.
+				// Unimportant on our side. still don't care.
 				++j;
 				continue;
 			}
@@ -343,11 +365,11 @@ INT32 CL_CheckFiles(void)
 			if (i >= fileneedednum || j >= numwadfiles)
 				return 2;
 
-			// for the sake of speed, only bother with a md5 check
+			// For the sake of speed, only bother with a md5 check
 			if (memcmp(wadfiles[j]->md5sum, fileneeded[i].md5sum, 16))
 				return 2;
 
-			// it's accounted for! let's keep going.
+			// It's accounted for! let's keep going.
 			CONS_Debug(DBG_NETPLAY, "'%s' accounted for\n", fileneeded[i].filename);
 			fileneeded[i].status = FS_OPEN;
 			++i;
@@ -360,7 +382,7 @@ INT32 CL_CheckFiles(void)
 	{
 		CONS_Debug(DBG_NETPLAY, "searching for '%s' ", fileneeded[i].filename);
 
-		// check in allready loaded files
+		// Check in already loaded files
 		for (j = 1; wadfiles[j]; j++)
 		{
 			nameonly(strcpy(wadfilename, wadfiles[j]->filename));
@@ -383,7 +405,7 @@ INT32 CL_CheckFiles(void)
 	return ret;
 }
 
-// load it now
+// Load it now
 void CL_LoadServerFiles(void)
 {
 	INT32 i;
@@ -394,7 +416,7 @@ void CL_LoadServerFiles(void)
 	for (i = 1; i < fileneedednum; i++)
 	{
 		if (fileneeded[i].status == FS_OPEN)
-			continue; // already loaded
+			continue; // Already loaded
 		else if (fileneeded[i].status == FS_FOUND)
 		{
 			P_AddWadFile(fileneeded[i].filename, NULL);
@@ -423,133 +445,200 @@ void CL_LoadServerFiles(void)
 			DEBFILE(va("File %s found but with different md5sum\n", fileneeded[i].filename));
 		}
 		else if (fileneeded[i].important)
-			I_Error("Try to load file %s with status of %d\n", fileneeded[i].filename,
-				fileneeded[i].status);
+		{
+			const char *s;
+			switch(fileneeded[i].status)
+			{
+			case FS_NOTFOUND:
+				s = "FS_NOTFOUND";
+				break;
+			case FS_REQUESTED:
+				s = "FS_REQUESTED";
+				break;
+			case FS_DOWNLOADING:
+				s = "FS_DOWNLOADING";
+				break;
+			default:
+				s = "unknown";
+				break;
+			}
+			I_Error("Try to load file \"%s\" with status of %d (%s)\n", fileneeded[i].filename,
+				fileneeded[i].status, s);
+		}
 	}
 }
 
-// little optimization to test if there is a file in the queue
-static INT32 filetosend = 0;
+// Number of files to send
+// Little optimization to quickly test if there is a file in the queue
+static INT32 filestosend = 0;
 
-static void SendFile(INT32 node, const char *filename, UINT8 fileid)
+/** Adds a file to the file list for a node
+  *
+  * \param node The node to send the file to
+  * \param filename The file to send
+  * \param fileid ???
+  * \sa SV_SendRam
+  *
+  */
+static void SV_SendFile(INT32 node, const char *filename, UINT8 fileid)
 {
-	filetx_t **q;
-	filetx_t *p;
+	filetx_t **q; // A pointer to the "next" field of the last file in the list
+	filetx_t *p; // The new file request
 	INT32 i;
 	char wadfilename[MAX_WADPATH];
 
+	// Find the last file in the list and set a pointer to its "next" field
 	q = &transfer[node].txlist;
 	while (*q)
 		q = &((*q)->next);
+
+	// Allocate a file request and append it to the file list
 	p = *q = (filetx_t *)malloc(sizeof (filetx_t));
-	if (p)
-		memset(p, 0, sizeof (filetx_t));
-	else
-		I_Error("SendFile: No more ram\n");
-	p->filename = (char *)malloc(MAX_WADPATH);
-	if (!p->filename)
-		I_Error("SendFile: No more ram\n");
+	if (!p)
+		I_Error("SV_SendFile: No more memory\n");
+
+	// Initialise with zeros
+	memset(p, 0, sizeof (filetx_t));
+
+	// Allocate the file name
+	p->id.filename = (char *)malloc(MAX_WADPATH);
+	if (!p->id.filename)
+		I_Error("SV_SendFile: No more memory\n");
 
-	// a minimum of security, can get only file in srb2 direcory
-	strlcpy(p->filename, filename, MAX_WADPATH);
-	nameonly(p->filename);
+	// Set the file name and get rid of the path
+	strlcpy(p->id.filename, filename, MAX_WADPATH);
+	nameonly(p->id.filename);
 
-	// check first in wads loaded the majority of case
+	// Look for the requested file through all loaded files
 	for (i = 0; wadfiles[i]; i++)
 	{
 		strlcpy(wadfilename, wadfiles[i]->filename, MAX_WADPATH);
 		nameonly(wadfilename);
-		if (!stricmp(wadfilename, p->filename))
+		if (!stricmp(wadfilename, p->id.filename))
 		{
-			// copy filename with full path
-			strlcpy(p->filename, wadfiles[i]->filename, MAX_WADPATH);
+			// Copy file name with full path
+			strlcpy(p->id.filename, wadfiles[i]->filename, MAX_WADPATH);
 			break;
 		}
 	}
 
+	// Handle non-loaded file requests
 	if (!wadfiles[i])
 	{
 		DEBFILE(va("%s not found in wadfiles\n", filename));
-		// this formerly checked if (!findfile(p->filename, NULL, true))
+		// This formerly checked if (!findfile(p->id.filename, NULL, true))
 
-		// not found
-		// don't inform client (probably hacker)
+		// Not found
+		// Don't inform client (probably someone who thought they could leak 2.2 ACZ)
 		DEBFILE(va("Client %d request %s: not found\n", node, filename));
-		free(p->filename);
+		free(p->id.filename);
 		free(p);
 		*q = NULL;
 		return;
 	}
 
+	// Handle huge file requests (i.e. bigger than cv_maxsend.value KB)
 	if (wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024)
 	{
-		// too big
-		// don't inform client (client sucks, man)
+		// Too big
+		// Don't inform client (client sucks, man)
 		DEBFILE(va("Client %d request %s: file too big, not sending\n", node, filename));
-		free(p->filename);
+		free(p->id.filename);
 		free(p);
 		*q = NULL;
 		return;
 	}
 
 	DEBFILE(va("Sending file %s (id=%d) to %d\n", filename, fileid, node));
-	p->ram = SF_FILE;
+	p->ram = SF_FILE; // It's a file, we need to close it and free its name once we're done sending it
 	p->fileid = fileid;
-	p->next = NULL; // end of list
-	filetosend++;
+	p->next = NULL; // End of list
+	filestosend++;
 }
 
-void SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid)
+/** Adds a memory block to the file list for a node
+  *
+  * \param node The node to send the memory block to
+  * \param data The memory block to send
+  * \param size The size of the block in bytes
+  * \param freemethod How to free the block after it has been sent
+  * \param fileid ???
+  * \sa SV_SendFile
+  *
+  */
+void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod, UINT8 fileid)
 {
-	filetx_t **q;
-	filetx_t *p;
+	filetx_t **q; // A pointer to the "next" field of the last file in the list
+	filetx_t *p; // The new file request
 
+	// Find the last file in the list and set a pointer to its "next" field
 	q = &transfer[node].txlist;
 	while (*q)
 		q = &((*q)->next);
+
+	// Allocate a file request and append it to the file list
 	p = *q = (filetx_t *)malloc(sizeof (filetx_t));
-	if (p)
-		memset(p, 0, sizeof (filetx_t));
-	else
-		I_Error("SendRam: No more ram\n");
-	p->ram = freemethod;
-	p->filename = data;
+	if (!p)
+		I_Error("SV_SendRam: No more memory\n");
+
+	// Initialise with zeros
+	memset(p, 0, sizeof (filetx_t));
+
+	p->ram = freemethod; // Remember how to free the memory block for when we're done sending it
+	p->id.ram = data;
 	p->size = (UINT32)size;
 	p->fileid = fileid;
-	p->next = NULL; // end of list
+	p->next = NULL; // End of list
 
-	DEBFILE(va("Sending ram %p(size:%u) to %d (id=%u)\n",p->filename,p->size,node,fileid));
+	DEBFILE(va("Sending ram %p(size:%u) to %d (id=%u)\n",p->id.ram,p->size,node,fileid));
 
-	filetosend++;
+	filestosend++;
 }
 
-static void EndSend(INT32 node)
+/** Stops sending a file for a node, and removes the file request from the list,
+  * either because the file has been fully sent or because the node was disconnected
+  *
+  * \param node The destination
+  *
+  */
+static void SV_EndFileSend(INT32 node)
 {
 	filetx_t *p = transfer[node].txlist;
+
+	// Free the file request according to the freemethod parameter used with SV_SendFile/Ram
 	switch (p->ram)
 	{
-		case SF_FILE:
+		case SF_FILE: // It's a file, close it and free its filename
 			if (transfer[node].currentfile)
 				fclose(transfer[node].currentfile);
-			free(p->filename);
+			free(p->id.filename);
 			break;
-		case SF_Z_RAM:
-			Z_Free(p->filename);
+		case SF_Z_RAM: // It's a memory block allocated with Z_Alloc or the likes, use Z_Free
+			Z_Free(p->id.ram);
 			break;
-		case SF_RAM:
-			free(p->filename);
-		case SF_NOFREERAM:
+		case SF_RAM: // It's a memory block allocated with malloc, use free
+			free(p->id.ram);
+		case SF_NOFREERAM: // Nothing to free
 			break;
 	}
+
+	// Remove the file request from the list
 	transfer[node].txlist = p->next;
-	transfer[node].currentfile = NULL;
 	free(p);
-	filetosend--;
+
+	// Indicate that the transmission is over
+	transfer[node].currentfile = NULL;
+
+	filestosend--;
 }
 
 #define PACKETPERTIC net_bandwidth/(TICRATE*software_MAXPACKETLENGTH)
 
-void FiletxTicker(void)
+/** Handles file transmission
+  *
+  *
+  */
+void SV_FileSendTicker(void)
 {
 	static INT32 currentnode = 0;
 	filetx_pak *p;
@@ -557,12 +646,12 @@ void FiletxTicker(void)
 	filetx_t *f;
 	INT32 packetsent = PACKETPERTIC, ram, i;
 
-	if (!filetosend)
+	if (!filestosend)
 		return;
 	if (!packetsent)
 		packetsent++;
 	// (((sendbytes-nowsentbyte)*TICRATE)/(I_GetTime()-starttime)<(UINT32)net_bandwidth)
-	while (packetsent-- && filetosend != 0)
+	while (packetsent-- && filestosend != 0)
 	{
 		for (i = currentnode, ram = 0; ram < MAXNETNODES;
 			i = (i+1) % MAXNETNODES, ram++)
@@ -571,24 +660,25 @@ void FiletxTicker(void)
 				goto found;
 		}
 		// no transfer to do
-		I_Error("filetosend=%d but no filetosend found\n", filetosend);
+		I_Error("filestosend=%d but no file to send found\n", filestosend);
 	found:
 		currentnode = (i+1) % MAXNETNODES;
 		f = transfer[i].txlist;
 		ram = f->ram;
 
-		if (!transfer[i].currentfile) // file not already open
+		// Open the file if it isn't open yet, or
+		if (!transfer[i].currentfile)
 		{
-			if (!ram)
+			if (!ram) // Sending a file
 			{
 				long filesize;
 
 				transfer[i].currentfile =
-					fopen(f->filename, "rb");
+					fopen(f->id.filename, "rb");
 
 				if (!transfer[i].currentfile)
 					I_Error("File %s does not exist",
-						f->filename);
+						f->id.filename);
 
 				fseek(transfer[i].currentfile, 0, SEEK_END);
 				filesize = ftell(transfer[i].currentfile);
@@ -596,46 +686,49 @@ void FiletxTicker(void)
 				// Nobody wants to transfer a file bigger
 				// than 4GB!
 				if (filesize >= LONG_MAX)
-					I_Error("filesize of %s is too large", f->filename);
-				if (-1 == filesize)
-					I_Error("Error getting filesize of %s", f->filename);
+					I_Error("filesize of %s is too large", f->id.filename);
+				if (filesize == -1)
+					I_Error("Error getting filesize of %s", f->id.filename);
 
 				f->size = (UINT32)filesize;
 				fseek(transfer[i].currentfile, 0, SEEK_SET);
 			}
-			else
-				transfer[i].currentfile = (FILE *)1;
+			else // Sending RAM
+				transfer[i].currentfile = (FILE *)1; // Set currentfile to a non-null value to indicate that it is open
 			transfer[i].position = 0;
 		}
 
+		// Build a packet containing a file fragment
 		p = &netbuffer->u.filetxpak;
 		size = software_MAXPACKETLENGTH - (FILETXHEADER + BASEPACKETSIZE);
 		if (f->size-transfer[i].position < size)
 			size = f->size-transfer[i].position;
 		if (ram)
-			M_Memcpy(p->data, &f->filename[transfer[i].position], size);
+			M_Memcpy(p->data, &f->id.ram[transfer[i].position], size);
 		else if (fread(p->data, 1, size, transfer[i].currentfile) != size)
-			I_Error("FiletxTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->filename, transfer[i].position, strerror(ferror(transfer[i].currentfile)));
+			I_Error("SV_FileSendTicker: can't read %s byte on %s at %d because %s", sizeu1(size), f->id.filename, transfer[i].position, strerror(ferror(transfer[i].currentfile)));
 		p->position = LONG(transfer[i].position);
-		// put flag so receiver know the totalsize
+		// Put flag so receiver knows the total size
 		if (transfer[i].position + size == f->size)
 			p->position |= LONG(0x80000000);
 		p->fileid = f->fileid;
 		p->size = SHORT((UINT16)size);
 		netbuffer->packettype = PT_FILEFRAGMENT;
-		if (!HSendPacket(i, true, 0, FILETXHEADER + size)) // reliable SEND
-		{ // not sent for some odd reason, retry at next call
+
+		// Send the packet
+		if (HSendPacket(i, true, 0, FILETXHEADER + size)) // Reliable SEND
+		{ // Success
+			transfer[i].position = (UINT32)(transfer[i].position + size);
+			if (transfer[i].position == f->size) // Finish?
+				SV_EndFileSend(i);
+		}
+		else
+		{ // Not sent for some odd reason, retry at next call
 			if (!ram)
-				fseek(transfer[i].currentfile,transfer[i].position,SEEK_SET);
-			// exit the while (can't send this one so why should i send the next?)
+				fseek(transfer[i].currentfile,transfer[i].position, SEEK_SET);
+			// Exit the while (can't send this one so why should i send the next?)
 			break;
 		}
-		else // success
-		{
-			transfer[i].position = (UINT32)(size+transfer[i].position);
-			if (transfer[i].position == f->size) //  finish ?
-				EndSend(i);
-		}
 	}
 }
 
@@ -646,16 +739,18 @@ void Got_Filetxpak(void)
 
 	if (filenum >= fileneedednum)
 	{
-		DEBFILE(va("fileframent not needed %d>%d\n",filenum, fileneedednum));
+		DEBFILE(va("fileframent not needed %d>%d\n", filenum, fileneedednum));
 		return;
 	}
 
 	if (fileneeded[filenum].status == FS_REQUESTED)
 	{
-		if (fileneeded[filenum].phandle) I_Error("Got_Filetxpak: allready open file\n");
-			fileneeded[filenum].phandle = fopen(fileneeded[filenum].filename, "wb");
-		if (!fileneeded[filenum].phandle) I_Error("Can't create file %s: %s",fileneeded[filenum].filename, strerror(errno));
-			CONS_Printf("\r%s...\n",fileneeded[filenum].filename);
+		if (fileneeded[filenum].file)
+			I_Error("Got_Filetxpak: already open file\n");
+		fileneeded[filenum].file = fopen(fileneeded[filenum].filename, "wb");
+		if (!fileneeded[filenum].file)
+			I_Error("Can't create file %s: %s", fileneeded[filenum].filename, strerror(errno));
+		CONS_Printf("\r%s...\n",fileneeded[filenum].filename);
 		fileneeded[filenum].currentsize = 0;
 		fileneeded[filenum].status = FS_DOWNLOADING;
 	}
@@ -664,24 +759,24 @@ void Got_Filetxpak(void)
 	{
 		UINT32 pos = LONG(netbuffer->u.filetxpak.position);
 		UINT16 size = SHORT(netbuffer->u.filetxpak.size);
-		// use a special tric to know when file is finished (not allways used)
-		// WARNING: filepak can arrive out of order so don't stop now !
+		// Use a special trick to know when the file is complete (not always used)
+		// WARNING: file fragments can arrive out of order so don't stop yet!
 		if (pos & 0x80000000)
 		{
 			pos &= ~0x80000000;
 			fileneeded[filenum].totalsize = pos + size;
 		}
-		// we can receive packet in the wrong order, anyway all os support gaped file
-		fseek(fileneeded[filenum].phandle,pos,SEEK_SET);
-		if (fwrite(netbuffer->u.filetxpak.data,size,1,fileneeded[filenum].phandle)!=1)
-			I_Error("Can't write to %s: %s\n",fileneeded[filenum].filename, strerror(ferror(fileneeded[filenum].phandle)));
+		// We can receive packet in the wrong order, anyway all os support gaped file
+		fseek(fileneeded[filenum].file, pos, SEEK_SET);
+		if (fwrite(netbuffer->u.filetxpak.data,size,1,fileneeded[filenum].file) != 1)
+			I_Error("Can't write to %s: %s\n",fileneeded[filenum].filename, strerror(ferror(fileneeded[filenum].file)));
 		fileneeded[filenum].currentsize += size;
 
-		// finished?
+		// Finished?
 		if (fileneeded[filenum].currentsize == fileneeded[filenum].totalsize)
 		{
-			fclose(fileneeded[filenum].phandle);
-			fileneeded[filenum].phandle = NULL;
+			fclose(fileneeded[filenum].file);
+			fileneeded[filenum].file = NULL;
 			fileneeded[filenum].status = FS_FOUND;
 			CONS_Printf(M_GetText("Downloading %s...(done)\n"),
 				fileneeded[filenum].filename);
@@ -689,8 +784,8 @@ void Got_Filetxpak(void)
 	}
 	else
 		I_Error("Received a file not requested\n");
-	// send ack back quickly
 
+	// Send ack back quickly
 	if (++filetime == 3)
 	{
 		Net_SendAcks(servernode);
@@ -702,33 +797,39 @@ void Got_Filetxpak(void)
 #endif
 }
 
-void AbortSendFiles(INT32 node)
+/** Cancels all file requests for a node
+ *
+ * \param node The destination
+ * \sa SV_EndFileSend
+ *
+ */
+void SV_AbortSendFiles(INT32 node)
 {
 	while (transfer[node].txlist)
-		EndSend(node);
+		SV_EndFileSend(node);
 }
 
 void CloseNetFile(void)
 {
 	INT32 i;
-	// is sending?
+	// Is sending?
 	for (i = 0; i < MAXNETNODES; i++)
-		AbortSendFiles(i);
+		SV_AbortSendFiles(i);
 
-	// receiving a file?
+	// Receiving a file?
 	for (i = 0; i < MAX_WADFILES; i++)
-		if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].phandle)
+		if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file)
 		{
-			fclose(fileneeded[i].phandle);
-			// file is not complete delete it
+			fclose(fileneeded[i].file);
+			// File is not complete delete it
 			remove(fileneeded[i].filename);
 		}
 
-	// remove FILEFRAGMENT from acknledge list
+	// Remove PT_FILEFRAGMENT from acknowledge list
 	Net_AbortPacketType(PT_FILEFRAGMENT);
 }
 
-// functions cut and pasted from doomatic :)
+// Functions cut and pasted from Doomatic :)
 
 void nameonly(char *s)
 {
diff --git a/src/d_netfil.h b/src/d_netfil.h
index a68119f10dc59cd6fec1406abda9f7fa0fa0591a..e82b57d67ea7a9ec75fd29655ac82c5fef6a6873 100644
--- a/src/d_netfil.h
+++ b/src/d_netfil.h
@@ -29,21 +29,21 @@ typedef enum
 	FS_FOUND,
 	FS_REQUESTED,
 	FS_DOWNLOADING,
-	FS_OPEN, // is opened and used in w_wad
+	FS_OPEN, // Is opened and used in w_wad
 	FS_MD5SUMBAD
 } filestatus_t;
 
 typedef struct
 {
 	UINT8 important;
-	UINT8 willsend; // is the server willing to send it?
+	UINT8 willsend; // Is the server willing to send it?
 	char filename[MAX_WADPATH];
 	UINT8 md5sum[16];
-	// used only for download
-	FILE *phandle;
+	// Used only for download
+	FILE *file;
 	UINT32 currentsize;
 	UINT32 totalsize;
-	filestatus_t status; // the value returned by recsearch
+	filestatus_t status; // The value returned by recsearch
 } fileneeded_t;
 
 extern INT32 fileneedednum;
@@ -58,28 +58,24 @@ UINT8 *PutFileNeeded(void);
 void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr);
 void CL_PrepareDownloadSaveGame(const char *tmpsave);
 
-// check file list in wadfiles return 0 when a file is not found
-//                                    1 if all file are found
-//                                    2 if you cannot connect (different wad version or
-//                                                   no enought space to download files)
 INT32 CL_CheckFiles(void);
 void CL_LoadServerFiles(void);
-void SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod,
+void SV_SendRam(INT32 node, void *data, size_t size, freemethod_t freemethod,
 	UINT8 fileid);
 
-void FiletxTicker(void);
+void SV_FileSendTicker(void);
 void Got_Filetxpak(void);
 
 boolean CL_CheckDownloadable(void);
 boolean CL_SendRequestFile(void);
 void Got_RequestFilePak(INT32 node);
 
-void AbortSendFiles(INT32 node);
+void SV_AbortSendFiles(INT32 node);
 void CloseNetFile(void);
 
 boolean fileexist(char *filename, time_t ptime);
 
-// search a file in the wadpath, return FS_FOUND when found
+// Search a file in the wadpath, return FS_FOUND when found
 filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum,
 	boolean completepath);
 filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum);
diff --git a/src/d_player.h b/src/d_player.h
index 49f6cfadea868462ffbaa51a0d608f72d3d8edcc..1c57e61677a85f9b05c053b010db98c5302c7271 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -44,6 +44,7 @@ typedef enum
 	SF_STOMPDAMAGE      = 1<<9, // Always damage enemies, etc by landing on them, no matter your vunerability?
 	SF_MARIODAMAGE      = SF_NOJUMPDAMAGE|SF_STOMPDAMAGE, // The Mario method of being able to damage enemies, etc.
 	SF_MACHINE          = 1<<10, // Beep boop. Are you a robot?
+	SF_NOSPINDASHDUST   = 1<<11, // Don't spawn dust particles when charging a spindash
 	// free up to and including 1<<31
 } skinflags_t;
 
@@ -151,7 +152,13 @@ typedef enum
 	PF_ANALOGMODE        = 1<<26, // Analog mode?
 
 	// Can carry another player?
-	PF_CANCARRY          = 1<<27
+	PF_CANCARRY          = 1<<27,
+
+	// Used shield ability
+	PF_SHIELDABILITY     = 1<<28,
+
+	// Force jump damage?
+	PF_FORCEJUMPDAMAGE        = 1<<29
 
 	// free up to and including 1<<31
 } pflags_t;
@@ -178,23 +185,34 @@ typedef enum
 typedef enum
 {
 	SH_NONE = 0,
-	// Standard shields
-	SH_JUMP,
-	SH_ATTRACT,
-	SH_ELEMENTAL,
-	SH_BOMB,
-	// Stupid useless unimplimented Sonic 3 shields
-	SH_BUBBLEWRAP,
-	SH_THUNDERCOIN,
-	SH_FLAMEAURA,
-	// Pity shield: the world's most basic shield ever, given to players who suck at Match
-	SH_PITY,
-	// The fireflower is special, it combines with other shields.
-	SH_FIREFLOWER = 0x100,
-	// The force shield uses the lower 8 bits to count how many hits are left.
-	SH_FORCE = 0x200,
-
-	SH_STACK = SH_FIREFLOWER,
+
+	// Shield flags
+	SH_PROTECTFIRE = 0x400,
+	SH_PROTECTWATER = 0x800,
+	SH_PROTECTELECTRIC = 0x1000,
+
+	// Indivisible shields
+	SH_PITY = 1, // the world's most basic shield ever, given to players who suck at Match
+	SH_WHIRLWIND,
+	SH_ARMAGEDDON,
+
+	// normal shields that use flags
+	SH_ATTRACT = SH_PROTECTELECTRIC,
+	SH_ELEMENTAL = SH_PROTECTFIRE|SH_PROTECTWATER,
+
+	// Sonic 3 shields
+	SH_FLAMEAURA = SH_PROTECTFIRE,
+	SH_BUBBLEWRAP = SH_PROTECTWATER,
+	SH_THUNDERCOIN = SH_WHIRLWIND|SH_PROTECTELECTRIC,
+
+	// The force shield uses the lower 8 bits to count how many extra hits are left.
+	SH_FORCE = 0x100,
+	SH_FORCEHP = 0xFF, // to be used as a bitmask only
+
+	// Mostly for use with Mario mode.
+	SH_FIREFLOWER = 0x200,
+
+	SH_STACK = SH_FIREFLOWER, // second-layer shields
 	SH_NOSTACK = ~SH_STACK
 } shieldtype_t; // pw_shield
 
@@ -359,8 +377,8 @@ typedef struct player_s
 	UINT8 gotcontinue; // Got continue from this stage?
 
 	fixed_t speed; // Player's speed (distance formula of MOMX and MOMY values)
-	UINT8 jumping; // Jump counter
-	UINT8 secondjump;
+	UINT8 jumping; // Holding down jump button
+	UINT8 secondjump; // Jump counter
 
 	UINT8 fly1; // Tails flying
 	UINT8 scoreadd; // Used for multiple enemy attack bonus
diff --git a/src/dehacked.c b/src/dehacked.c
index 347bae8c9bd66bc02a64a81717389592c62820a5..56a211be86fb8a63bd9d563c737abd49c48412ff 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -371,7 +371,9 @@ static void clear_levels(void)
 		// (no need to set num to 0, we're freeing the entire header shortly)
 		Z_Free(mapheaderinfo[i]->customopts);
 
+		P_DeleteFlickies(i);
 		P_DeleteGrades(i);
+
 		Z_Free(mapheaderinfo[i]);
 		mapheaderinfo[i] = NULL;
 	}
@@ -990,6 +992,34 @@ static const struct {
 	{NULL, 0}
 };
 
+static const struct {
+	const char *name;
+	const mobjtype_t type;
+} FLICKYTYPES[] = {
+	{"BLUEBIRD", MT_FLICKY_01},
+	{"RABBIT",   MT_FLICKY_02},
+	{"CHICKEN",  MT_FLICKY_03},
+	{"SEAL",     MT_FLICKY_04},
+	{"PIG",      MT_FLICKY_05},
+	{"CHIPMUNK", MT_FLICKY_06},
+	{"PENGUIN",  MT_FLICKY_07},
+	{"FISH",     MT_FLICKY_08},
+	{"RAM",      MT_FLICKY_09},
+	{"PUFFIN",   MT_FLICKY_10},
+	{"COW",      MT_FLICKY_11},
+	{"RAT",      MT_FLICKY_12},
+	{"BEAR",     MT_FLICKY_13},
+	{"DOVE",     MT_FLICKY_14},
+	{"CAT",      MT_FLICKY_15},
+	{"CANARY",   MT_FLICKY_16},
+	{"a", 0}, // End of normal flickies - a lower case character so will never fastcmp valid with uppercase tmp
+	//{"FLICKER",  MT_FLICKER},
+	{"SEED",          MT_SEED},
+	{NULL, 0}
+};
+
+#define MAXFLICKIES 64
+
 static void readlevelheader(MYFILE *f, INT32 num)
 {
 	char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
@@ -1088,8 +1118,82 @@ static void readlevelheader(MYFILE *f, INT32 num)
 			// Now go to uppercase
 			strupr(word2);
 
+			// List of flickies that are be freed in this map
+			if (fastcmp(word, "FLICKYLIST") || fastcmp(word, "ANIMALLIST"))
+			{
+				if (fastcmp(word2, "NONE"))
+					P_DeleteFlickies(num-1);
+				else if (fastcmp(word2, "DEMO"))
+					P_SetDemoFlickies(num-1);
+				else if (fastcmp(word2, "ALL"))
+				{
+					mobjtype_t tmpflickies[MAXFLICKIES];
+
+					for (mapheaderinfo[num-1]->numFlickies = 0;
+					((mapheaderinfo[num-1]->numFlickies < MAXFLICKIES) && FLICKYTYPES[mapheaderinfo[num-1]->numFlickies].type);
+					mapheaderinfo[num-1]->numFlickies++)
+						tmpflickies[mapheaderinfo[num-1]->numFlickies] = FLICKYTYPES[mapheaderinfo[num-1]->numFlickies].type;
+
+					if (mapheaderinfo[num-1]->numFlickies) // just in case...
+					{
+						size_t newsize = sizeof(mobjtype_t) * mapheaderinfo[num-1]->numFlickies;
+						mapheaderinfo[num-1]->flickies = Z_Realloc(mapheaderinfo[num-1]->flickies, newsize, PU_STATIC, NULL);
+						M_Memcpy(mapheaderinfo[num-1]->flickies, tmpflickies, newsize);
+					}
+				}
+				else
+				{
+					mobjtype_t tmpflickies[MAXFLICKIES];
+					mapheaderinfo[num-1]->numFlickies = 0;
+					tmp = strtok(word2,",");
+					// get up to the first MAXFLICKIES flickies
+					do {
+						if (mapheaderinfo[num-1]->numFlickies == MAXFLICKIES) // never going to get above that number
+						{
+							deh_warning("Level header %d: too many flickies\n", num);
+							break;
+						}
+
+						if (fastncmp(tmp, "MT_", 3)) // support for specified mobjtypes...
+						{
+							i = get_mobjtype(tmp);
+							if (!i)
+							{
+								//deh_warning("Level header %d: unknown flicky mobj type %s\n", num, tmp); -- no need for this line as get_mobjtype complains too
+								continue;
+							}
+							tmpflickies[mapheaderinfo[num-1]->numFlickies] = i;
+						}
+						else // ...or a quick, limited selection of default flickies!
+						{
+							for (i = 0; FLICKYTYPES[i].name; i++)
+								if (fastcmp(tmp, FLICKYTYPES[i].name))
+									break;
+
+							if (!FLICKYTYPES[i].name)
+							{
+								deh_warning("Level header %d: unknown flicky selection %s\n", num, tmp);
+								continue;
+							}
+							tmpflickies[mapheaderinfo[num-1]->numFlickies] = FLICKYTYPES[i].type;
+						}
+						mapheaderinfo[num-1]->numFlickies++;
+					} while ((tmp = strtok(NULL,",")) != NULL);
+
+					if (mapheaderinfo[num-1]->numFlickies)
+					{
+						size_t newsize = sizeof(mobjtype_t) * mapheaderinfo[num-1]->numFlickies;
+						mapheaderinfo[num-1]->flickies = Z_Realloc(mapheaderinfo[num-1]->flickies, newsize, PU_STATIC, NULL);
+						// now we add them to the list!
+						M_Memcpy(mapheaderinfo[num-1]->flickies, tmpflickies, newsize);
+					}
+					else
+						deh_warning("Level header %d: no valid flicky types found\n", num);
+				}
+			}
+
 			// NiGHTS grades
-			if (fastncmp(word, "GRADES", 6))
+			else if (fastncmp(word, "GRADES", 6))
 			{
 				UINT8 mare = (UINT8)atoi(word + 6);
 
@@ -1322,6 +1426,8 @@ static void readlevelheader(MYFILE *f, INT32 num)
 	Z_Free(s);
 }
 
+#undef MAXFLICKIES
+
 static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
 {
 	char *s = Z_Calloc(MAXLINELEN, PU_STATIC, NULL);
@@ -1687,6 +1793,9 @@ static actionpointer_t actionpointers[] =
 	{{A_WaterShield},          "A_WATERSHIELD"},
 	{{A_ForceShield},          "A_FORCESHIELD"},
 	{{A_PityShield},           "A_PITYSHIELD"},
+	{{A_FlameShield},          "A_FLAMESHIELD"},
+	{{A_BubbleShield},         "A_BUBBLESHIELD"},
+	{{A_ThunderShield},        "A_THUNDERSHIELD"},
 	{{A_GravityBox},           "A_GRAVITYBOX"},
 	{{A_ScoreRise},            "A_SCORERISE"},
 	{{A_ParticleSpawn},        "A_PARTICLESPAWN"},
@@ -1842,6 +1951,16 @@ static actionpointer_t actionpointers[] =
 	{{A_BrakLobShot},          "A_BRAKLOBSHOT"},
 	{{A_NapalmScatter},        "A_NAPALMSCATTER"},
 	{{A_SpawnFreshCopy},       "A_SPAWNFRESHCOPY"},
+	{{A_FlickySpawn},          "A_FLICKYSPAWN"},
+	{{A_FlickyAim},            "A_FLICKYAIM"},
+	{{A_FlickyFly},            "A_FLICKYFLY"},
+	{{A_FlickySoar},           "A_FLICKYSOAR"},
+	{{A_FlickyCoast},          "A_FLICKYCOAST"},
+	{{A_FlickyHop},            "A_FLICKYHOP"},
+	{{A_FlickyFlounder},       "A_FLICKYFLOUNDER"},
+	{{A_FlickyCheck},          "A_FLICKYCHECK"},
+	{{A_FlickyHeightCheck},    "A_FLICKYHEIGHTCHECK"},
+	{{A_FlickyFlutter},        "A_FLICKYFLUTTER"},
 
 	{{NULL},                   "NONE"},
 
@@ -2778,7 +2897,7 @@ static void readpatch(MYFILE *f, const char *name, UINT16 wad)
 	char *word2;
 	char *tmp;
 	INT32 i = 0, j = 0, value;
-	texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX};
+	texpatch_t patch = {0, 0, UINT16_MAX, UINT16_MAX, 0};
 
 	// Jump to the texture this patch belongs to, which,
 	// coincidentally, is always the last one on the buffer cache.
@@ -3378,11 +3497,11 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad)
 				{
 					if (i == 0 && word2[0] != '0') // If word2 isn't a number
 						i = get_mobjtype(word2); // find a thing by name
-					if (i < NUMMOBJTYPES && i >= 0)
+					if (i < NUMMOBJTYPES && i > 0)
 						readthing(f, i);
 					else
 					{
-						deh_warning("Thing %d out of range (0 - %d)", i, NUMMOBJTYPES-1);
+						deh_warning("Thing %d out of range (1 - %d)", i, NUMMOBJTYPES-1);
 						ignorelines(f);
 					}
 					DEH_WriteUndoline(word, word2, UNDO_HEADER);
@@ -4834,7 +4953,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_SPIKEBALL7",
 	"S_SPIKEBALL8",
 
-	// Fire Shield's Spawn
+	// Elemental Shield's Spawn
 	"S_SPINFIRE1",
 	"S_SPINFIRE2",
 	"S_SPINFIRE3",
@@ -4908,6 +5027,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_RECYCLER_BOX",
 	"S_SCORE1K_BOX",
 	"S_SCORE10K_BOX",
+	"S_FLAMEAURA_BOX",
+	"S_BUBBLEWRAP_BOX",
+	"S_THUNDERCOIN_BOX",
 
 	// Gold Repeat Monitor States (one per box)
 	"S_PITY_GOLDBOX",
@@ -4920,6 +5042,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_INVULN_GOLDBOX",
 	"S_EGGMAN_GOLDBOX",
 	"S_GRAVITY_GOLDBOX",
+	"S_FLAMEAURA_GOLDBOX",
+	"S_BUBBLEWRAP_GOLDBOX",
+	"S_THUNDERCOIN_GOLDBOX",
 
 	// Team Ring Boxes (these are special)
 	"S_RING_REDBOX1",
@@ -4981,6 +5106,15 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_SCORE10K_ICON1",
 	"S_SCORE10K_ICON2",
 
+	"S_FLAMEAURA_ICON1",
+	"S_FLAMEAURA_ICON2",
+
+	"S_BUBBLEWRAP_ICON1",
+	"S_BUBBLEWRAP_ICON2",
+
+	"S_THUNDERCOIN_ICON1",
+	"S_THUNDERCOIN_ICON2",
+
 	"S_ROCKET",
 
 	"S_LASER",
@@ -5350,6 +5484,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_MAGN10",
 	"S_MAGN11",
 	"S_MAGN12",
+	"S_MAGN13",
 
 	"S_FORC1",
 	"S_FORC2",
@@ -5373,6 +5508,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_FORC19",
 	"S_FORC20",
 
+	"S_FORC21",
+
 	"S_ELEM1",
 	"S_ELEM2",
 	"S_ELEM3",
@@ -5386,6 +5523,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_ELEM11",
 	"S_ELEM12",
 
+	"S_ELEM13",
+	"S_ELEM14",
+
 	"S_ELEMF1",
 	"S_ELEMF2",
 	"S_ELEMF3",
@@ -5394,6 +5534,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_ELEMF6",
 	"S_ELEMF7",
 	"S_ELEMF8",
+	"S_ELEMF9",
+	"S_ELEMF10",
 
 	"S_PITY1",
 	"S_PITY2",
@@ -5406,6 +5548,84 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_PITY9",
 	"S_PITY10",
 
+	"S_FIRS1",
+	"S_FIRS2",
+	"S_FIRS3",
+	"S_FIRS4",
+	"S_FIRS5",
+	"S_FIRS6",
+	"S_FIRS7",
+	"S_FIRS8",
+	"S_FIRS9",
+
+	"S_FIRS10",
+	"S_FIRS11",
+
+	"S_FIRSB1",
+	"S_FIRSB2",
+	"S_FIRSB3",
+	"S_FIRSB4",
+	"S_FIRSB5",
+	"S_FIRSB6",
+	"S_FIRSB7",
+	"S_FIRSB8",
+	"S_FIRSB9",
+
+	"S_FIRSB10",
+
+	"S_BUBS1",
+	"S_BUBS2",
+	"S_BUBS3",
+	"S_BUBS4",
+	"S_BUBS5",
+	"S_BUBS6",
+	"S_BUBS7",
+	"S_BUBS8",
+	"S_BUBS9",
+
+	"S_BUBS10",
+	"S_BUBS11",
+
+	"S_BUBSB1",
+	"S_BUBSB2",
+	"S_BUBSB3",
+	"S_BUBSB4",
+
+	"S_BUBSB5",
+	"S_BUBSB6",
+
+	"S_ZAPS1",
+	"S_ZAPS2",
+	"S_ZAPS3",
+	"S_ZAPS4",
+	"S_ZAPS5",
+	"S_ZAPS6",
+	"S_ZAPS7",
+	"S_ZAPS8",
+	"S_ZAPS9",
+	"S_ZAPS10",
+	"S_ZAPS11",
+	"S_ZAPS12",
+	"S_ZAPS13", // blank frame
+	"S_ZAPS14",
+	"S_ZAPS15",
+	"S_ZAPS16",
+
+	"S_ZAPSB1", // blank frame
+	"S_ZAPSB2",
+	"S_ZAPSB3",
+	"S_ZAPSB4",
+	"S_ZAPSB5",
+	"S_ZAPSB6",
+	"S_ZAPSB7",
+	"S_ZAPSB8",
+	"S_ZAPSB9",
+	"S_ZAPSB10",
+	"S_ZAPSB11", // blank frame
+
+	// Thunder spark
+	"S_THUNDERCOIN_SPARK",
+
 	// Invincibility Sparkles
 	"S_IVSP",
 
@@ -5416,43 +5636,133 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_SSPK4",
 	"S_SSPK5",
 
-	// Freed Birdie
-	"S_BIRD1",
-	"S_BIRD2",
-	"S_BIRD3",
-
-	// Freed Bunny
-	"S_BUNNY1",
-	"S_BUNNY2",
-	"S_BUNNY3",
-	"S_BUNNY4",
-	"S_BUNNY5",
-	"S_BUNNY6",
-	"S_BUNNY7",
-	"S_BUNNY8",
-	"S_BUNNY9",
-	"S_BUNNY10",
-
-	// Freed Mouse
-	"S_MOUSE1",
-	"S_MOUSE2",
-
-	// Freed Chicken
-	"S_CHICKEN1",
-	"S_CHICKENHOP",
-	"S_CHICKENFLY1",
-	"S_CHICKENFLY2",
-
-	// Freed Cow
-	"S_COW1",
-	"S_COW2",
-	"S_COW3",
-	"S_COW4",
-
-	// Red Birdie in Bubble
-	"S_RBIRD1",
-	"S_RBIRD2",
-	"S_RBIRD3",
+	// Flicky-sized bubble
+	"S_FLICKY_BUBBLE",
+
+	// Bluebird
+	"S_FLICKY_01_OUT",
+	"S_FLICKY_01_FLAP1",
+	"S_FLICKY_01_FLAP2",
+	"S_FLICKY_01_FLAP3",
+
+	// Rabbit
+	"S_FLICKY_02_OUT",
+	"S_FLICKY_02_AIM",
+	"S_FLICKY_02_HOP",
+	"S_FLICKY_02_UP",
+	"S_FLICKY_02_DOWN",
+
+	// Chicken
+	"S_FLICKY_03_OUT",
+	"S_FLICKY_03_AIM",
+	"S_FLICKY_03_HOP",
+	"S_FLICKY_03_UP",
+	"S_FLICKY_03_FLAP1",
+	"S_FLICKY_03_FLAP2",
+
+	// Seal
+	"S_FLICKY_04_OUT",
+	"S_FLICKY_04_AIM",
+	"S_FLICKY_04_HOP",
+	"S_FLICKY_04_UP",
+	"S_FLICKY_04_DOWN",
+	"S_FLICKY_04_SWIM1",
+	"S_FLICKY_04_SWIM2",
+	"S_FLICKY_04_SWIM3",
+	"S_FLICKY_04_SWIM4",
+
+	// Pig
+	"S_FLICKY_05_OUT",
+	"S_FLICKY_05_AIM",
+	"S_FLICKY_05_HOP",
+	"S_FLICKY_05_UP",
+	"S_FLICKY_05_DOWN",
+
+	// Chipmunk
+	"S_FLICKY_06_OUT",
+	"S_FLICKY_06_AIM",
+	"S_FLICKY_06_HOP",
+	"S_FLICKY_06_UP",
+	"S_FLICKY_06_DOWN",
+
+	// Penguin
+	"S_FLICKY_07_OUT",
+	"S_FLICKY_07_AIML",
+	"S_FLICKY_07_HOPL",
+	"S_FLICKY_07_UPL",
+	"S_FLICKY_07_DOWNL",
+	"S_FLICKY_07_AIMR",
+	"S_FLICKY_07_HOPR",
+	"S_FLICKY_07_UPR",
+	"S_FLICKY_07_DOWNR",
+	"S_FLICKY_07_SWIM1",
+	"S_FLICKY_07_SWIM2",
+	"S_FLICKY_07_SWIM3",
+
+	// Fish
+	"S_FLICKY_08_OUT",
+	"S_FLICKY_08_AIM",
+	"S_FLICKY_08_HOP",
+	"S_FLICKY_08_FLAP1",
+	"S_FLICKY_08_FLAP2",
+	"S_FLICKY_08_FLAP3",
+	"S_FLICKY_08_FLAP4",
+	"S_FLICKY_08_SWIM1",
+	"S_FLICKY_08_SWIM2",
+	"S_FLICKY_08_SWIM3",
+	"S_FLICKY_08_SWIM4",
+
+	// Ram
+	"S_FLICKY_09_OUT",
+	"S_FLICKY_09_AIM",
+	"S_FLICKY_09_HOP",
+	"S_FLICKY_09_UP",
+	"S_FLICKY_09_DOWN",
+
+	// Puffin
+	"S_FLICKY_10_OUT",
+	"S_FLICKY_10_FLAP1",
+	"S_FLICKY_10_FLAP2",
+
+	// Cow
+	"S_FLICKY_11_OUT",
+	"S_FLICKY_11_AIM",
+	"S_FLICKY_11_RUN1",
+	"S_FLICKY_11_RUN2",
+	"S_FLICKY_11_RUN3",
+
+	// Rat
+	"S_FLICKY_12_OUT",
+	"S_FLICKY_12_AIM",
+	"S_FLICKY_12_RUN1",
+	"S_FLICKY_12_RUN2",
+	"S_FLICKY_12_RUN3",
+
+	// Bear
+	"S_FLICKY_13_OUT",
+	"S_FLICKY_13_AIM",
+	"S_FLICKY_13_HOP",
+	"S_FLICKY_13_UP",
+	"S_FLICKY_13_DOWN",
+
+	// Dove
+	"S_FLICKY_14_OUT",
+	"S_FLICKY_14_FLAP1",
+	"S_FLICKY_14_FLAP2",
+	"S_FLICKY_14_FLAP3",
+
+	// Cat
+	"S_FLICKY_15_OUT",
+	"S_FLICKY_15_AIM",
+	"S_FLICKY_15_HOP",
+	"S_FLICKY_15_UP",
+	"S_FLICKY_15_DOWN",
+
+	// Canary
+	"S_FLICKY_16_OUT",
+	"S_FLICKY_16_FLAP1",
+	"S_FLICKY_16_FLAP2",
+	"S_FLICKY_16_FLAP3",
 
 	"S_YELLOWSPRING",
 	"S_YELLOWSPRING2",
@@ -5566,6 +5876,20 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 
 	"S_WATERZAP",
 
+	// Spindash dust
+	"S_SPINDUST1",
+	"S_SPINDUST2",
+	"S_SPINDUST3",
+	"S_SPINDUST4",
+	"S_SPINDUST_BUBBLE1",
+	"S_SPINDUST_BUBBLE2",
+	"S_SPINDUST_BUBBLE3",
+	"S_SPINDUST_BUBBLE4",
+	"S_SPINDUST_FIRE1",
+	"S_SPINDUST_FIRE2",
+	"S_SPINDUST_FIRE3",
+	"S_SPINDUST_FIRE4",
+
 	"S_FOG1",
 	"S_FOG2",
 	"S_FOG3",
@@ -5938,6 +6262,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_NIGHTOPIANHELPER6",
 	"S_NIGHTOPIANHELPER7",
 	"S_NIGHTOPIANHELPER8",
+	"S_NIGHTOPIANHELPER9",
 
 	"S_CRUMBLE1",
 	"S_CRUMBLE2",
@@ -5961,10 +6286,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_SPRK16",
 
 	// Robot Explosion
+	"S_XPLD_FLICKY",
 	"S_XPLD1",
 	"S_XPLD2",
-	"S_XPLD3",
-	"S_XPLD4",
+	"S_XPLD_EGGTRAP",
 
 	// Underwater Explosion
 	"S_WPLD1",
@@ -6164,6 +6489,9 @@ static const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for s
 	"MT_RECYCLER_BOX",
 	"MT_SCORE1K_BOX",
 	"MT_SCORE10K_BOX",
+	"MT_FLAMEAURA_BOX",
+	"MT_BUBBLEWRAP_BOX",
+	"MT_THUNDERCOIN_BOX",
 
 	// Monitor boxes -- repeating (big) boxes
 	"MT_PITY_GOLDBOX",
@@ -6176,6 +6504,9 @@ static const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for s
 	"MT_INVULN_GOLDBOX",
 	"MT_EGGMAN_GOLDBOX",
 	"MT_GRAVITY_GOLDBOX",
+	"MT_FLAMEAURA_GOLDBOX",
+	"MT_BUBBLEWRAP_GOLDBOX",
+	"MT_THUNDERCOIN_GOLDBOX",
 
 	// Monitor boxes -- special
 	"MT_RING_REDBOX",
@@ -6198,6 +6529,9 @@ static const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for s
 	"MT_RECYCLER_ICON",
 	"MT_SCORE1K_ICON",
 	"MT_SCORE10K_ICON",
+	"MT_FLAMEAURA_ICON",
+	"MT_BUBBLEWRAP_ICON",
+	"MT_THUNDERCOIN_ICON",
 
 	// Projectiles
 	"MT_ROCKET",
@@ -6350,22 +6684,36 @@ static const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for s
 	"MT_EGGSTATUE2",
 
 	// Powerup Indicators
-	"MT_GREENORB", // Elemental shield mobj
-	"MT_YELLOWORB", // Attract shield mobj
-	"MT_BLUEORB", // Force shield mobj
-	"MT_BLACKORB", // Armageddon shield mobj
-	"MT_WHITEORB", // Whirlwind shield mobj
-	"MT_PITYORB", // Pity shield mobj
-	"MT_IVSP", // invincibility sparkles
+	"MT_ELEMENTAL_ORB", // Elemental shield mobj
+	"MT_ATTRACT_ORB", // Attract shield mobj
+	"MT_FORCE_ORB", // Force shield mobj
+	"MT_ARMAGEDDON_ORB", // Armageddon shield mobj
+	"MT_WHIRLWIND_ORB", // Whirlwind shield mobj
+	"MT_PITY_ORB", // Pity shield mobj
+	"MT_FLAMEAURA_ORB", // Flame shield mobj
+	"MT_BUBBLEWRAP_ORB", // Bubble shield mobj
+	"MT_THUNDERCOIN_ORB", // Thunder shield mobj
+	"MT_THUNDERCOIN_SPARK", // Thunder spark
+	"MT_IVSP", // Invincibility sparkles
 	"MT_SUPERSPARK", // Super Sonic Spark
 
-	// Freed Animals
-	"MT_BIRD", // Birdie freed!
-	"MT_BUNNY", // Bunny freed!
-	"MT_MOUSE", // Mouse
-	"MT_CHICKEN", // Chicken
-	"MT_COW", // Cow
-	"MT_REDBIRD", // Red Birdie in Bubble
+	// Flickies
+	"MT_FLICKY_01", // Bluebird
+	"MT_FLICKY_02", // Rabbit
+	"MT_FLICKY_03", // Chicken
+	"MT_FLICKY_04", // Seal
+	"MT_FLICKY_05", // Pig
+	"MT_FLICKY_06", // Chipmunk
+	"MT_FLICKY_07", // Penguin
+	"MT_FLICKY_08", // Fish
+	"MT_FLICKY_09", // Ram
+	"MT_FLICKY_10", // Puffin
+	"MT_FLICKY_11", // Cow
+	"MT_FLICKY_12", // Rat
+	"MT_FLICKY_13", // Bear
+	"MT_FLICKY_14", // Dove
+	"MT_FLICKY_15", // Cat
+	"MT_FLICKY_16", // Canary
 
 	// Environmental Effects
 	"MT_RAIN", // Rain
@@ -6376,6 +6724,7 @@ static const char *const MOBJTYPE_LIST[] = {  // array length left dynamic for s
 	"MT_MEDIUMBUBBLE", // medium bubble
 	"MT_EXTRALARGEBUBBLE", // extra large bubble
 	"MT_WATERZAP",
+	"MT_SPINDUST", // Spindash dust
 	"MT_TFOG",
 	"MT_SEED",
 	"MT_PARTICLE",
@@ -6544,35 +6893,36 @@ static const char *const MOBJFLAG_LIST[] = {
 
 // \tMF2_(\S+).*// (.+) --> \t"\1", // \2
 static const char *const MOBJFLAG2_LIST[] = {
-	"AXIS",			// It's a NiGHTS axis! (For faster checking)
-	"TWOD",			// Moves like it's in a 2D level
-	"DONTRESPAWN",	// Don't respawn this object!
-	"DONTDRAW",		// Don't generate a vissprite
-	"AUTOMATIC",	// Thrown ring has automatic properties
-	"RAILRING",		// Thrown ring has rail properties
-	"BOUNCERING",	// Thrown ring has bounce properties
-	"EXPLOSION",	// Thrown ring has explosive properties
-	"SCATTER",		// Thrown ring has scatter properties
-	"BEYONDTHEGRAVE",// Source of this missile has died and has since respawned.
-	"SLIDEPUSH",	// MF_PUSHABLE that pushes continuously.
-	"CLASSICPUSH",	// Drops straight down when object has negative Z.
-	"STANDONME",	// While not pushable, stand on me anyway.
-	"INFLOAT",		// Floating to a height for a move, don't auto float to target's height.
-	"DEBRIS",		// Splash ring from explosion ring
-	"NIGHTSPULL",	// Attracted from a paraloop
-	"JUSTATTACKED",	// can be pushed by other moving mobjs
-	"FIRING",		// turret fire
-	"SUPERFIRE",	// Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it.
-	"SHADOW",		// Fuzzy draw, makes targeting harder.
-	"STRONGBOX",	// Flag used for "strong" random monitors.
-	"OBJECTFLIP",	// Flag for objects that always have flipped gravity.
-	"SKULLFLY",		// Special handling: skull in flight.
-	"FRET",			// Flashing from a previous hit
-	"BOSSNOTRAP",	// No Egg Trap after boss
-	"BOSSFLEE",		// Boss is fleeing!
-	"BOSSDEAD",		// Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.)
-	"AMBUSH",       // Alternate behaviour typically set by MTF_AMBUSH
-	"LINKDRAW",     // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
+	"AXIS",			  // It's a NiGHTS axis! (For faster checking)
+	"TWOD",			  // Moves like it's in a 2D level
+	"DONTRESPAWN",	  // Don't respawn this object!
+	"DONTDRAW",		  // Don't generate a vissprite
+	"AUTOMATIC",	  // Thrown ring has automatic properties
+	"RAILRING",		  // Thrown ring has rail properties
+	"BOUNCERING",	  // Thrown ring has bounce properties
+	"EXPLOSION",	  // Thrown ring has explosive properties
+	"SCATTER",		  // Thrown ring has scatter properties
+	"BEYONDTHEGRAVE", // Source of this missile has died and has since respawned.
+	"SLIDEPUSH",	  // MF_PUSHABLE that pushes continuously.
+	"CLASSICPUSH",	  // Drops straight down when object has negative Z.
+	"STANDONME",	  // While not pushable, stand on me anyway.
+	"INFLOAT",		  // Floating to a height for a move, don't auto float to target's height.
+	"DEBRIS",		  // Splash ring from explosion ring
+	"NIGHTSPULL",	  // Attracted from a paraloop
+	"JUSTATTACKED",	  // can be pushed by other moving mobjs
+	"FIRING",		  // turret fire
+	"SUPERFIRE",	  // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it.
+	"SHADOW",		  // Fuzzy draw, makes targeting harder.
+	"STRONGBOX",	  // Flag used for "strong" random monitors.
+	"OBJECTFLIP",	  // Flag for objects that always have flipped gravity.
+	"SKULLFLY",		  // Special handling: skull in flight.
+	"FRET",			  // Flashing from a previous hit
+	"BOSSNOTRAP",	  // No Egg Trap after boss
+	"BOSSFLEE",		  // Boss is fleeing!
+	"BOSSDEAD",		  // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.)
+	"AMBUSH",         // Alternate behaviour typically set by MTF_AMBUSH
+	"LINKDRAW",       // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
+	"SHIELD",         // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
 	NULL
 };
 
@@ -6654,6 +7004,9 @@ static const char *const PLAYERFLAG_LIST[] = {
 	/*** misc ***/
 	"FORCESTRAFE", // Translate turn inputs into strafe inputs
 	"ANALOGMODE", // Analog mode?
+	"CANCARRY", // Can carry?
+	"SHIELDABILITY", // Thokked with shield ability
+	"FORCEJUMPDAMAGE", // Force jump damage
 
 	NULL // stop loop here.
 };
@@ -6998,20 +7351,27 @@ struct {
 	{"PRECIP_STORM_NOSTRIKES",PRECIP_STORM_NOSTRIKES},
 
 	// Shields
-	// These ones use the lower 8 bits
 	{"SH_NONE",SH_NONE},
-	{"SH_JUMP",SH_JUMP},
+	// Shield flags
+	{"SH_PROTECTFIRE",SH_PROTECTFIRE},
+	{"SH_PROTECTWATER",SH_PROTECTWATER},
+	{"SH_PROTECTELECTRIC",SH_PROTECTELECTRIC},
+	// Indivisible shields
+	{"SH_PITY",SH_PITY},
+	{"SH_WHIRLWIND",SH_WHIRLWIND},
+	{"SH_ARMAGEDDON",SH_ARMAGEDDON},
+	// normal shields that use flags
 	{"SH_ATTRACT",SH_ATTRACT},
 	{"SH_ELEMENTAL",SH_ELEMENTAL},
-	{"SH_BOMB",SH_BOMB},
+	// Sonic 3 shields
+	{"SH_FLAMEAURA",SH_FLAMEAURA},
 	{"SH_BUBBLEWRAP",SH_BUBBLEWRAP},
 	{"SH_THUNDERCOIN",SH_THUNDERCOIN},
-	{"SH_FLAMEAURA",SH_FLAMEAURA},
-	{"SH_PITY",SH_PITY},
-	// These ones are special and use the upper bits
-	{"SH_FIREFLOWER",SH_FIREFLOWER}, // Lower bits are a normal shield stacked on top of the fire flower
-	{"SH_FORCE",SH_FORCE}, // Lower bits are how many hits left, 0 is the last hit
-	// Stack masks
+	// The force shield uses the lower 8 bits to count how many extra hits are left.
+	{"SH_FORCE",SH_FORCE},
+	{"SH_FORCEHP",SH_FORCEHP}, // to be used as a bitmask only
+	// Mostly for use with Mario mode.
+	{"SH_FIREFLOWER", SH_FIREFLOWER},
 	{"SH_STACK",SH_STACK},
 	{"SH_NOSTACK",SH_NOSTACK},
 
@@ -7045,6 +7405,7 @@ struct {
 	{"SF_STOMPDAMAGE",SF_STOMPDAMAGE},
 	{"SF_MARIODAMAGE",SF_MARIODAMAGE},
 	{"SF_MACHINE",SF_MACHINE},
+	{"SF_NOSPINDASHDUST",SF_NOSPINDASHDUST},
 
 	// Character abilities!
 	// Primary
@@ -7217,6 +7578,11 @@ struct {
 	{"FF_COLORMAPONLY",FF_COLORMAPONLY},       ///< Only copy the colormap, not the lightlevel
 	{"FF_GOOWATER",FF_GOOWATER},               ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop.
 
+#ifdef HAVE_LUA_SEGS
+	// Node flags
+	{"NF_SUBSECTOR",NF_SUBSECTOR}, // Indicate a leaf.
+#endif
+
 	// Angles
 	{"ANG1",ANG1},
 	{"ANG2",ANG2},
@@ -7362,7 +7728,7 @@ static mobjtype_t get_mobjtype(const char *word)
 		if (fastcmp(word, MOBJTYPE_LIST[i]+3))
 			return i;
 	deh_warning("Couldn't find mobjtype named 'MT_%s'",word);
-	return MT_BLUECRAWLA;
+	return MT_NULL;
 }
 
 static statenum_t get_state(const char *word)
diff --git a/src/doomdef.h b/src/doomdef.h
index f599b5f81f22515d5b88d248c0c38da7c9d656e3..83576a12c12283a965d191a21538ccc5cb833fb7 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -407,6 +407,7 @@ void M_StartupLocale(void);
 extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL;
 char *va(const char *format, ...) FUNCPRINTF;
 char *M_GetToken(const char *inputString);
+void M_UnGetToken(void);
 char *sizeu1(size_t num);
 char *sizeu2(size_t num);
 char *sizeu3(size_t num);
diff --git a/src/doomstat.h b/src/doomstat.h
index 8072a15528f56a23727da9a6d7b32bcf86db4166..f1b7d2169516c2020ecd20fdd0b12cae7a356234 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -241,6 +241,10 @@ typedef struct
 	UINT8 levelflags;     ///< LF_flags:  merged eight booleans into one UINT8 for space, see below
 	UINT8 menuflags;      ///< LF2_flags: options that affect record attack / nights mode menus
 
+	// Freed animals stuff.
+	UINT8 numFlickies;     ///< Internal. For freed flicky support.
+	mobjtype_t *flickies;  ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful.
+
 	// NiGHTS stuff.
 	UINT8 numGradedMares;   ///< Internal. For grade support.
 	nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful.
diff --git a/src/g_game.c b/src/g_game.c
index c5488e0b7d17476b3ad8f24c6c3e86089745c529..5e04af496327329e2f54c00cec4912beb5535b35 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -4728,7 +4728,7 @@ void G_BeginRecording(void)
 	// Don't do it.
 	WRITEFIXED(demo_p, player->jumpfactor);
 
-	// Save netvar data (SONICCD, etc)
+	// Save netvar data
 	CV_SaveNetVars(&demo_p);
 
 	memset(&oldcmd,0,sizeof(oldcmd));
diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c
index 9e5d92e0ba14344e6cd521f91951eedb07af8d84..35a07c5270150b42fdd093fa20dec2edd40ea030 100644
--- a/src/hardware/hw_light.c
+++ b/src/hardware/hw_light.c
@@ -271,6 +271,9 @@ light_t *t_lspr[NUMSPRITES] =
 	&lspr[NOLIGHT],     // SPR_TVRC
 	&lspr[NOLIGHT],     // SPR_TV1K
 	&lspr[NOLIGHT],     // SPR_TVTK
+	&lspr[NOLIGHT],     // SPR_TVFL
+	&lspr[NOLIGHT],     // SPR_TVBB
+	&lspr[NOLIGHT],     // SPR_TVZP
 
 	// Projectiles
 	&lspr[NOLIGHT],     // SPR_MISL
@@ -359,18 +362,32 @@ light_t *t_lspr[NUMSPRITES] =
 	&lspr[NOLIGHT],     // SPR_ELEM
 	&lspr[NOLIGHT],     // SPR_FORC
 	&lspr[NOLIGHT],     // SPR_PITY
+	&lspr[NOLIGHT],     // SPR_FIRS
+	&lspr[NOLIGHT],     // SPR_BUBS
+	&lspr[NOLIGHT],     // SPR_ZAPS
 	&lspr[INVINCIBLE_L],     // SPR_IVSP
 	&lspr[SUPERSPARK_L],     // SPR_SSPK
 
 	&lspr[NOLIGHT],     // SPR_GOAL
 
-	// Freed Animals
-	&lspr[NOLIGHT],     // SPR_BIRD
-	&lspr[NOLIGHT],     // SPR_BUNY
-	&lspr[NOLIGHT],     // SPR_MOUS
-	&lspr[NOLIGHT],     // SPR_CHIC
-	&lspr[NOLIGHT],     // SPR_COWZ
-	&lspr[NOLIGHT],     // SPR_RBRD
+	// Flickies
+	&lspr[NOLIGHT],     // SPR_FBUB
+	&lspr[NOLIGHT],     // SPR_FL01
+	&lspr[NOLIGHT],     // SPR_FL02
+	&lspr[NOLIGHT],     // SPR_FL03
+	&lspr[NOLIGHT],     // SPR_FL04
+	&lspr[NOLIGHT],     // SPR_FL05
+	&lspr[NOLIGHT],     // SPR_FL06
+	&lspr[NOLIGHT],     // SPR_FL07
+	&lspr[NOLIGHT],     // SPR_FL08
+	&lspr[NOLIGHT],     // SPR_FL09
+	&lspr[NOLIGHT],     // SPR_FL10
+	&lspr[NOLIGHT],     // SPR_FL11
+	&lspr[NOLIGHT],     // SPR_FL12
+	&lspr[NOLIGHT],     // SPR_FL13
+	&lspr[NOLIGHT],     // SPR_FL14
+	&lspr[NOLIGHT],     // SPR_FL15
+	&lspr[NOLIGHT],     // SPR_FL16
 
 	// Springs
 	&lspr[NOLIGHT],     // SPR_SPRY
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 270229ad07d888153fbb9b40660f3baa8ee71bb6..7bc12ba75db5ceb77e493d32aa9e5f273d9f5415 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -1558,6 +1558,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 
 	if (gr_backsector)
 	{
+		INT32 gr_toptexture, gr_bottomtexture;
 		// two sided line
 		if (gr_backsector->heightsec != -1)
 		{
@@ -1608,19 +1609,22 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 #endif
 		}
 
+		gr_toptexture = R_GetTextureNum(gr_sidedef->toptexture);
+		gr_bottomtexture = R_GetTextureNum(gr_sidedef->bottomtexture);
+
 		// check TOP TEXTURE
 		if ((
 #ifdef ESLOPE
 			worldhighslope < worldtopslope ||
 #endif
             worldhigh < worldtop
-            ) && texturetranslation[gr_sidedef->toptexture])
+            ) && gr_toptexture)
 		{
 			if (drawtextured)
 			{
 				fixed_t texturevpegtop; // top
 
-				grTex = HWR_GetTexture(texturetranslation[gr_sidedef->toptexture]);
+				grTex = HWR_GetTexture(gr_toptexture);
 
 				// PEGGING
 				if (gr_linedef->flags & ML_DONTPEGTOP)
@@ -1638,7 +1642,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				texturevpegtop += gr_sidedef->rowoffset;
 
 				// This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway
-				texturevpegtop %= SHORT(textures[texturetranslation[gr_sidedef->toptexture]]->height)<<FRACBITS;
+				texturevpegtop %= SHORT(textures[gr_toptexture]->height)<<FRACBITS;
 
 				wallVerts[3].t = wallVerts[2].t = texturevpegtop * grTex->scaleY;
 				wallVerts[0].t = wallVerts[1].t = (texturevpegtop + gr_frontsector->ceilingheight - gr_backsector->ceilingheight) * grTex->scaleY;
@@ -1683,9 +1687,9 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 #endif
 
 			if (gr_frontsector->numlights)
-				HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[gr_sidedef->toptexture], &Surf, FF_CUTSOLIDS);
+				HWR_SplitWall(gr_frontsector, wallVerts, gr_toptexture, &Surf, FF_CUTSOLIDS);
 			else if (grTex->mipmap.flags & TF_TRANSPARENT)
-				HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[gr_sidedef->toptexture], PF_Environment, false, lightnum, colormap);
+				HWR_AddTransparentWall(wallVerts, &Surf, gr_toptexture, PF_Environment, false, lightnum, colormap);
 			else
 				HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
 		}
@@ -1695,13 +1699,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 #ifdef ESLOPE
 			worldlowslope > worldbottomslope ||
 #endif
-            worldlow > worldbottom) && texturetranslation[gr_sidedef->bottomtexture]) //only if VISIBLE!!!
+            worldlow > worldbottom) && gr_bottomtexture) //only if VISIBLE!!!
 		{
 			if (drawtextured)
 			{
 				fixed_t texturevpegbottom = 0; // bottom
 
-				grTex = HWR_GetTexture(texturetranslation[gr_sidedef->bottomtexture]);
+				grTex = HWR_GetTexture(gr_bottomtexture);
 
 				// PEGGING
 #ifdef ESLOPE
@@ -1721,7 +1725,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				texturevpegbottom += gr_sidedef->rowoffset;
 
 				// This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway
-				texturevpegbottom %= SHORT(textures[texturetranslation[gr_sidedef->bottomtexture]]->height)<<FRACBITS;
+				texturevpegbottom %= SHORT(textures[gr_bottomtexture]->height)<<FRACBITS;
 
 				wallVerts[3].t = wallVerts[2].t = texturevpegbottom * grTex->scaleY;
 				wallVerts[0].t = wallVerts[1].t = (texturevpegbottom + gr_backsector->floorheight - gr_frontsector->floorheight) * grTex->scaleY;
@@ -1766,13 +1770,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 #endif
 
 			if (gr_frontsector->numlights)
-				HWR_SplitWall(gr_frontsector, wallVerts, texturetranslation[gr_sidedef->bottomtexture], &Surf, FF_CUTSOLIDS);
+				HWR_SplitWall(gr_frontsector, wallVerts, gr_bottomtexture, &Surf, FF_CUTSOLIDS);
 			else if (grTex->mipmap.flags & TF_TRANSPARENT)
-				HWR_AddTransparentWall(wallVerts, &Surf, texturetranslation[gr_sidedef->bottomtexture], PF_Environment, false, lightnum, colormap);
+				HWR_AddTransparentWall(wallVerts, &Surf, gr_bottomtexture, PF_Environment, false, lightnum, colormap);
 			else
 				HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap);
 		}
-		gr_midtexture = texturetranslation[gr_sidedef->midtexture];
+		gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture);
 		if (gr_midtexture)
 		{
 			FBITFIELD blendmode;
@@ -2134,7 +2138,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 	else
 	{
 		// Single sided line... Deal only with the middletexture (if one exists)
-		gr_midtexture = texturetranslation[gr_sidedef->midtexture];
+		gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture);
 		if (gr_midtexture)
 		{
 			if (drawtextured)
@@ -2232,13 +2236,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
 					continue;
 
-				texnum = texturetranslation[sides[rover->master->sidenum[0]].midtexture];
+				texnum = R_GetTextureNum(sides[rover->master->sidenum[0]].midtexture);
 
 				if (rover->master->flags & ML_TFERLINE)
 				{
 					size_t linenum = gr_curline->linedef-gr_backsector->lines[0];
 					newline = rover->master->frontsector->lines[0] + linenum;
-					texnum = texturetranslation[sides[newline->sidenum[0]].midtexture];
+					texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
 				}
 
 #ifdef ESLOPE
@@ -2366,13 +2370,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 				if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
 					continue;
 
-				texnum = texturetranslation[sides[rover->master->sidenum[0]].midtexture];
+				texnum = R_GetTextureNum(sides[rover->master->sidenum[0]].midtexture);
 
 				if (rover->master->flags & ML_TFERLINE)
 				{
 					size_t linenum = gr_curline->linedef-gr_backsector->lines[0];
 					newline = rover->master->frontsector->lines[0] + linenum;
-					texnum = texturetranslation[sides[newline->sidenum[0]].midtexture];
+					texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
 				}
 #ifdef ESLOPE //backsides
 				h  = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight;
@@ -4519,8 +4523,8 @@ static void HWR_SortVisSprites(void)
 	gr_vissprite_t *ds, *dsprev, *dsnext, *dsfirst;
 	gr_vissprite_t *best = NULL;
 	gr_vissprite_t unsorted;
-	float bestdist;
-	INT32 bestdispoffset;
+	float bestdist = 0.0f;
+	INT32 bestdispoffset = 0;
 
 	if (!gr_visspritecount)
 		return;
diff --git a/src/hu_stuff.c b/src/hu_stuff.c
index 5878bbf5ef78b4ceebd3818592fd79dc0bc0274c..c8cd8df0d8e4db6ee7d1a8d1e26fdbb0d1ac4e52 100644
--- a/src/hu_stuff.c
+++ b/src/hu_stuff.c
@@ -790,6 +790,14 @@ boolean HU_Responder(event_t *ev)
 	}
 	else // if chat_on
 	{
+		// Ignore modifier keys
+		// Note that we do this here so users can still set
+		// their chat keys to one of these, if they so desire.
+		if (ev->data1 == KEY_LSHIFT || ev->data1 == KEY_RSHIFT
+		 || ev->data1 == KEY_LCTRL || ev->data1 == KEY_RCTRL
+		 || ev->data1 == KEY_LALT || ev->data1 == KEY_RALT)
+			return true;
+
 		c = (UINT8)ev->data1;
 
 		// use console translations
diff --git a/src/info.c b/src/info.c
index d9567b37fe123d87461879bed67e13b9715a4496..cede31861e4b1b6b14221f7af0eded5dbfdd294a 100644
--- a/src/info.c
+++ b/src/info.c
@@ -159,6 +159,9 @@ char sprnames[NUMSPRITES + 1][5] =
 	"TVRC", // ReCycler
 	"TV1K", // 1,000 points  (1 K)
 	"TVTK", // 10,000 points (Ten K)
+	"TVFL", // FLame shield
+	"TVBB", // BuBble shield
+	"TVZP", // Thunder shield (ZaP)
 
 	// Projectiles
 	"MISL",
@@ -243,18 +246,32 @@ char sprnames[NUMSPRITES + 1][5] =
 	"ELEM", // Elemental Shield Orb and Fire
 	"FORC", // Force Shield Orb
 	"PITY", // Pity Shield Orb
+	"FIRS", // Flame Shield Orb
+	"BUBS", // Bubble Shield Orb
+	"ZAPS", // Thunder Shield Orb
 	"IVSP", // invincibility sparkles
 	"SSPK", // Super Sonic Spark
 
 	"GOAL", // Special Stage goal (here because lol NiGHTS)
 
-	// Freed Animals
-	"BIRD", // Birdie freed!
-	"BUNY", // Bunny freed!
-	"MOUS", // Mouse
-	"CHIC", // Chicken
-	"COWZ", // Cow
-	"RBRD", // Red Birdie in Bubble
+	// Flickies
+	"FBUB", // Flicky-sized bubble
+	"FL01", // Bluebird
+	"FL02", // Rabbit
+	"FL03", // Chicken
+	"FL04", // Seal
+	"FL05", // Pig
+	"FL06", // Chipmunk
+	"FL07", // Penguin
+	"FL08", // Fish
+	"FL09", // Ram
+	"FL10", // Puffin
+	"FL11", // Cow
+	"FL12", // Rat
+	"FL13", // Bear
+	"FL14", // Dove
+	"FL15", // Cat
+	"FL16", // Canary
 
 	// Springs
 	"SPRY", // yellow spring
@@ -274,6 +291,8 @@ char sprnames[NUMSPRITES + 1][5] =
 	"SMOK",
 	"BUBL", // Bubble
 	"WZAP",
+	"DUST", // Spindash dust
+	"FPRT", // Spindash dust (flame)
 	"TFOG", // Teleport Fog
 	"SEED", // Sonic CD flower seed
 	"PRTL", // Particle (for fans, etc.)
@@ -1532,7 +1551,7 @@ state_t states[NUMSTATES] =
 	{SPR_SPIK, 6, 1, {A_RotateSpikeBall}, 0, 0, S_SPIKEBALL8}, // S_SPIKEBALL7
 	{SPR_SPIK, 7, 1, {A_RotateSpikeBall}, 0, 0, S_SPIKEBALL1}, // S_SPIKEBALL8
 
-	// Red Shield's Spawn
+	// Elemental 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
@@ -1606,6 +1625,9 @@ state_t states[NUMSTATES] =
 	{SPR_TVRC, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_RECYCLER_BOX
 	{SPR_TV1K, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_SCORE1K_BOX
 	{SPR_TVTK, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_SCORE10K_BOX
+	{SPR_TVFL, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_FLAMEAURA_BOX
+	{SPR_TVBB, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_BUBBLEWRAP_BOX
+	{SPR_TVZP, 0, 2, {NULL}, 0, 0, S_BOX_FLICKER}, // S_THUNDERCOIN_BOX
 
 	// Gold Repeat Monitor States (one per box)
 	{SPR_TVPI, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_PITY_GOLDBOX
@@ -1618,6 +1640,9 @@ state_t states[NUMSTATES] =
 	{SPR_TVIV, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_INVULN_GOLDBOX
 	{SPR_TVEG, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_EGGMAN_GOLDBOX
 	{SPR_TVGV, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_GRAVITY_GOLDBOX
+	{SPR_TVFL, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_FLAMEAURA_GOLDBOX
+	{SPR_TVBB, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_BUBBLEWRAP_GOLDBOX
+	{SPR_TVZP, 1, 2, {A_GoldMonitorSparkle}, 0, 0, S_GOLDBOX_FLICKER}, // S_THUNDERCOIN_GOLDBOX
 
 	// Team Ring Boxes (these are special)
 	{SPR_TRRI, 0, 2, {NULL}, 0, 0, S_RING_REDBOX2}, // S_RING_REDBOX1
@@ -1641,7 +1666,7 @@ state_t states[NUMSTATES] =
 	{SPR_TVAT, 2, 18, {A_RingShield},0, 0, S_NULL}, // S_ATTRACT_ICON2
 
 	{SPR_TVFO, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FORCE_ICON2}, // S_FORCE_ICON1
-	{SPR_TVFO, 2, 18, {A_ForceShield}, 0, 0, S_NULL}, // S_FORCE_ICON2
+	{SPR_TVFO, 2, 18, {A_ForceShield}, 1, 0, S_NULL}, // S_FORCE_ICON2
 
 	{SPR_TVAR, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_ARMAGEDDON_ICON2}, // S_ARMAGEDDON_ICON1
 	{SPR_TVAR, 2, 18, {A_BombShield}, 0, 0, S_NULL}, // S_ARMAGEDDON_ICON2
@@ -1679,6 +1704,15 @@ state_t states[NUMSTATES] =
 	{SPR_TVTK, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_SCORE10K_ICON2}, // S_SCORE10K_ICON1
 	{SPR_TVTK, 2, 18, {A_AwardScore}, 0, 0, S_NULL}, // S_SCORE10K_ICON2
 
+	{SPR_TVFL, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_FLAMEAURA_ICON2}, // S_FLAMEAURA_ICON1
+	{SPR_TVFL, 2, 18, {A_FlameShield}, 0, 0, S_NULL}, // S_FLAMEAURA_ICON2
+
+	{SPR_TVBB, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_BUBBLEWRAP_ICON2}, // S_BUBBLEWRAP_ICON1
+	{SPR_TVBB, 2, 18, {A_BubbleShield}, 0, 0, S_NULL}, // S_BUBBLERWAP_ICON2
+
+	{SPR_TVZP, FF_ANIMATE|2, 18, {NULL}, 3, 4, S_THUNDERCOIN_ICON2}, // S_THUNDERCOIN_ICON1
+	{SPR_TVZP, 2, 18, {A_ThunderShield}, 0, 0, S_NULL}, // S_THUNDERCOIN_ICON2
+
 	// ---
 
 	{SPR_MISL, FF_FULLBRIGHT, 1, {A_SmokeTrailer}, MT_SMOKE, 0, S_ROCKET}, // S_ROCKET
@@ -2059,6 +2093,8 @@ state_t states[NUMSTATES] =
 	{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_MAGN, FF_FULLBRIGHT|FF_TRANS10|12, 2, {NULL}, 0, 0, S_MAGN1 }, // S_MAGN13
+
 	{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
@@ -2081,6 +2117,8 @@ state_t states[NUMSTATES] =
 	{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_FORC, FF_TRANS50|20, -1, {NULL}, 0, 0, S_NULL}, // S_FORC21
+
 	{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
@@ -2094,14 +2132,20 @@ state_t states[NUMSTATES] =
 	{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_NULL,             0, 1, {NULL}, 0, 0, S_ELEM14}, // S_ELEM13
+	{SPR_ELEM, FF_TRANS50|11, 1, {NULL}, 0, 0, S_ELEM1 }, // S_ELEM14
+
+	{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_ELEM, FF_FULLBRIGHT|20, 1, {NULL}, 0, 0, S_ELEMF10}, // S_ELEMF9
+	{SPR_NULL, 0,                1, {NULL}, 0, 0, S_ELEMF1 }, // S_ELEMF10
 
 	{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
@@ -2114,6 +2158,84 @@ state_t states[NUMSTATES] =
 	{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
 
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40  , 2, {NULL}, 0, 0, S_FIRS2}, // S_FIRS1
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|1, 2, {NULL}, 0, 0, S_FIRS3}, // S_FIRS2
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|2, 2, {NULL}, 0, 0, S_FIRS4}, // S_FIRS3
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|3, 2, {NULL}, 0, 0, S_FIRS5}, // S_FIRS4
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|4, 2, {NULL}, 0, 0, S_FIRS6}, // S_FIRS5
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|5, 2, {NULL}, 0, 0, S_FIRS7}, // S_FIRS6
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|6, 2, {NULL}, 0, 0, S_FIRS8}, // S_FIRS7
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|7, 2, {NULL}, 0, 0, S_FIRS9}, // S_FIRS8
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|8, 2, {NULL}, 0, 0, S_FIRS1}, // S_FIRS9
+
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|18, 1, {NULL}, 0, 0, S_FIRS11}, // S_FIRS10
+	{SPR_NULL, 0,                           1, {NULL}, 0, 0, S_FIRS1 }, // S_FIRS11
+
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40| 9, 2, {NULL}, 0, 0, S_FIRSB2}, // S_FIRSB1
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|10, 2, {NULL}, 0, 0, S_FIRSB3}, // S_FIRSB2
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|11, 2, {NULL}, 0, 0, S_FIRSB4}, // S_FIRSB3
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|12, 2, {NULL}, 0, 0, S_FIRSB5}, // S_FIRSB4
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|13, 2, {NULL}, 0, 0, S_FIRSB6}, // S_FIRSB5
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|14, 2, {NULL}, 0, 0, S_FIRSB7}, // S_FIRSB6
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|15, 2, {NULL}, 0, 0, S_FIRSB8}, // S_FIRSB7
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|16, 2, {NULL}, 0, 0, S_FIRSB9}, // S_FIRSB8
+	{SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|17, 2, {NULL}, 0, 0, S_FIRSB1}, // S_FIRSB9
+
+	{SPR_NULL, 0,                           2, {NULL}, 0, 0, S_FIRSB1 }, // S_FIRSB10
+
+	{SPR_BUBS, FF_TRANS30  , 3, {NULL}, 0, 0, S_BUBS2}, // S_BUBS1
+	{SPR_BUBS, FF_TRANS30|1, 3, {NULL}, 0, 0, S_BUBS3}, // S_BUBS2
+	{SPR_BUBS, FF_TRANS30|2, 3, {NULL}, 0, 0, S_BUBS4}, // S_BUBS3
+	{SPR_BUBS, FF_TRANS30|3, 3, {NULL}, 0, 0, S_BUBS5}, // S_BUBS4
+	{SPR_BUBS, FF_TRANS30|4, 3, {NULL}, 0, 0, S_BUBS6}, // S_BUBS5
+	{SPR_BUBS, FF_TRANS30|5, 3, {NULL}, 0, 0, S_BUBS7}, // S_BUBS6
+	{SPR_BUBS, FF_TRANS30|6, 3, {NULL}, 0, 0, S_BUBS8}, // S_BUBS7
+	{SPR_BUBS, FF_TRANS30|7, 3, {NULL}, 0, 0, S_BUBS9}, // S_BUBS8
+	{SPR_BUBS, FF_TRANS30|8, 3, {NULL}, 0, 0, S_BUBS1}, // S_BUBS9
+
+	{SPR_NULL, 0,   3, {NULL}, 0, 0, S_BUBS1}, // S_BUBS10
+	{SPR_NULL, 0, 4*3, {NULL}, 0, 0, S_BUBS1}, // S_BUBS11
+
+	{SPR_BUBS, FF_TRANS30| 9, 3, {NULL}, 0, 0, S_BUBSB2}, // S_BUBSB1
+	{SPR_BUBS, FF_TRANS30|10, 3, {NULL}, 0, 0, S_BUBSB3}, // S_BUBSB2
+	{SPR_BUBS, FF_TRANS30|11, 3, {NULL}, 0, 0, S_BUBSB4}, // S_BUBSB3
+	{SPR_BUBS, FF_TRANS30|10, 3, {NULL}, 0, 0, S_BUBSB1}, // S_BUBSB4
+
+	{SPR_BUBS, FF_TRANS30|12, 3, {NULL}, 0, 0, S_BUBSB3}, // S_BUBSB5
+	{SPR_BUBS, FF_TRANS30|13, 3, {NULL}, 0, 0, S_BUBSB5}, // S_BUBSB6
+
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20   ,   2, {NULL}, 0, 0, S_ZAPS2 }, // S_ZAPS1
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 1,   2, {NULL}, 0, 0, S_ZAPS3 }, // S_ZAPS2
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 2,   2, {NULL}, 0, 0, S_ZAPS4 }, // S_ZAPS3
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 3,   2, {NULL}, 0, 0, S_ZAPS5 }, // S_ZAPS4
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 4,   2, {NULL}, 0, 0, S_ZAPS6 }, // S_ZAPS5
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 5,   2, {NULL}, 0, 0, S_ZAPS7 }, // S_ZAPS6
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 6,   2, {NULL}, 0, 0, S_ZAPS8 }, // S_ZAPS7
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 7,   2, {NULL}, 0, 0, S_ZAPS9 }, // S_ZAPS8
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 8,   2, {NULL}, 0, 0, S_ZAPS10}, // S_ZAPS9
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 9,   2, {NULL}, 0, 0, S_ZAPS11}, // S_ZAPS10
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|10,   2, {NULL}, 0, 0, S_ZAPS12}, // S_ZAPS11
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|11,   2, {NULL}, 0, 0, S_ZAPS13}, // S_ZAPS12
+	{SPR_NULL,                           0, 9*2, {NULL}, 0, 0, S_ZAPS14}, // S_ZAPS13
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 9,   2, {NULL}, 0, 0, S_ZAPS15}, // S_ZAPS14
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|10,   2, {NULL}, 0, 0, S_ZAPS16}, // S_ZAPS15
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20|11,   2, {NULL}, 0, 0, S_ZAPS1 }, // S_ZAPS16
+
+	{SPR_NULL,                           0, 12*2, {NULL}, 0, 0, S_ZAPSB2 }, // S_ZAPSB1
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 8,    2, {NULL}, 0, 0, S_ZAPSB3 }, // S_ZAPSB2
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 7,    2, {NULL}, 0, 0, S_ZAPSB4 }, // S_ZAPSB3
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 6,    2, {NULL}, 0, 0, S_ZAPSB5 }, // S_ZAPSB4
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 5,    2, {NULL}, 0, 0, S_ZAPSB6 }, // S_ZAPSB5
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 4,    2, {NULL}, 0, 0, S_ZAPSB7 }, // S_ZAPSB6
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 3,    2, {NULL}, 0, 0, S_ZAPSB8 }, // S_ZAPSB7
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 2,    2, {NULL}, 0, 0, S_ZAPSB9 }, // S_ZAPSB8
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20| 1,    2, {NULL}, 0, 0, S_ZAPSB10}, // S_ZAPSB9
+	{SPR_ZAPS, FF_FULLBRIGHT|FF_TRANS20   ,    2, {NULL}, 0, 0, S_ZAPSB11}, // S_ZAPSB10
+	{SPR_NULL,                           0, 15*2, {NULL}, 0, 0, S_ZAPSB2 }, // S_ZAPSB11
+
+	// Thunder spark
+	{SPR_SSPK, FF_ANIMATE, 18, {NULL}, 1, 2, S_NULL},   // S_THUNDERCOIN_SPARK
+
 	// Invincibility Sparkles
 	{SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL},   // S_IVSP
 
@@ -2124,43 +2246,133 @@ state_t states[NUMSTATES] =
 	{SPR_SSPK, 1, 2, {NULL}, 0, 0, S_SSPK5}, // S_SSPK4
 	{SPR_SSPK, 0, 2, {NULL}, 0, 0, S_NULL},  // S_SSPK5
 
-	// Freed Birdie
-	{SPR_BIRD, 0, 4, {NULL}, 0, 0, S_BIRD2},    // S_BIRD1
-	{SPR_BIRD, 0, 4, {A_Chase}, 0, 0, S_BIRD3}, // S_BIRD2
-	{SPR_BIRD, 1, 4, {A_Chase}, 0, 0, S_BIRD2}, // S_BIRD3
-
-	// Freed Bunny
-	{SPR_BUNY, 0, 4, {NULL}, 0, 0, S_BUNNY2},       // S_BUNNY1
-	{SPR_BUNY, 0, 64, {NULL}, 0, 0, S_BUNNY3},      // S_BUNNY2
-	{SPR_BUNY, 1, 2, {A_BunnyHop}, 6, 3, S_BUNNY4}, // S_BUNNY3
-	{SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY5},    // S_BUNNY4
-	{SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY6},    // S_BUNNY5
-	{SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY7},    // S_BUNNY6
-	{SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY8},    // S_BUNNY7
-	{SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY9},    // S_BUNNY8
-	{SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY10},   // S_BUNNY9
-	{SPR_BUNY, 1, 2, {A_Chase}, 0, 0, S_BUNNY2},    // S_BUNNY10
-
-	// Freed Mouse
-	{SPR_MOUS, 0, 2, {A_MouseThink}, 0, 0, S_MOUSE2}, // S_MOUSE1
-	{SPR_MOUS, 1, 2, {A_MouseThink}, 0, 0, S_MOUSE1}, // S_MOUSE2
-
-	// Freed Chicken
-	{SPR_CHIC, 0, 7, {A_Chase},        3, 0, S_CHICKENHOP},  // S_CHICKEN1
-	{SPR_CHIC, 0, 1, {A_BunnyHop},     4, 2, S_CHICKENFLY1}, // S_CHICKENHOP
-	{SPR_CHIC, 1, 2, {A_ChickenCheck}, 0, 0, S_CHICKENFLY2}, // S_CHICKENFLY1
-	{SPR_CHIC, 2, 2, {NULL},           0, 0, S_CHICKENFLY1}, // S_CHICKENFLY2
-
-	// Freed Cow
-	{SPR_COWZ, 0, 4, {A_Chase}, 3, 0, S_COW2}, // S_COW1
-	{SPR_COWZ, 1, 4, {A_Chase}, 3, 0, S_COW3}, // S_COW2
-	{SPR_COWZ, 2, 4, {A_Chase}, 3, 0, S_COW4}, // S_COW3
-	{SPR_COWZ, 3, 4, {A_Chase}, 3, 0, S_COW1}, // S_COW4
-
-	// Freed Birdie
-	{SPR_RBRD, 0, 4, {NULL}, 0, 0, S_RBIRD2},    // S_RBIRD1
-	{SPR_RBRD, 0, 4, {A_Chase}, 0, 0, S_RBIRD3}, // S_RBIRD2
-	{SPR_RBRD, 1, 4, {A_Chase}, 0, 0, S_RBIRD2}, // S_RBIRD3
+	// Flicky-sized bubble
+	{SPR_FBUB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FLICKY_BUBBLE
+
+	// Bluebird
+	{SPR_FL01, 0, 2, {A_FlickyCheck}, S_FLICKY_01_FLAP1, S_FLICKY_01_FLAP1, S_FLICKY_01_OUT},   // S_FLICKY_01_OUT
+	{SPR_FL01, 1, 3, {A_FlickyFly},          4*FRACUNIT,       16*FRACUNIT, S_FLICKY_01_FLAP2}, // S_FLICKY_01_FLAP1
+	{SPR_FL01, 2, 3, {A_FlickyFly},          4*FRACUNIT,       16*FRACUNIT, S_FLICKY_01_FLAP3}, // S_FLICKY_01_FLAP2
+	{SPR_FL01, 3, 3, {A_FlickyFly},          4*FRACUNIT,       16*FRACUNIT, S_FLICKY_01_FLAP1}, // S_FLICKY_01_FLAP3
+
+	// Rabbit
+	{SPR_FL02, 0, 2, {A_FlickyCheck}, S_FLICKY_02_AIM,                0, S_FLICKY_02_OUT},  // S_FLICKY_02_OUT
+	{SPR_FL02, 1, 1, {A_FlickyAim},             ANG30,      32*FRACUNIT, S_FLICKY_02_HOP},  // S_FLICKY_02_AIM
+	{SPR_FL02, 1, 1, {A_FlickyHop},        6*FRACUNIT,       4*FRACUNIT, S_FLICKY_02_UP},   // S_FLICKY_02_HOP
+	{SPR_FL02, 2, 2, {A_FlickyCheck}, S_FLICKY_02_AIM, S_FLICKY_02_DOWN, S_FLICKY_02_UP},   // S_FLICKY_02_UP
+	{SPR_FL02, 3, 2, {A_FlickyCheck}, S_FLICKY_02_AIM,                0, S_FLICKY_02_DOWN}, // S_FLICKY_02_DOWN
+
+	// Chicken
+	{SPR_FL03, 0, 2, {A_FlickyCheck},   S_FLICKY_03_AIM, S_FLICKY_03_FLAP1, S_FLICKY_03_OUT},   // S_FLICKY_03_OUT
+	{SPR_FL03, 1, 1, {A_FlickyAim},            ANGLE_45,       32*FRACUNIT, S_FLICKY_03_HOP},   // S_FLICKY_03_AIM
+	{SPR_FL03, 1, 1, {A_FlickyHop},          7*FRACUNIT,        2*FRACUNIT, S_FLICKY_03_UP},    // S_FLICKY_03_HOP
+	{SPR_FL03, 2, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP, S_FLICKY_03_FLAP1, S_FLICKY_03_UP},    // S_FLICKY_03_UP
+	{SPR_FL03, 3, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP,                 0, S_FLICKY_03_FLAP2}, // S_FLICKY_03_FLAP1
+	{SPR_FL03, 4, 2, {A_FlickyFlutter}, S_FLICKY_03_HOP,                 0, S_FLICKY_03_FLAP1}, // S_FLICKY_03_FLAP2
+
+	// Seal
+	{SPR_FL04, 0, 2, {A_FlickyCheck}, S_FLICKY_04_AIM,                 0, S_FLICKY_04_OUT},   // S_FLICKY_04_OUT
+	{SPR_FL04, 1, 1, {A_FlickyAim},             ANG30,       32*FRACUNIT, S_FLICKY_04_HOP},   // S_FLICKY_04_AIM
+	{SPR_FL04, 1, 1, {A_FlickyHop},        3*FRACUNIT,        2*FRACUNIT, S_FLICKY_04_UP},    // S_FLICKY_04_HOP
+	{SPR_FL04, 2, 4, {A_FlickyCheck}, S_FLICKY_04_AIM,  S_FLICKY_04_DOWN, S_FLICKY_04_UP},    // S_FLICKY_04_UP
+	{SPR_FL04, 3, 4, {A_FlickyCheck}, S_FLICKY_04_AIM,                 0, S_FLICKY_04_DOWN},  // S_FLICKY_04_DOWN
+	{SPR_FL04, 3, 4, {A_FlickyFly},        2*FRACUNIT,       48*FRACUNIT, S_FLICKY_04_SWIM2}, // S_FLICKY_04_SWIM1
+	{SPR_FL04, 4, 4, {A_FlickyCoast},        FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM3}, // S_FLICKY_04_SWIM2
+	{SPR_FL04, 3, 4, {A_FlickyCoast},        FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM4}, // S_FLICKY_04_SWIM3
+	{SPR_FL04, 5, 4, {A_FlickyCoast},        FRACUNIT, S_FLICKY_04_SWIM1, S_FLICKY_04_SWIM1}, // S_FLICKY_04_SWIM4
+
+	// Pig
+	{SPR_FL05, 0, 2, {A_FlickyCheck}, S_FLICKY_05_AIM,                0, S_FLICKY_05_OUT},  // S_FLICKY_05_OUT
+	{SPR_FL05, 1, 1, {A_FlickyAim},             ANG20,      32*FRACUNIT, S_FLICKY_05_HOP},  // S_FLICKY_05_AIM
+	{SPR_FL05, 1, 1, {A_FlickyHop},        4*FRACUNIT,       3*FRACUNIT, S_FLICKY_05_UP},   // S_FLICKY_05_HOP
+	{SPR_FL05, 2, 2, {A_FlickyCheck}, S_FLICKY_05_AIM, S_FLICKY_05_DOWN, S_FLICKY_05_UP},   // S_FLICKY_05_UP
+	{SPR_FL05, 3, 2, {A_FlickyCheck}, S_FLICKY_05_AIM,                0, S_FLICKY_05_DOWN}, // S_FLICKY_05_DOWN
+
+	// Chipmunk
+	{SPR_FL06, 0, 2, {A_FlickyCheck}, S_FLICKY_06_AIM,                0, S_FLICKY_06_OUT},  // S_FLICKY_06_OUT
+	{SPR_FL06, 1, 1, {A_FlickyAim},          ANGLE_90,      32*FRACUNIT, S_FLICKY_06_HOP},  // S_FLICKY_06_AIM
+	{SPR_FL06, 1, 1, {A_FlickyHop},        5*FRACUNIT,       6*FRACUNIT, S_FLICKY_06_UP},   // S_FLICKY_06_HOP
+	{SPR_FL06, 2, 2, {A_FlickyCheck}, S_FLICKY_06_AIM, S_FLICKY_06_DOWN, S_FLICKY_06_UP},   // S_FLICKY_06_UP
+	{SPR_FL06, 3, 2, {A_FlickyCheck}, S_FLICKY_06_AIM,                0, S_FLICKY_06_DOWN}, // S_FLICKY_06_DOWN
+
+	// Penguin
+	{SPR_FL07, 0, 2, {A_FlickyCheck}, S_FLICKY_07_AIML,                 0, S_FLICKY_07_OUT},   // S_FLICKY_07_OUT
+	{SPR_FL07, 1, 1, {A_FlickyAim},              ANG30,       32*FRACUNIT, S_FLICKY_07_HOPL},  // S_FLICKY_07_AIML
+	{SPR_FL07, 1, 1, {A_FlickyHop},         4*FRACUNIT,        2*FRACUNIT, S_FLICKY_07_UPL},   // S_FLICKY_07_HOPL
+	{SPR_FL07, 2, 4, {A_FlickyCheck}, S_FLICKY_07_AIMR, S_FLICKY_07_DOWNL, S_FLICKY_07_UPL},   // S_FLICKY_07_UPL
+	{SPR_FL07, 1, 4, {A_FlickyCheck}, S_FLICKY_07_AIMR,                 0, S_FLICKY_07_DOWNL}, // S_FLICKY_07_DOWNL
+	{SPR_FL07, 1, 1, {A_FlickyAim},              ANG30,       32*FRACUNIT, S_FLICKY_07_HOPR},  // S_FLICKY_07_AIMR
+	{SPR_FL07, 1, 1, {A_FlickyHop},         4*FRACUNIT,        2*FRACUNIT, S_FLICKY_07_UPR},   // S_FLICKY_07_HOPR
+	{SPR_FL07, 3, 4, {A_FlickyCheck}, S_FLICKY_07_AIML, S_FLICKY_07_DOWNR, S_FLICKY_07_UPR},   // S_FLICKY_07_UPR
+	{SPR_FL07, 1, 4, {A_FlickyCheck}, S_FLICKY_07_AIML,                 0, S_FLICKY_07_DOWNR}, // S_FLICKY_07_DOWNR
+	{SPR_FL07, 4, 4, {A_FlickyFly},         3*FRACUNIT,       72*FRACUNIT, S_FLICKY_07_SWIM2}, // S_FLICKY_07_SWIM1
+	{SPR_FL07, 5, 4, {A_FlickyCoast},         FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3}, // S_FLICKY_07_SWIM2
+	{SPR_FL07, 6, 4, {A_FlickyCoast},       2*FRACUNIT, S_FLICKY_07_SWIM1, S_FLICKY_07_SWIM3}, // S_FLICKY_07_SWIM3
+
+	// Fish
+	{SPR_FL08, 0, 2, {A_FlickyCheck}, S_FLICKY_08_AIM,                 0, S_FLICKY_08_OUT},   // S_FLICKY_08_OUT
+	{SPR_FL08, 2, 1, {A_FlickyAim},             ANG30,       32*FRACUNIT, S_FLICKY_08_HOP},   // S_FLICKY_08_AIM
+	{SPR_FL08, 2, 1, {A_FlickyFlounder},   2*FRACUNIT,        1*FRACUNIT, S_FLICKY_08_FLAP1}, // S_FLICKY_08_HOP
+	{SPR_FL08, 0, 4, {A_FlickyCheck}, S_FLICKY_08_AIM,                 0, S_FLICKY_08_FLAP2}, // S_FLICKY_08_FLAP1
+	{SPR_FL08, 1, 4, {A_FlickyCheck}, S_FLICKY_08_AIM,                 0, S_FLICKY_08_FLAP3}, // S_FLICKY_08_FLAP2
+	{SPR_FL08, 0, 4, {A_FlickyCheck}, S_FLICKY_08_AIM,                 0, S_FLICKY_08_FLAP4}, // S_FLICKY_08_FLAP3
+	{SPR_FL08, 2, 4, {A_FlickyCheck}, S_FLICKY_08_AIM,                 0, S_FLICKY_08_FLAP1}, // S_FLICKY_08_FLAP4
+	{SPR_FL08, 0, 4, {A_FlickyFly},        3*FRACUNIT,       64*FRACUNIT, S_FLICKY_08_SWIM2}, // S_FLICKY_08_SWIM1
+	{SPR_FL08, 1, 4, {A_FlickyCoast},        FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM3}, // S_FLICKY_08_SWIM2
+	{SPR_FL08, 0, 4, {A_FlickyCoast},        FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4}, // S_FLICKY_08_SWIM3
+	{SPR_FL08, 2, 4, {A_FlickyCoast},        FRACUNIT, S_FLICKY_08_SWIM1, S_FLICKY_08_SWIM4}, // S_FLICKY_08_SWIM4
+
+	// Ram
+	{SPR_FL09, 0, 2, {A_FlickyCheck}, S_FLICKY_09_AIM,                0, S_FLICKY_09_OUT},  // S_FLICKY_09_OUT
+	{SPR_FL09, 1, 1, {A_FlickyAim},             ANG30,      32*FRACUNIT, S_FLICKY_09_HOP},  // S_FLICKY_09_AIM
+	{SPR_FL09, 1, 1, {A_FlickyHop},        7*FRACUNIT,       2*FRACUNIT, S_FLICKY_09_UP},   // S_FLICKY_09_HOP
+	{SPR_FL09, 2, 2, {A_FlickyCheck}, S_FLICKY_09_AIM, S_FLICKY_09_DOWN, S_FLICKY_09_UP},   // S_FLICKY_09_UP
+	{SPR_FL09, 3, 2, {A_FlickyCheck}, S_FLICKY_09_AIM,                0, S_FLICKY_09_DOWN}, // S_FLICKY_09_DOWN
+
+	// Puffin
+	{SPR_FL10, 0, 2, {A_FlickyCheck}, S_FLICKY_10_FLAP1, S_FLICKY_10_FLAP1, S_FLICKY_10_OUT},   // S_FLICKY_10_OUT
+	{SPR_FL10, 1, 3, {A_FlickySoar},         4*FRACUNIT,       16*FRACUNIT, S_FLICKY_10_FLAP2}, // S_FLICKY_10_FLAP1
+	{SPR_FL10, 2, 3, {A_FlickySoar},         4*FRACUNIT,       16*FRACUNIT, S_FLICKY_10_FLAP1}, // S_FLICKY_10_FLAP2
+
+	// Cow
+	{SPR_FL11, 0, 2, {A_FlickyCheck}, S_FLICKY_11_AIM,           0, S_FLICKY_11_OUT},  // S_FLICKY_11_OUT
+	{SPR_FL11, 1, 1, {A_FlickyAim},          ANGLE_90, 64*FRACUNIT, S_FLICKY_11_RUN1}, // S_FLICKY_11_AIM
+	{SPR_FL11, 1, 3, {A_FlickyHop},        FRACUNIT/2,  2*FRACUNIT, S_FLICKY_11_RUN2}, // S_FLICKY_11_RUN1
+	{SPR_FL11, 2, 4, {A_FlickyHop},        FRACUNIT/2,  2*FRACUNIT, S_FLICKY_11_RUN3}, // S_FLICKY_11_RUN2
+	{SPR_FL11, 3, 4, {A_FlickyHop},        FRACUNIT/2,  2*FRACUNIT, S_FLICKY_11_AIM},  // S_FLICKY_11_RUN3
+
+	// Rat
+	{SPR_FL12, 0, 2, {A_FlickyCheck}, S_FLICKY_12_AIM,           0, S_FLICKY_12_OUT},  // S_FLICKY_12_OUT
+	{SPR_FL12, 1, 1, {A_FlickyAim},          ANGLE_90, 32*FRACUNIT, S_FLICKY_12_RUN1}, // S_FLICKY_12_AIM
+	{SPR_FL12, 1, 2, {A_FlickyHop},                 1, 12*FRACUNIT, S_FLICKY_12_RUN2}, // S_FLICKY_12_RUN1
+	{SPR_FL12, 2, 3, {A_FlickyHop},                 1, 12*FRACUNIT, S_FLICKY_12_RUN3}, // S_FLICKY_12_RUN2
+	{SPR_FL12, 3, 3, {A_FlickyHop},                 1, 12*FRACUNIT, S_FLICKY_12_AIM},  // S_FLICKY_12_RUN3
+
+	// Bear
+	{SPR_FL13, 0, 2, {A_FlickyCheck}, S_FLICKY_13_AIM,                0, S_FLICKY_13_OUT}, // S_FLICKY_13_OUT
+	{SPR_FL13, 1, 1, {A_FlickyAim},             ANG30,      32*FRACUNIT, S_FLICKY_13_HOP}, // S_FLICKY_13_AIM
+	{SPR_FL13, 1, 1, {A_FlickyHop},        5*FRACUNIT,       3*FRACUNIT, S_FLICKY_13_UP}, // S_FLICKY_13_HOP
+	{SPR_FL13, 2, 2, {A_FlickyCheck}, S_FLICKY_13_AIM, S_FLICKY_13_DOWN, S_FLICKY_13_UP}, // S_FLICKY_13_UP
+	{SPR_FL13, 3, 2, {A_FlickyCheck}, S_FLICKY_13_AIM,                0, S_FLICKY_13_DOWN}, // S_FLICKY_13_DOWN
+
+	// Dove
+	{SPR_FL14, 0, 2, {A_FlickyCheck}, S_FLICKY_14_FLAP1, S_FLICKY_14_FLAP1, S_FLICKY_14_OUT},   // S_FLICKY_14_OUT
+	{SPR_FL14, 1, 3, {A_FlickySoar},         4*FRACUNIT,       32*FRACUNIT, S_FLICKY_14_FLAP2}, // S_FLICKY_14_FLAP1
+	{SPR_FL14, 2, 3, {A_FlickySoar},         4*FRACUNIT,       32*FRACUNIT, S_FLICKY_14_FLAP3}, // S_FLICKY_14_FLAP2
+	{SPR_FL14, 3, 3, {A_FlickySoar},         4*FRACUNIT,       32*FRACUNIT, S_FLICKY_14_FLAP1}, // S_FLICKY_14_FLAP3
+
+	// Cat
+	{SPR_FL15, 0, 2, {A_FlickyCheck}, S_FLICKY_15_AIM,                0, S_FLICKY_15_OUT},  // S_FLICKY_15_OUT
+	{SPR_FL15, 1, 1, {A_FlickyAim},             ANG30,      32*FRACUNIT, S_FLICKY_15_HOP},  // S_FLICKY_15_AIM
+	{SPR_FL15, 1, 1, {A_FlickyFlounder},   2*FRACUNIT,       6*FRACUNIT, S_FLICKY_15_UP},   // S_FLICKY_15_HOP
+	{SPR_FL15, 2, 2, {A_FlickyCheck}, S_FLICKY_15_AIM, S_FLICKY_15_DOWN, S_FLICKY_15_UP},   // S_FLICKY_15_UP
+	{SPR_FL15, 3, 2, {A_FlickyCheck}, S_FLICKY_15_AIM,                0, S_FLICKY_15_DOWN}, // S_FLICKY_15_DOWN
+
+	// Canary
+	{SPR_FL16, 0, 2, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1,          0, S_FLICKY_16_OUT},   // S_FLICKY_16_OUT
+	{SPR_FL16, 1, 3, {A_FlickyFly},                4*FRACUNIT, 8*FRACUNIT, S_FLICKY_16_FLAP2}, // S_FLICKY_16_FLAP1
+	{SPR_FL16, 2, 3, {A_SetObjectFlags},         MF_NOGRAVITY,          1, S_FLICKY_16_FLAP3}, // S_FLICKY_16_FLAP2
+	{SPR_FL16, 3, 3, {A_FlickyHeightCheck}, S_FLICKY_16_FLAP1,          0, S_FLICKY_16_FLAP3}, // S_FLICKY_16_FLAP3
 
 	// Yellow Spring
 	{SPR_SPRY, 0, -1, {NULL}, 0, 0, S_NULL},           // S_YELLOWSPRING
@@ -2279,6 +2491,21 @@ state_t states[NUMSTATES] =
 
 	{SPR_WZAP, FF_TRANS10|FF_ANIMATE|FF_RANDOMANIM, 4, {NULL}, 3, 2, S_NULL},  // S_WATERZAP
 
+	// Spindash dust
+	{SPR_DUST,            0, 7, {NULL}, 0, 0, S_SPINDUST2}, // S_SPINDUST1
+	{SPR_DUST,            1, 6, {NULL}, 0, 0, S_SPINDUST3}, // S_SPINDUST2
+	{SPR_DUST, FF_TRANS30|2, 4, {NULL}, 0, 0, S_SPINDUST4}, // S_SPINDUST3
+	{SPR_DUST, FF_TRANS60|3, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST4
+	{SPR_BUBL,            0, 7, {NULL}, 0, 0, S_SPINDUST_BUBBLE2}, // S_SPINDUST_BUBBLE1
+	{SPR_BUBL,            0, 6, {NULL}, 0, 0, S_SPINDUST_BUBBLE3}, // S_SPINDUST_BUBBLE2
+	{SPR_BUBL, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_BUBBLE4}, // S_SPINDUST_BUBBLE3
+	{SPR_BUBL, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_BUBBLE4
+	{SPR_FPRT,            0, 7, {NULL}, 0, 0, S_SPINDUST_FIRE2}, // S_SPINDUST_FIRE1
+	{SPR_FPRT,            0, 6, {NULL}, 0, 0, S_SPINDUST_FIRE3}, // S_SPINDUST_FIRE2
+	{SPR_FPRT, FF_TRANS30|0, 4, {NULL}, 0, 0, S_SPINDUST_FIRE4}, // S_SPINDUST_FIRE3
+	{SPR_FPRT, FF_TRANS60|0, 3, {NULL}, 0, 0, S_NULL}, // S_SPINDUST_FIRE4
+
+
 	{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
@@ -2295,7 +2522,7 @@ state_t states[NUMSTATES] =
 	{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
+	{SPR_SEED, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 2, 2, S_NULL}, // S_SEED
 
 	// Particle sprite
 	{SPR_PRTL, FF_FULLBRIGHT|FF_TRANS70, 2*TICRATE, {NULL}, 0, 0, S_NULL}, // S_PARTICLE
@@ -2690,14 +2917,15 @@ state_t states[NUMSTATES] =
 	{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
-	{SPR_BIRD, 0, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER3}, // S_NIGHTOPIANHELPER2
-	{SPR_BIRD, 0, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER4}, // S_NIGHTOPIANHELPER3
-	{SPR_BIRD, 0, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER5}, // S_NIGHTOPIANHELPER4
-	{SPR_BIRD, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER6}, // S_NIGHTOPIANHELPER5
-	{SPR_BIRD, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER7}, // S_NIGHTOPIANHELPER6
-	{SPR_BIRD, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER8}, // S_NIGHTOPIANHELPER7
-	{SPR_BIRD, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER1}, // S_NIGHTOPIANHELPER8
+	{SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER2}, // S_NIGHTOPIANHELPER1
+	{SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER3}, // S_NIGHTOPIANHELPER2
+	{SPR_FL01, 1, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER4}, // S_NIGHTOPIANHELPER3
+	{SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER5}, // S_NIGHTOPIANHELPER4
+	{SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER6}, // S_NIGHTOPIANHELPER5
+	{SPR_FL01, 2, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER7}, // S_NIGHTOPIANHELPER6
+	{SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER8}, // S_NIGHTOPIANHELPER7
+	{SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER9}, // S_NIGHTOPIANHELPER8
+	{SPR_FL01, 3, 1, {A_OrbitNights}, ANG2*2, 180 | 0x10000, S_NIGHTOPIANHELPER1}, // S_NIGHTOPIANHELPER9
 
 	{SPR_NULL, 0, 35, {NULL}, 0, 0, S_CRUMBLE2},  // S_CRUMBLE1
 	{SPR_NULL, 0, 105, {A_Scream}, 0, 0, S_NULL}, // S_CRUMBLE2
@@ -2721,10 +2949,11 @@ state_t states[NUMSTATES] =
 	{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
-	{SPR_BOM1, 1, 5, {NULL}, 0, 0, S_XPLD3},     // S_XPLD2
-	{SPR_BOM1, 2, 5, {NULL}, 0, 0, S_XPLD4},     // S_XPLD3
-	{SPR_BOM1, 3, 5, {NULL}, 0, 0, S_NULL},      // S_XPLD4
+	{SPR_BOM1, 0,             0, {A_FlickySpawn}, 0, 0, S_XPLD1}, // S_XPLD_FLICKY
+	{SPR_BOM1, 0,             1, {A_Scream},      0, 0, S_XPLD2}, // S_XPLD1
+	{SPR_BOM1, FF_ANIMATE|1, 15, {NULL},          2, 5, S_NULL},  // S_XPLD2
+
+	{SPR_BOM1, FF_ANIMATE,   20, {NULL},          3, 5, S_INVISIBLE}, // S_XPLD_EGGTRAP
 
 	// Underwater Explosion
 	{SPR_BOM4, 0, 3, {A_Scream}, 0, 0, S_WPLD2}, // S_WPLD1
@@ -2881,7 +3110,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		3,              // speed
@@ -2908,7 +3137,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		3,              // speed
@@ -2935,7 +3164,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_FISH3,        // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_FISH4,        // xdeathstate
 		sfx_pop,        // deathsound
 		0,              // speed
@@ -2962,7 +3191,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		4*FRACUNIT,     // speed
@@ -2989,7 +3218,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		8*FRACUNIT,     // speed
@@ -3016,7 +3245,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		6*FRACUNIT,     // speed
@@ -3043,7 +3272,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		1*FRACUNIT,     // speed
@@ -3070,7 +3299,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_JETGSHOOT1,   // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		1*FRACUNIT,     // speed
@@ -3097,7 +3326,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_dmpain,     // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		3,              // speed
@@ -3124,7 +3353,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_DETON16,      // xdeathstate
 		sfx_pop,        // deathsound
 		1*FRACUNIT,     // speed
@@ -3151,7 +3380,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_SKIM3,        // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		8,              // speed
@@ -3205,7 +3434,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_s3k64,      // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		0,              // speed
@@ -3232,7 +3461,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_SHARP_AIM1,   // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_SHARP_SPIN,   // xdeathstate
 		sfx_pop,        // deathsound
 		2,              // speed
@@ -3259,7 +3488,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		8,              // speed
@@ -3286,7 +3515,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		FRACUNIT,       // speed
@@ -3313,7 +3542,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_VULTURE_ZOOM1,// missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		3,              // speed
@@ -3340,7 +3569,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		5*FRACUNIT,     // speed
@@ -3394,7 +3623,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,         // painsound
 		S_NULL,           // meleestate
 		S_ROBOHOOD_SHOOT, // missilestate
-		S_XPLD1,          // deathstate
+		S_XPLD_FLICKY,    // deathstate
 		S_ROBOHOOD_JUMP2, // xdeathstate
 		sfx_pop,          // deathsound
 		0,                // speed
@@ -3421,7 +3650,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_FACESTABBER_CHARGE1, // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		3,              // speed
@@ -3448,7 +3677,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,        // painsound
 		S_EGGGUARD_RUN1, // meleestate
 		S_NULL,          // missilestate
-		S_XPLD1,         // deathstate
+		S_XPLD_FLICKY,   // deathstate
 		S_NULL,          // xdeathstate
 		sfx_pop,         // deathsound
 		6,               // speed
@@ -3502,7 +3731,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		3,              // speed
@@ -3529,7 +3758,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_MINUS_DOWNWARD1,// meleestate
 		S_MINUS_POPUP,  // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		12,             // speed
@@ -3556,7 +3785,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_spring,     // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		6,              // speed
@@ -3583,7 +3812,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_spring,     // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		6,              // speed
@@ -3610,7 +3839,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_XPLD1,        // deathstate
+		S_XPLD_FLICKY,  // deathstate
 		S_NULL,         // xdeathstate
 		sfx_pop,        // deathsound
 		2,              // speed
@@ -6346,6 +6575,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
+	{           // MT_FLAMEAURA_BOX
+		420,            // doomednum
+		S_FLAMEAURA_BOX, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_FLAMEAURA_BOX, // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_BOX_POP1,     // deathstate
+		S_NULL,         // xdeathstate
+		sfx_pop,        // deathsound
+		1,              // speed
+		16*FRACUNIT,    // radius
+		32*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		MT_FLAMEAURA_ICON, // damage
+		sfx_None,       // activesound
+		MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags
+		S_NULL          // raisestate
+	},
+
+	{           // MT_BUBBLEWRAP_BOX
+		421,            // doomednum
+		S_BUBBLEWRAP_BOX, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_BUBBLEWRAP_BOX, // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_BOX_POP1,     // deathstate
+		S_NULL,         // xdeathstate
+		sfx_pop,        // deathsound
+		1,              // speed
+		16*FRACUNIT,    // radius
+		32*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		MT_BUBBLEWRAP_ICON, // damage
+		sfx_None,       // activesound
+		MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags
+		S_NULL          // raisestate
+	},
+
+	{           // MT_THUNDERCOIN_BOX
+		422,            // doomednum
+		S_THUNDERCOIN_BOX, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_THUNDERCOIN_BOX, // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_BOX_POP1,     // deathstate
+		S_NULL,         // xdeathstate
+		sfx_pop,        // deathsound
+		1,              // speed
+		16*FRACUNIT,    // radius
+		32*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		MT_THUNDERCOIN_ICON, // damage
+		sfx_None,       // activesound
+		MF_SOLID|MF_SHOOTABLE|MF_MONITOR, // flags
+		S_NULL          // raisestate
+	},
+
 	{           // MT_PITY_GOLDBOX
 		431,            // doomednum
 		S_PITY_GOLDBOX, // spawnstate
@@ -6616,6 +6926,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
+	{           // MT_FLAMEAURA_GOLDBOX
+		450,            // doomednum
+		S_FLAMEAURA_GOLDBOX, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_monton,     // attacksound
+		S_FLAMEAURA_GOLDBOX, // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_GOLDBOX_OFF1, // deathstate
+		S_NULL,         // xdeathstate
+		sfx_pop,        // deathsound
+		0,              // speed
+		16*FRACUNIT,    // radius
+		36*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		MT_FLAMEAURA_ICON, // damage
+		sfx_None,       // activesound
+		MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags
+		S_NULL          // raisestate
+	},
+
+	{           // MT_BUBBLEWRAP_GOLDBOX
+		451,            // doomednum
+		S_BUBBLEWRAP_GOLDBOX, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_monton,     // attacksound
+		S_BUBBLEWRAP_GOLDBOX, // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_GOLDBOX_OFF1, // deathstate
+		S_NULL,         // xdeathstate
+		sfx_pop,        // deathsound
+		0,              // speed
+		16*FRACUNIT,    // radius
+		36*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		MT_BUBBLEWRAP_ICON, // damage
+		sfx_None,       // activesound
+		MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags
+		S_NULL          // raisestate
+	},
+
+	{           // MT_THUNDERCOIN_GOLDBOX
+		452,            // doomednum
+		S_THUNDERCOIN_GOLDBOX, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_monton,     // attacksound
+		S_THUNDERCOIN_GOLDBOX, // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_GOLDBOX_OFF1, // deathstate
+		S_NULL,         // xdeathstate
+		sfx_pop,        // deathsound
+		0,              // speed
+		16*FRACUNIT,    // radius
+		36*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		MT_THUNDERCOIN_ICON, // damage
+		sfx_None,       // activesound
+		MF_SOLID|MF_SHOOTABLE|MF_MONITOR|MF_GRENADEBOUNCE, // flags
+		S_NULL          // raisestate
+	},
+
 	{  		   // MT_RING_REDBOX
 		414,            // doomednum
 		S_RING_REDBOX1, // spawnstate
@@ -6702,7 +7093,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_PITY_ICON1,   // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
-		sfx_shield,     // seesound
+		sfx_s3k3a,      // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
@@ -6729,7 +7120,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_ATTRACT_ICON1, // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
-		sfx_shield,     // seesound
+		sfx_s3k41,      // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
@@ -6756,7 +7147,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_FORCE_ICON1,  // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
-		sfx_shield,     // seesound
+		sfx_forcsg,     // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
@@ -6783,7 +7174,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_ARMAGEDDON_ICON1, // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
-		sfx_shield,     // seesound
+		sfx_armasg,     // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
@@ -6810,7 +7201,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_WHIRLWIND_ICON1, // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
-		sfx_shield,     // seesound
+		sfx_wirlsg,     // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
@@ -6837,7 +7228,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_ELEMENTAL_ICON1, // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
-		sfx_shield,     // seesound
+		sfx_elemsg,      // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
@@ -7102,6 +7493,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
+	{           // MT_FLAMEAURA_ICON
+		-1,             // doomednum
+		S_FLAMEAURA_ICON1, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_s3k3e,      // 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
+		2*FRACUNIT,     // speed
+		8*FRACUNIT,     // radius
+		14*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		62*FRACUNIT,    // damage
+		sfx_None,       // activesound
+		MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
+		S_NULL          // raisestate
+	},
+
+	{           // MT_BUBBLEWRAP_ICON
+		-1,             // doomednum
+		S_BUBBLEWRAP_ICON1, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_s3k3f,      // 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
+		2*FRACUNIT,     // speed
+		8*FRACUNIT,     // radius
+		14*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		62*FRACUNIT,    // damage
+		sfx_None,       // activesound
+		MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
+		S_NULL          // raisestate
+	},
+
+	{           // MT_THUNDERCOIN_ICON
+		-1,             // doomednum
+		S_THUNDERCOIN_ICON1, // spawnstate
+		1,              // spawnhealth
+		S_NULL,         // seestate
+		sfx_s3k41,      // 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
+		2*FRACUNIT,     // speed
+		8*FRACUNIT,     // radius
+		14*FRACUNIT,    // height
+		0,              // display offset
+		100,            // mass
+		62*FRACUNIT,    // damage
+		sfx_None,       // activesound
+		MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOGRAVITY|MF_BOXICON, // flags
+		S_NULL          // raisestate
+	},
+
 	{           // MT_ROCKET
 		-1,             // doomednum
 		S_ROCKET,       // spawnstate
@@ -10345,7 +10817,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
-	{           // MT_GREENORB
+	{           // MT_ELEMENTAL_ORB
 		-1,             // doomednum
 		S_ELEM1,        // spawnstate
 		1000,           // spawnhealth
@@ -10353,7 +10825,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // seesound
 		0,              // reactiontime
 		sfx_None,       // attacksound
-		S_NULL,         // painstate
+		S_ELEM13,       // painstate
 		SKINCOLOR_NONE, // painchance
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
@@ -10364,15 +10836,15 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		SH_ELEMENTAL,   // speed
 		64*FRACUNIT,    // radius
 		64*FRACUNIT,    // height
-		1,              // display offset
+		2,              // display offset
 		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
 		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
-		S_NULL          // raisestate
+		S_ELEMF9        // raisestate
 	},
 
-	{           // MT_YELLOWORB
+	{           // MT_ATTRACT_ORB
 		-1,             // doomednum
 		S_MAGN1,        // spawnstate
 		1000,           // spawnhealth
@@ -10380,7 +10852,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
-		S_NULL,         // painstate
+		S_MAGN13,       // painstate
 		SKINCOLOR_NONE, // painchance
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
@@ -10391,7 +10863,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		SH_ATTRACT,     // speed
 		64*FRACUNIT,    // radius
 		64*FRACUNIT,    // height
-		1,              // display offset
+		2,              // display offset
 		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
@@ -10399,7 +10871,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
-	{           // MT_BLUEORB
+	{           // MT_FORCE_ORB
 		-1,             // doomednum
 		S_FORC1,        // spawnstate
 		1000,           // spawnhealth
@@ -10418,15 +10890,15 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		SH_FORCE,       // speed
 		64*FRACUNIT,    // radius
 		64*FRACUNIT,    // height
-		1,              // display offset
+		2,              // display offset
 		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
 		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
-		S_NULL          // raisestate
+		S_FORC21        // raisestate
 	},
 
-	{           // MT_BLACKORB
+	{           // MT_ARMAGEDDON_ORB
 		-1,             // doomednum
 		S_ARMA1,        // spawnstate
 		1000,           // spawnhealth
@@ -10442,10 +10914,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // deathstate
 		S_NULL,         // xdeathstate
 		sfx_None,       // deathsound
-		SH_BOMB,        // speed
+		SH_ARMAGEDDON,  // speed
 		64*FRACUNIT,    // radius
 		64*FRACUNIT,    // height
-		1,              // display offset
+		2,              // display offset
 		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
@@ -10453,7 +10925,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
-	{           // MT_WHITEORB
+	{           // MT_WHIRLWIND_ORB
 		-1,             // doomednum
 		S_WIND1,        // spawnstate
 		1000,           // spawnhealth
@@ -10469,10 +10941,10 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // deathstate
 		S_NULL,         // xdeathstate
 		sfx_None,       // deathsound
-		SH_JUMP,        // speed
+		SH_WHIRLWIND,        // speed
 		64*FRACUNIT,    // radius
 		64*FRACUNIT,    // height
-		1,              // display offset
+		2,              // display offset
 		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
@@ -10480,7 +10952,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
-	{           // MT_PITYORB
+	{           // MT_PITY_ORB
 		-1,             // doomednum
 		S_PITY1,        // spawnstate
 		1000,           // spawnhealth
@@ -10499,7 +10971,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		SH_PITY,        // speed
 		64*FRACUNIT,    // radius
 		64*FRACUNIT,    // height
-		1,              // display offset
+		2,              // display offset
 		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
@@ -10507,7 +10979,115 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
-	{           // MT_IVSP
+	{           // MT_FLAMEAURA_ORB
+		-1,             // doomednum
+		S_FIRSB1,       // spawnstate
+		1000,           // spawnhealth
+		S_FIRS1,        // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_FIRSB10,      // painstate
+		SKINCOLOR_NONE, // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_NULL,         // deathstate
+		S_NULL,         // xdeathstate
+		sfx_None,       // deathsound
+		SH_FLAMEAURA,   // speed
+		64*FRACUNIT,    // radius
+		64*FRACUNIT,    // height
+		-2,             // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
+		S_FIRS10        // raisestate
+	},
+
+	{           // MT_BUBBLEWRAP_ORB
+		-1,             // doomednum
+		S_BUBSB1,       // spawnstate
+		1000,           // spawnhealth
+		S_BUBS1,        // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_BUBSB5,       // painstate
+		SKINCOLOR_NONE, // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_NULL,         // deathstate
+		S_NULL,         // xdeathstate
+		sfx_None,       // deathsound
+		SH_BUBBLEWRAP,  // speed
+		64*FRACUNIT,    // radius
+		64*FRACUNIT,    // height
+		2,              // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
+		S_BUBS10        // raisestate
+	},
+
+	{           // MT_THUNDERCOIN_ORB
+		-1,             // doomednum
+		S_ZAPSB1,       // spawnstate
+		1000,           // spawnhealth
+		S_ZAPS1,        // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_ZAPSB11,      // painstate
+		SKINCOLOR_NONE, // painchance
+		sfx_None,       // painsound
+		S_NULL,         // meleestate
+		S_NULL,         // missilestate
+		S_NULL,         // deathstate
+		S_NULL,         // xdeathstate
+		sfx_None,       // deathsound
+		SH_THUNDERCOIN, // speed
+		64*FRACUNIT,    // radius
+		64*FRACUNIT,    // height
+		-2,             // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
+		S_ZAPS14        // raisestate
+	},
+
+	{           // MT_THUNDERCOIN_SPARK
+		-1,             // doomednum
+		S_THUNDERCOIN_SPARK, // spawnstate
+		1,              // 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
+		0,              // speed
+		4*FRACUNIT,     // radius
+		4*FRACUNIT,     // height
+		0,              // display offset
+		100,            // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
+		S_NULL          // raisestate
+	},
+
+	{           // MT_IVSP
 		-1,             // doomednum
 		S_IVSP,         // spawnstate
 		1000,           // spawnhealth
@@ -10526,7 +11106,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		8,              // speed
 		64*FRACUNIT,    // radius
 		64*FRACUNIT,    // height
-		2,              // display offset
+		3,              // display offset
 		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
@@ -10561,11 +11141,12 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
-	{           // MT_BIRD
+	// Bluebird
+	{           // MT_FLICKY_01
 		-1,             // doomednum
-		S_BIRD1,        // spawnstate
+		S_FLICKY_01_OUT, // spawnstate
 		1000,           // spawnhealth
-		S_BIRD1,        // seestate
+		S_NULL,         // seestate
 		sfx_None,       // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
@@ -10578,22 +11159,21 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // xdeathstate
 		sfx_None,       // deathsound
 		8,              // speed
-		16*FRACUNIT,    // radius
-		16*FRACUNIT,    // height
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
 		0,              // display offset
 		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
-		MF_NOCLIPTHING|MF_FLOAT|MF_NOGRAVITY, // flags
-		S_NULL          // raisestate
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
 	},
 
-	// freed bunny
-	{           // MT_BUNNY
+	{           // MT_FLICKY_02
 		-1,             // doomednum
-		S_BUNNY1,       // spawnstate
+		S_FLICKY_02_OUT, // spawnstate
 		1000,           // spawnhealth
-		S_BUNNY1,       // seestate
+		S_NULL,         // seestate
 		sfx_None,       // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
@@ -10606,50 +11186,77 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // xdeathstate
 		sfx_None,       // deathsound
 		8,              // speed
-		16*FRACUNIT,    // radius
-		16*FRACUNIT,    // height
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
 		0,              // display offset
 		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
-		MF_NOCLIPTHING|MF_FLOAT, // flags
-		S_NULL          // raisestate
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
 	},
 
-	{           // MT_MOUSE
+	{           // MT_FLICKY_03
 		-1,             // doomednum
-		S_MOUSE1,       // spawnstate
-		1,              // spawnhealth
+		S_FLICKY_03_OUT, // spawnstate
+		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
-		1,              // reactiontime
+		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
-		200,            // painchance
+		0,              // painchance
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
 		S_NULL,         // deathstate
 		S_NULL,         // xdeathstate
 		sfx_None,       // deathsound
-		20*FRACUNIT,    // speed
-		4*FRACUNIT,     // radius
-		4*FRACUNIT,     // height
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
 		0,              // display offset
-		100,            // mass
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
+	},
+
+	{           // MT_FLICKY_04
+		-1,             // doomednum
+		S_FLICKY_04_OUT, // spawnstate
+		1000,           // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_NULL,         // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_FLICKY_04_SWIM1, // meleestate
+		S_NULL,         // missilestate
+		S_NULL,         // deathstate
+		S_NULL,         // xdeathstate
+		sfx_None,       // deathsound
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
+		0,              // display offset
+		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
 		MF_NOCLIPTHING, // flags
 		S_NULL          // raisestate
 	},
 
-	{           // MT_CHICKEN
+	{           // MT_FLICKY_05
 		-1,             // doomednum
-		S_CHICKEN1,     // spawnstate
+		S_FLICKY_05_OUT, // spawnstate
 		1000,           // spawnhealth
-		S_CHICKEN1,     // seestate
+		S_NULL,         // seestate
 		sfx_None,       // seesound
-		0,              // reactiontime
+		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
 		0,              // painchance
@@ -10659,71 +11266,314 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // deathstate
 		S_NULL,         // xdeathstate
 		sfx_None,       // deathsound
-		1,              // speed
-		16*FRACUNIT,    // radius
-		16*FRACUNIT,    // height
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
 		0,              // display offset
 		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
-		MF_NOCLIPTHING|MF_FLOAT, // flags
-		S_NULL          // raisestate
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
 	},
 
-	{           // MT_COW
+	{           // MT_FLICKY_06
 		-1,             // doomednum
-		S_COW1,         // spawnstate
-		1,              // spawnhealth
+		S_FLICKY_06_OUT, // spawnstate
+		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
-		1,              // reactiontime
+		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
-		200,            // painchance
+		0,              // painchance
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
 		S_NULL,         // deathstate
 		S_NULL,         // xdeathstate
 		sfx_None,       // deathsound
-		4,              // speed
-		4*FRACUNIT,     // radius
-		4*FRACUNIT,     // height
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
 		0,              // display offset
-		100,            // mass
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
+	},
+
+	{           // MT_FLICKY_07
+		-1,             // doomednum
+		S_FLICKY_07_OUT, // spawnstate
+		1000,           // spawnhealth
+		S_NULL,         // seestate
+		sfx_None,       // seesound
+		8,              // reactiontime
+		sfx_None,       // attacksound
+		S_NULL,         // painstate
+		0,              // painchance
+		sfx_None,       // painsound
+		S_FLICKY_07_SWIM1, // meleestate
+		S_NULL,         // missilestate
+		S_NULL,         // deathstate
+		S_NULL,         // xdeathstate
+		sfx_None,       // deathsound
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
+		0,              // display offset
+		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
 		MF_NOCLIPTHING, // flags
 		S_NULL          // raisestate
 	},
 
-	{           // MT_REDBIRD
+	{           // MT_FLICKY_08
 		-1,             // doomednum
-		S_RBIRD1,       // spawnstate
+		S_FLICKY_08_OUT, // spawnstate
 		1000,           // spawnhealth
-		S_RBIRD1,       // seestate
+		S_NULL,         // seestate
 		sfx_None,       // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
 		0,              // painchance
 		sfx_None,       // painsound
-		S_NULL,         // meleestate
+		S_FLICKY_08_SWIM1, // meleestate
 		S_NULL,         // missilestate
 		S_NULL,         // deathstate
 		S_NULL,         // xdeathstate
 		sfx_None,       // deathsound
 		8,              // speed
-		16*FRACUNIT,    // radius
-		16*FRACUNIT,    // height
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
 		0,              // display offset
 		16,             // mass
 		0,              // damage
 		sfx_None,       // activesound
-		MF_NOCLIPTHING|MF_FLOAT|MF_NOGRAVITY, // flags
+		MF_NOCLIPTHING, // flags
 		S_NULL          // raisestate
 	},
 
+	{           // MT_FLICKY_09
+		-1,             // doomednum
+		S_FLICKY_09_OUT, // 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
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
+		0,              // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
+	},
+
+	{           // MT_FLICKY_10
+		-1,             // doomednum
+		S_FLICKY_10_OUT, // 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
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
+		0,              // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
+	},
+
+	{           // MT_FLICKY_11
+		-1,             // doomednum
+		S_FLICKY_11_OUT, // 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
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
+		0,              // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
+	},
+
+	{           // MT_FLICKY_12
+		-1,             // doomednum
+		S_FLICKY_12_OUT, // 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
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
+		0,              // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
+	},
+
+	{           // MT_FLICKY_13
+		-1,             // doomednum
+		S_FLICKY_13_OUT, // 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
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
+		0,              // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
+	},
+
+	{           // MT_FLICKY_14
+		-1,             // doomednum
+		S_FLICKY_14_OUT, // 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
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
+		0,              // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
+	},
+
+	{           // MT_FLICKY_15
+		-1,             // doomednum
+		S_FLICKY_15_OUT, // 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
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
+		0,              // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
+	},
+
+	{           // MT_FLICKY_16
+		-1,             // doomednum
+		S_FLICKY_16_OUT, // 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
+		8,              // speed
+		8*FRACUNIT,     // radius
+		20*FRACUNIT,    // height
+		0,              // display offset
+		16,             // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOCLIPTHING, // flags
+		S_FLICKY_BUBBLE // raisestate
+	},
+
 	{           // MT_RAIN
 		-1,             // doomednum
 		S_RAIN1,        // spawnstate
@@ -10940,6 +11790,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL          // raisestate
 	},
 
+	{           // MT_SPINDUST
+		-1,             // doomednum
+		S_SPINDUST1,     // 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
+		4*FRACUNIT,     // speed
+		4*FRACUNIT,     // radius
+		4*FRACUNIT,     // height
+		0,              // display offset
+		4,              // mass
+		0,              // damage
+		sfx_None,       // activesound
+		MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP, // flags
+		S_NULL          // raisestate
+	},
+
 	{           // MT_TFOG
 		-1,             // doomednum
 		S_FOG1,         // spawnstate
@@ -10990,7 +11867,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		4,              // mass
 		0,              // damage
 		sfx_None,       // activesound
-		MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY, // flags
+		MF_NOBLOCKMAP|MF_SCENERY, // flags
 		S_NULL          // raisestate
 	},
 
@@ -12153,7 +13030,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // missilestate
 		S_NULL,         // deathstate
 		S_NULL,         // xdeathstate
-		sfx_mario3,     // deathsound
+		sfx_None,       // deathsound
 		0,              // speed
 		16*FRACUNIT,    // radius
 		32*FRACUNIT,    // height
diff --git a/src/info.h b/src/info.h
index b0683c172793ebd04662a80f4a74dd23be68bf3d..edd8541d423a0c28437cdb08ecc285943f520c1e 100644
--- a/src/info.h
+++ b/src/info.h
@@ -56,6 +56,9 @@ void A_BombShield(); // Obtained Bomb Shield
 void A_WaterShield(); // Obtained Water Shield
 void A_ForceShield(); // Obtained Force Shield
 void A_PityShield(); // Obtained Pity Shield. We're... sorry.
+void A_FlameShield(); // Obtained Flame Shield
+void A_BubbleShield(); // Obtained Bubble Shield
+void A_ThunderShield(); // Obtained Thunder Shield
 void A_GravityBox();
 void A_ScoreRise(); // Rise the score logo
 void A_ParticleSpawn();
@@ -211,6 +214,16 @@ void A_BrakFireShot();
 void A_BrakLobShot();
 void A_NapalmScatter();
 void A_SpawnFreshCopy();
+void A_FlickySpawn();
+void A_FlickyAim();
+void A_FlickyFly();
+void A_FlickySoar();
+void A_FlickyCoast();
+void A_FlickyHop();
+void A_FlickyFlounder();
+void A_FlickyCheck();
+void A_FlickyHeightCheck();
+void A_FlickyFlutter();
 
 // ratio of states to sprites to mobj types is roughly 6 : 1 : 1
 #define NUMMOBJFREESLOTS 256
@@ -351,6 +364,9 @@ typedef enum sprite
 	SPR_TVRC, // ReCycler
 	SPR_TV1K, // 1,000 points  (1 K)
 	SPR_TVTK, // 10,000 points (Ten K)
+	SPR_TVFL, // FLame shield
+	SPR_TVBB, // BuBble shield
+	SPR_TVZP, // Thunder shield (ZaP)
 
 	// Projectiles
 	SPR_MISL,
@@ -435,18 +451,32 @@ typedef enum sprite
 	SPR_ELEM, // Elemental Shield Orb and Fire
 	SPR_FORC, // Force Shield Orb
 	SPR_PITY, // Pity Shield Orb
+	SPR_FIRS, // Flame Shield Orb
+	SPR_BUBS, // Bubble Shield Orb
+	SPR_ZAPS, // Thunder Shield Orb
 	SPR_IVSP, // invincibility sparkles
 	SPR_SSPK, // Super Sonic Spark
 
 	SPR_GOAL, // Special Stage goal (here because lol NiGHTS)
 
-	// Freed Animals
-	SPR_BIRD, // Birdie freed!
-	SPR_BUNY, // Bunny freed!
-	SPR_MOUS, // Mouse
-	SPR_CHIC, // Chicken
-	SPR_COWZ, // Cow
-	SPR_RBRD, // Red Birdie in Bubble
+	// Flickies
+	SPR_FBUB, // Flicky-sized bubble
+	SPR_FL01, // Bluebird
+	SPR_FL02, // Rabbit
+	SPR_FL03, // Chicken
+	SPR_FL04, // Seal
+	SPR_FL05, // Pig
+	SPR_FL06, // Chipmunk
+	SPR_FL07, // Penguin
+	SPR_FL08, // Fish
+	SPR_FL09, // Ram
+	SPR_FL10, // Puffin
+	SPR_FL11, // Cow
+	SPR_FL12, // Rat
+	SPR_FL13, // Bear
+	SPR_FL14, // Dove
+	SPR_FL15, // Cat
+	SPR_FL16, // Canary
 
 	// Springs
 	SPR_SPRY, // yellow spring
@@ -466,6 +496,8 @@ typedef enum sprite
 	SPR_SMOK,
 	SPR_BUBL, // Bubble
 	SPR_WZAP,
+	SPR_DUST, // Spindash dust
+	SPR_FPRT, // Spindash dust (flame)
 	SPR_TFOG, // Teleport Fog
 	SPR_SEED, // Sonic CD flower seed
 	SPR_PRTL, // Particle (for fans, etc.)
@@ -1723,7 +1755,7 @@ typedef enum state
 	S_SPIKEBALL7,
 	S_SPIKEBALL8,
 
-	// Fire Shield's Spawn
+	// Elemental Shield's Spawn
 	S_SPINFIRE1,
 	S_SPINFIRE2,
 	S_SPINFIRE3,
@@ -1797,6 +1829,9 @@ typedef enum state
 	S_RECYCLER_BOX,
 	S_SCORE1K_BOX,
 	S_SCORE10K_BOX,
+	S_FLAMEAURA_BOX,
+	S_BUBBLEWRAP_BOX,
+	S_THUNDERCOIN_BOX,
 
 	// Gold Repeat Monitor States (one per box)
 	S_PITY_GOLDBOX,
@@ -1809,6 +1844,9 @@ typedef enum state
 	S_INVULN_GOLDBOX,
 	S_EGGMAN_GOLDBOX,
 	S_GRAVITY_GOLDBOX,
+	S_FLAMEAURA_GOLDBOX,
+	S_BUBBLEWRAP_GOLDBOX,
+	S_THUNDERCOIN_GOLDBOX,
 
 	// Team Ring Boxes (these are special)
 	S_RING_REDBOX1,
@@ -1870,6 +1908,15 @@ typedef enum state
 	S_SCORE10K_ICON1,
 	S_SCORE10K_ICON2,
 
+	S_FLAMEAURA_ICON1,
+	S_FLAMEAURA_ICON2,
+
+	S_BUBBLEWRAP_ICON1,
+	S_BUBBLEWRAP_ICON2,
+
+	S_THUNDERCOIN_ICON1,
+	S_THUNDERCOIN_ICON2,
+
 	// ---
 
 	S_ROCKET,
@@ -2241,6 +2288,7 @@ typedef enum state
 	S_MAGN10,
 	S_MAGN11,
 	S_MAGN12,
+	S_MAGN13,
 
 	S_FORC1,
 	S_FORC2,
@@ -2264,6 +2312,8 @@ typedef enum state
 	S_FORC19,
 	S_FORC20,
 
+	S_FORC21,
+
 	S_ELEM1,
 	S_ELEM2,
 	S_ELEM3,
@@ -2277,6 +2327,9 @@ typedef enum state
 	S_ELEM11,
 	S_ELEM12,
 
+	S_ELEM13,
+	S_ELEM14,
+
 	S_ELEMF1,
 	S_ELEMF2,
 	S_ELEMF3,
@@ -2285,6 +2338,8 @@ typedef enum state
 	S_ELEMF6,
 	S_ELEMF7,
 	S_ELEMF8,
+	S_ELEMF9,
+	S_ELEMF10,
 
 	S_PITY1,
 	S_PITY2,
@@ -2297,6 +2352,84 @@ typedef enum state
 	S_PITY9,
 	S_PITY10,
 
+	S_FIRS1,
+	S_FIRS2,
+	S_FIRS3,
+	S_FIRS4,
+	S_FIRS5,
+	S_FIRS6,
+	S_FIRS7,
+	S_FIRS8,
+	S_FIRS9,
+
+	S_FIRS10,
+	S_FIRS11,
+
+	S_FIRSB1,
+	S_FIRSB2,
+	S_FIRSB3,
+	S_FIRSB4,
+	S_FIRSB5,
+	S_FIRSB6,
+	S_FIRSB7,
+	S_FIRSB8,
+	S_FIRSB9,
+
+	S_FIRSB10,
+
+	S_BUBS1,
+	S_BUBS2,
+	S_BUBS3,
+	S_BUBS4,
+	S_BUBS5,
+	S_BUBS6,
+	S_BUBS7,
+	S_BUBS8,
+	S_BUBS9,
+
+	S_BUBS10,
+	S_BUBS11,
+
+	S_BUBSB1,
+	S_BUBSB2,
+	S_BUBSB3,
+	S_BUBSB4,
+
+	S_BUBSB5,
+	S_BUBSB6,
+
+	S_ZAPS1,
+	S_ZAPS2,
+	S_ZAPS3,
+	S_ZAPS4,
+	S_ZAPS5,
+	S_ZAPS6,
+	S_ZAPS7,
+	S_ZAPS8,
+	S_ZAPS9,
+	S_ZAPS10,
+	S_ZAPS11,
+	S_ZAPS12,
+	S_ZAPS13, // blank frame
+	S_ZAPS14,
+	S_ZAPS15,
+	S_ZAPS16,
+
+	S_ZAPSB1, // blank frame
+	S_ZAPSB2,
+	S_ZAPSB3,
+	S_ZAPSB4,
+	S_ZAPSB5,
+	S_ZAPSB6,
+	S_ZAPSB7,
+	S_ZAPSB8,
+	S_ZAPSB9,
+	S_ZAPSB10,
+	S_ZAPSB11, // blank frame
+
+	//Thunder spark
+	S_THUNDERCOIN_SPARK,
+
 	// Invincibility Sparkles
 	S_IVSP,
 
@@ -2307,43 +2440,133 @@ typedef enum state
 	S_SSPK4,
 	S_SSPK5,
 
-	// Freed Birdie
-	S_BIRD1,
-	S_BIRD2,
-	S_BIRD3,
-
-	// Freed Bunny
-	S_BUNNY1,
-	S_BUNNY2,
-	S_BUNNY3,
-	S_BUNNY4,
-	S_BUNNY5,
-	S_BUNNY6,
-	S_BUNNY7,
-	S_BUNNY8,
-	S_BUNNY9,
-	S_BUNNY10,
-
-	// Freed Mouse
-	S_MOUSE1,
-	S_MOUSE2,
-
-	// Freed Chicken
-	S_CHICKEN1,
-	S_CHICKENHOP,
-	S_CHICKENFLY1,
-	S_CHICKENFLY2,
-
-	// Freed Cow
-	S_COW1,
-	S_COW2,
-	S_COW3,
-	S_COW4,
-
-	// Red Birdie in Bubble
-	S_RBIRD1,
-	S_RBIRD2,
-	S_RBIRD3,
+	// Flicky-sized bubble
+	S_FLICKY_BUBBLE,
+
+	// Bluebird
+	S_FLICKY_01_OUT,
+	S_FLICKY_01_FLAP1,
+	S_FLICKY_01_FLAP2,
+	S_FLICKY_01_FLAP3,
+
+	// Rabbit
+	S_FLICKY_02_OUT,
+	S_FLICKY_02_AIM,
+	S_FLICKY_02_HOP,
+	S_FLICKY_02_UP,
+	S_FLICKY_02_DOWN,
+
+	// Chicken
+	S_FLICKY_03_OUT,
+	S_FLICKY_03_AIM,
+	S_FLICKY_03_HOP,
+	S_FLICKY_03_UP,
+	S_FLICKY_03_FLAP1,
+	S_FLICKY_03_FLAP2,
+
+	// Seal
+	S_FLICKY_04_OUT,
+	S_FLICKY_04_AIM,
+	S_FLICKY_04_HOP,
+	S_FLICKY_04_UP,
+	S_FLICKY_04_DOWN,
+	S_FLICKY_04_SWIM1,
+	S_FLICKY_04_SWIM2,
+	S_FLICKY_04_SWIM3,
+	S_FLICKY_04_SWIM4,
+
+	// Pig
+	S_FLICKY_05_OUT,
+	S_FLICKY_05_AIM,
+	S_FLICKY_05_HOP,
+	S_FLICKY_05_UP,
+	S_FLICKY_05_DOWN,
+
+	// Chipmunk
+	S_FLICKY_06_OUT,
+	S_FLICKY_06_AIM,
+	S_FLICKY_06_HOP,
+	S_FLICKY_06_UP,
+	S_FLICKY_06_DOWN,
+
+	// Penguin
+	S_FLICKY_07_OUT,
+	S_FLICKY_07_AIML,
+	S_FLICKY_07_HOPL,
+	S_FLICKY_07_UPL,
+	S_FLICKY_07_DOWNL,
+	S_FLICKY_07_AIMR,
+	S_FLICKY_07_HOPR,
+	S_FLICKY_07_UPR,
+	S_FLICKY_07_DOWNR,
+	S_FLICKY_07_SWIM1,
+	S_FLICKY_07_SWIM2,
+	S_FLICKY_07_SWIM3,
+
+	// Fish
+	S_FLICKY_08_OUT,
+	S_FLICKY_08_AIM,
+	S_FLICKY_08_HOP,
+	S_FLICKY_08_FLAP1,
+	S_FLICKY_08_FLAP2,
+	S_FLICKY_08_FLAP3,
+	S_FLICKY_08_FLAP4,
+	S_FLICKY_08_SWIM1,
+	S_FLICKY_08_SWIM2,
+	S_FLICKY_08_SWIM3,
+	S_FLICKY_08_SWIM4,
+
+	// Ram
+	S_FLICKY_09_OUT,
+	S_FLICKY_09_AIM,
+	S_FLICKY_09_HOP,
+	S_FLICKY_09_UP,
+	S_FLICKY_09_DOWN,
+
+	// Puffin
+	S_FLICKY_10_OUT,
+	S_FLICKY_10_FLAP1,
+	S_FLICKY_10_FLAP2,
+
+	// Cow
+	S_FLICKY_11_OUT,
+	S_FLICKY_11_AIM,
+	S_FLICKY_11_RUN1,
+	S_FLICKY_11_RUN2,
+	S_FLICKY_11_RUN3,
+
+	// Rat
+	S_FLICKY_12_OUT,
+	S_FLICKY_12_AIM,
+	S_FLICKY_12_RUN1,
+	S_FLICKY_12_RUN2,
+	S_FLICKY_12_RUN3,
+
+	// Bear
+	S_FLICKY_13_OUT,
+	S_FLICKY_13_AIM,
+	S_FLICKY_13_HOP,
+	S_FLICKY_13_UP,
+	S_FLICKY_13_DOWN,
+
+	// Dove
+	S_FLICKY_14_OUT,
+	S_FLICKY_14_FLAP1,
+	S_FLICKY_14_FLAP2,
+	S_FLICKY_14_FLAP3,
+
+	// Cat
+	S_FLICKY_15_OUT,
+	S_FLICKY_15_AIM,
+	S_FLICKY_15_HOP,
+	S_FLICKY_15_UP,
+	S_FLICKY_15_DOWN,
+
+	// Canary
+	S_FLICKY_16_OUT,
+	S_FLICKY_16_FLAP1,
+	S_FLICKY_16_FLAP2,
+	S_FLICKY_16_FLAP3,
 
 	S_YELLOWSPRING,
 	S_YELLOWSPRING2,
@@ -2457,6 +2680,20 @@ typedef enum state
 
 	S_WATERZAP,
 
+	// Spindash dust
+	S_SPINDUST1,
+	S_SPINDUST2,
+	S_SPINDUST3,
+	S_SPINDUST4,
+	S_SPINDUST_BUBBLE1,
+	S_SPINDUST_BUBBLE2,
+	S_SPINDUST_BUBBLE3,
+	S_SPINDUST_BUBBLE4,
+	S_SPINDUST_FIRE1,
+	S_SPINDUST_FIRE2,
+	S_SPINDUST_FIRE3,
+	S_SPINDUST_FIRE4,
+
 	S_FOG1,
 	S_FOG2,
 	S_FOG3,
@@ -2829,6 +3066,7 @@ typedef enum state
 	S_NIGHTOPIANHELPER6,
 	S_NIGHTOPIANHELPER7,
 	S_NIGHTOPIANHELPER8,
+	S_NIGHTOPIANHELPER9,
 
 	S_CRUMBLE1,
 	S_CRUMBLE2,
@@ -2852,10 +3090,10 @@ typedef enum state
 	S_SPRK16,
 
 	// Robot Explosion
+	S_XPLD_FLICKY,
 	S_XPLD1,
 	S_XPLD2,
-	S_XPLD3,
-	S_XPLD4,
+	S_XPLD_EGGTRAP,
 
 	// Underwater Explosion
 	S_WPLD1,
@@ -3074,6 +3312,9 @@ typedef enum mobj_type
 	MT_RECYCLER_BOX,
 	MT_SCORE1K_BOX,
 	MT_SCORE10K_BOX,
+	MT_FLAMEAURA_BOX,
+	MT_BUBBLEWRAP_BOX,
+	MT_THUNDERCOIN_BOX,
 
 	// Monitor boxes -- repeating (big) boxes
 	MT_PITY_GOLDBOX,
@@ -3086,6 +3327,9 @@ typedef enum mobj_type
 	MT_INVULN_GOLDBOX,
 	MT_EGGMAN_GOLDBOX,
 	MT_GRAVITY_GOLDBOX,
+	MT_FLAMEAURA_GOLDBOX,
+	MT_BUBBLEWRAP_GOLDBOX,
+	MT_THUNDERCOIN_GOLDBOX,
 
 	// Monitor boxes -- special
 	MT_RING_REDBOX,
@@ -3108,6 +3352,9 @@ typedef enum mobj_type
 	MT_RECYCLER_ICON,
 	MT_SCORE1K_ICON,
 	MT_SCORE10K_ICON,
+	MT_FLAMEAURA_ICON,
+	MT_BUBBLEWRAP_ICON,
+	MT_THUNDERCOIN_ICON,
 
 	// Projectiles
 	MT_ROCKET,
@@ -3260,22 +3507,36 @@ typedef enum mobj_type
 	MT_EGGSTATUE2,
 
 	// Powerup Indicators
-	MT_GREENORB, // Elemental shield mobj
-	MT_YELLOWORB, // Attract shield mobj
-	MT_BLUEORB, // Force shield mobj
-	MT_BLACKORB, // Armageddon shield mobj
-	MT_WHITEORB, // Whirlwind shield mobj
-	MT_PITYORB, // Pity shield mobj
-	MT_IVSP, // invincibility sparkles
+	MT_ELEMENTAL_ORB, // Elemental shield mobj
+	MT_ATTRACT_ORB, // Attract shield mobj
+	MT_FORCE_ORB, // Force shield mobj
+	MT_ARMAGEDDON_ORB, // Armageddon shield mobj
+	MT_WHIRLWIND_ORB, // Whirlwind shield mobj
+	MT_PITY_ORB, // Pity shield mobj
+	MT_FLAMEAURA_ORB, // Flame shield mobj
+	MT_BUBBLEWRAP_ORB, // Bubble shield mobj
+	MT_THUNDERCOIN_ORB, // Thunder shield mobj
+	MT_THUNDERCOIN_SPARK, // Thunder spark
+	MT_IVSP, // Invincibility sparkles
 	MT_SUPERSPARK, // Super Sonic Spark
 
-	// Freed Animals
-	MT_BIRD, // Birdie freed!
-	MT_BUNNY, // Bunny freed!
-	MT_MOUSE, // Mouse
-	MT_CHICKEN, // Chicken
-	MT_COW, // Cow
-	MT_REDBIRD, // Red Birdie in Bubble
+	// Flickies
+	MT_FLICKY_01, // Bluebird
+	MT_FLICKY_02, // Rabbit
+	MT_FLICKY_03, // Chicken
+	MT_FLICKY_04, // Seal
+	MT_FLICKY_05, // Pig
+	MT_FLICKY_06, // Chipmunk
+	MT_FLICKY_07, // Penguin
+	MT_FLICKY_08, // Fish
+	MT_FLICKY_09, // Ram
+	MT_FLICKY_10, // Puffin
+	MT_FLICKY_11, // Cow
+	MT_FLICKY_12, // Rat
+	MT_FLICKY_13, // Bear
+	MT_FLICKY_14, // Dove
+	MT_FLICKY_15, // Cat
+	MT_FLICKY_16, // Canary
 
 	// Environmental Effects
 	MT_RAIN, // Rain
@@ -3286,6 +3547,7 @@ typedef enum mobj_type
 	MT_MEDIUMBUBBLE, // medium bubble
 	MT_EXTRALARGEBUBBLE, // extra large bubble
 	MT_WATERZAP,
+	MT_SPINDUST, // Spindash dust
 	MT_TFOG,
 	MT_SEED,
 	MT_PARTICLE,
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 6e0457ce8f633031a5ad02b26de2578d38997c89..def0ad1b37dc42460e9fb3675638e281a93b6236 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -27,7 +27,6 @@
 
 #define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!");
 
-
 boolean luaL_checkboolean(lua_State *L, int narg) {
 	luaL_checktype(L, narg, LUA_TBOOLEAN);
 	return lua_toboolean(L, narg);
@@ -205,6 +204,41 @@ static int lib_pClosestPointOnLine(lua_State *L)
 	return 2;
 }
 
+static int lib_pPointOnLineSide(lua_State *L)
+{
+	int n = lua_gettop(L);
+	fixed_t x = luaL_checkfixed(L, 1);
+	fixed_t y = luaL_checkfixed(L, 2);
+	//HUDSAFE
+	if (lua_isuserdata(L, 3)) // use a real linedef to get our points
+	{
+		line_t *line = *((line_t **)luaL_checkudata(L, 3, META_LINE));
+		if (!line)
+			return LUA_ErrInvalid(L, "line_t");
+		lua_pushinteger(L, P_PointOnLineSide(x, y, line));
+	}
+	else // use custom coordinates of our own!
+	{
+		vertex_t v1, v2; // fake vertexes
+		line_t junk; // fake linedef
+
+		if (n < 6)
+			return luaL_error(L, "arguments 3 to 6 not all given (expected 4 fixed-point integers)");
+
+		v1.x = luaL_checkfixed(L, 3);
+		v1.y = luaL_checkfixed(L, 4);
+		v2.x = luaL_checkfixed(L, 5);
+		v2.y = luaL_checkfixed(L, 6);
+
+		junk.v1 = &v1;
+		junk.v2 = &v2;
+		junk.dx = v2.x - v1.x;
+		junk.dy = v2.y - v1.y;
+		lua_pushinteger(L, P_PointOnLineSide(x, y, &junk));
+	}
+	return 1;
+}
+
 // P_ENEMY
 /////////////
 
@@ -801,6 +835,16 @@ static int lib_pDoJumpShield(lua_State *L)
 	return 0;
 }
 
+static int lib_pDoBubbleBounce(lua_State *L)
+{
+	player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+	NOHUD
+	if (!player)
+		return LUA_ErrInvalid(L, "player_t");
+	P_DoBubbleBounce(player);
+	return 0;
+}
+
 static int lib_pBlackOw(lua_State *L)
 {
 	player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
@@ -811,13 +855,14 @@ static int lib_pBlackOw(lua_State *L)
 	return 0;
 }
 
-static int lib_pElementalFireTrail(lua_State *L)
+static int lib_pElementalFire(lua_State *L)
 {
 	player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+	boolean cropcircle = lua_optboolean(L, 2);
 	NOHUD
 	if (!player)
 		return LUA_ErrInvalid(L, "player_t");
-	P_ElementalFireTrail(player);
+	P_ElementalFire(player, cropcircle);
 	return 0;
 }
 
@@ -872,10 +917,11 @@ static int lib_pReturnThrustY(lua_State *L)
 static int lib_pLookForEnemies(lua_State *L)
 {
 	player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
+	boolean nonenemies = lua_opttrueboolean(L, 2);
 	NOHUD
 	if (!player)
 		return LUA_ErrInvalid(L, "player_t");
-	lua_pushboolean(L, P_LookForEnemies(player));
+	lua_pushboolean(L, P_LookForEnemies(player, nonenemies));
 	return 1;
 }
 
@@ -2035,6 +2081,7 @@ static luaL_Reg lib[] = {
 	// p_maputil
 	{"P_AproxDistance",lib_pAproxDistance},
 	{"P_ClosestPointOnLine",lib_pClosestPointOnLine},
+	{"P_PointOnLineSide",lib_pPointOnLineSide},
 
 	// p_enemy
 	{"P_CheckMeleeRange", lib_pCheckMeleeRange},
@@ -2092,8 +2139,9 @@ static luaL_Reg lib[] = {
 	{"P_GivePlayerLives",lib_pGivePlayerLives},
 	{"P_ResetScore",lib_pResetScore},
 	{"P_DoJumpShield",lib_pDoJumpShield},
+	{"P_DoBubbleBounce",lib_pDoBubbleBounce},
 	{"P_BlackOw",lib_pBlackOw},
-	{"P_ElementalFireTrail",lib_pElementalFireTrail},
+	{"P_ElementalFire",lib_pElementalFire},
 	{"P_DoPlayerExit",lib_pDoPlayerExit},
 	{"P_InstaThrust",lib_pInstaThrust},
 	{"P_ReturnThrustX",lib_pReturnThrustX},
diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c
new file mode 100644
index 0000000000000000000000000000000000000000..33f350d6912863df71db33a36f070af221c38f34
--- /dev/null
+++ b/src/lua_blockmaplib.c
@@ -0,0 +1,266 @@
+// SONIC ROBO BLAST 2
+//-----------------------------------------------------------------------------
+// Copyright (C) 2016 by Iestyn "Monster Iestyn" Jealous.
+// Copyright (C) 2016 by Sonic Team Junior.
+//
+// This program is free software distributed under the
+// terms of the GNU General Public License, version 2.
+// See the 'LICENSE' file for more details.
+//-----------------------------------------------------------------------------
+/// \file  lua_blockmaplib.c
+/// \brief blockmap library for Lua scripting
+
+#include "doomdef.h"
+#ifdef HAVE_BLUA
+#include "p_local.h"
+#include "r_main.h" // validcount
+#include "lua_script.h"
+#include "lua_libs.h"
+//#include "lua_hud.h" // hud_running errors
+
+static const char *const search_opt[] = {
+	"objects",
+	"lines",
+	NULL};
+
+// a quickly-made function pointer typedef used by lib_searchBlockmap...
+// return values:
+// 0 - normal, no interruptions
+// 1 - stop search through current block
+// 2 - stop search completely
+typedef UINT8 (*blockmap_func)(lua_State *, INT32, INT32, mobj_t *);
+
+static boolean blockfuncerror = false; // errors should only print once per search blockmap call
+
+// Helper function for "objects" search
+static UINT8 lib_searchBlockmap_Objects(lua_State *L, INT32 x, INT32 y, mobj_t *thing)
+{
+	mobj_t *mobj, *bnext = NULL;
+
+	if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
+		return 0;
+
+	// Check interaction with the objects in the blockmap.
+	for (mobj = blocklinks[y*bmapwidth + x]; mobj; mobj = bnext)
+	{
+		P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed!
+		if (mobj == thing)
+			continue; // our thing just found itself, so move on
+		lua_pushvalue(L, 1); // push function
+		LUA_PushUserdata(L, thing, META_MOBJ);
+		LUA_PushUserdata(L, mobj, META_MOBJ);
+		if (lua_pcall(gL, 2, 1, 0)) {
+			if (!blockfuncerror || cv_debug & DBG_LUA)
+				CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+			lua_pop(gL, 1);
+			blockfuncerror = true;
+			return 0; // *shrugs*
+		}
+		if (!lua_isnil(gL, -1))
+		{ // if nil, continue
+			if (lua_toboolean(gL, -1))
+				return 2; // stop whole search
+			else
+				return 1; // stop block search
+		}
+		lua_pop(gL, 1);
+		if (P_MobjWasRemoved(thing) // func just popped our thing, cannot continue.
+		|| (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue.
+		{
+			P_SetTarget(&bnext, NULL);
+			return (P_MobjWasRemoved(thing)) ? 2 : 1;
+		}
+	}
+	return 0;
+}
+
+// Helper function for "lines" search
+static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *thing)
+{
+	INT32 offset;
+	const INT32 *list; // Big blockmap
+#ifdef POLYOBJECTS
+	polymaplink_t *plink; // haleyjd 02/22/06
+#endif
+	line_t *ld;
+
+	if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
+		return 0;
+
+	offset = y*bmapwidth + x;
+
+#ifdef POLYOBJECTS
+	// haleyjd 02/22/06: consider polyobject lines
+	plink = polyblocklinks[offset];
+
+	while (plink)
+	{
+		polyobj_t *po = plink->po;
+
+		if (po->validcount != validcount) // if polyobj hasn't been checked
+		{
+			size_t i;
+			po->validcount = validcount;
+
+			for (i = 0; i < po->numLines; ++i)
+			{
+				if (po->lines[i]->validcount == validcount) // line has been checked
+					continue;
+				po->lines[i]->validcount = validcount;
+
+				lua_pushvalue(L, 1);
+				LUA_PushUserdata(L, thing, META_MOBJ);
+				LUA_PushUserdata(L, po->lines[i], META_LINE);
+				if (lua_pcall(gL, 2, 1, 0)) {
+					if (!blockfuncerror || cv_debug & DBG_LUA)
+						CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+					lua_pop(gL, 1);
+					blockfuncerror = true;
+					return 0; // *shrugs*
+				}
+				if (!lua_isnil(gL, -1))
+				{ // if nil, continue
+					if (lua_toboolean(gL, -1))
+						return 2; // stop whole search
+					else
+						return 1; // stop block search
+				}
+				lua_pop(gL, 1);
+				if (P_MobjWasRemoved(thing))
+					return 2;
+			}
+		}
+		plink = (polymaplink_t *)(plink->link.next);
+	}
+#endif
+
+	offset = *(blockmap + offset); // offset = blockmap[y*bmapwidth+x];
+
+	// First index is really empty, so +1 it.
+	for (list = blockmaplump + offset + 1; *list != -1; list++)
+	{
+		ld = &lines[*list];
+
+		if (ld->validcount == validcount)
+			continue; // Line has already been checked.
+
+		ld->validcount = validcount;
+
+		lua_pushvalue(L, 1);
+		LUA_PushUserdata(L, thing, META_MOBJ);
+		LUA_PushUserdata(L, ld, META_LINE);
+		if (lua_pcall(gL, 2, 1, 0)) {
+			if (!blockfuncerror || cv_debug & DBG_LUA)
+				CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+			lua_pop(gL, 1);
+			blockfuncerror = true;
+			return 0; // *shrugs*
+		}
+		if (!lua_isnil(gL, -1))
+		{ // if nil, continue
+			if (lua_toboolean(gL, -1))
+				return 2; // stop whole search
+			else
+				return 1; // stop block search
+		}
+		lua_pop(gL, 1);
+		if (P_MobjWasRemoved(thing))
+			return 2;
+	}
+	return 0; // Everything was checked.
+}
+
+// The searchBlockmap function
+// arguments: searchBlockmap(searchtype, function, mobj, [x1, x2, y1, y2])
+// return value:
+//   true = search completely uninteruppted,
+//   false = searching of at least one block stopped mid-way (including if the whole search was stopped)
+static int lib_searchBlockmap(lua_State *L)
+{
+	int searchtype = luaL_checkoption(L, 1, "objects", search_opt);
+	int n;
+	mobj_t *mobj;
+	INT32 xl, xh, yl, yh, bx, by;
+	fixed_t x1, x2, y1, y2;
+	boolean retval = true;
+	UINT8 funcret = 0;
+	blockmap_func searchFunc;
+
+	lua_remove(L, 1); // remove searchtype, stack is now function, mobj, [x1, x2, y1, y2]
+	luaL_checktype(L, 1, LUA_TFUNCTION);
+
+	switch (searchtype)
+	{
+		case 0: // "objects"
+		default:
+			searchFunc = lib_searchBlockmap_Objects;
+			break;
+		case 1: // "lines"
+			searchFunc = lib_searchBlockmap_Lines;
+			break;
+	}
+
+	// the mobj we are searching around, the "calling" mobj we could say
+	mobj = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
+	if (!mobj)
+		return LUA_ErrInvalid(L, "mobj_t");
+
+	n = lua_gettop(L);
+
+	if (n > 2) // specific x/y ranges have been supplied
+	{
+		if (n < 6)
+			return luaL_error(L, "arguments 4 to 6 not all given (expected 4 fixed-point integers)");
+
+		x1 = luaL_checkfixed(L, 3);
+		x2 = luaL_checkfixed(L, 4);
+		y1 = luaL_checkfixed(L, 5);
+		y2 = luaL_checkfixed(L, 6);
+	}
+	else // mobj and function only - search around mobj's radius by default
+	{
+		fixed_t radius = mobj->radius + MAXRADIUS;
+		x1 = mobj->x - radius;
+		x2 = mobj->x + radius;
+		y1 = mobj->y - radius;
+		y2 = mobj->y + radius;
+	}
+	lua_settop(L, 2); // pop everything except function, mobj
+
+	xl = (unsigned)(x1 - bmaporgx)>>MAPBLOCKSHIFT;
+	xh = (unsigned)(x2 - bmaporgx)>>MAPBLOCKSHIFT;
+	yl = (unsigned)(y1 - bmaporgy)>>MAPBLOCKSHIFT;
+	yh = (unsigned)(y2 - bmaporgy)>>MAPBLOCKSHIFT;
+
+	BMBOUNDFIX(xl, xh, yl, yh);
+
+	blockfuncerror = false; // reset
+	validcount++;
+	for (bx = xl; bx <= xh; bx++)
+		for (by = yl; by <= yh; by++)
+		{
+			funcret = searchFunc(L, bx, by, mobj);
+			// return value of searchFunc determines searchFunc's return value and/or when to stop
+			if (funcret == 2){ // stop whole search
+				lua_pushboolean(L, false); // return false
+				return 1;
+			}
+			else if (funcret == 1) // search was interrupted for this block
+				retval = false; // this changes the return value, but doesn't stop the whole search
+			// else don't do anything, continue as normal
+			if (P_MobjWasRemoved(mobj)){ // ...unless the original object was removed
+				lua_pushboolean(L, false); // in which case we have to stop now regardless
+				return 1;
+			}	
+		}
+	lua_pushboolean(L, retval);
+	return 1;
+}
+
+int LUA_BlockmapLib(lua_State *L)
+{
+	lua_register(L, "searchBlockmap", lib_searchBlockmap);
+	return 0;
+}
+
+#endif
\ No newline at end of file
diff --git a/src/lua_hook.h b/src/lua_hook.h
index 97d447d2eafc38a8d0567a562c4833e672f6f74a..7192a2979e0da5a8e9368898cea8dc5670658d9d 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -43,6 +43,8 @@ enum hook {
 	hook_PlayerMsg,
 	hook_HurtMsg,
 	hook_PlayerSpawn,
+	hook_ShieldSpawn,
+	hook_ShieldSpecial,
 
 	hook_MAX // last hook
 };
@@ -60,7 +62,7 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which);
 #define LUAh_MobjMoveCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjMoveCollide) // Hook for PIT_CheckThing by (tmthing) mobj type
 boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher); // Hook for P_TouchSpecialThing by mobj type
 #define LUAh_MobjFuse(mo) LUAh_MobjHook(mo, hook_MobjFuse) // Hook for mobj->fuse == 0 by mobj type
-#define LUAh_MobjThinker(mo) LUAh_MobjHook(mo, hook_MobjThinker) // Hook for P_MobjThinker or P_SceneryThinker by mobj type
+boolean LUAh_MobjThinker(mobj_t *mo); // Hook for P_MobjThinker or P_SceneryThinker by mobj type
 #define LUAh_BossThinker(mo) LUAh_MobjHook(mo, hook_BossThinker) // Hook for P_GenericBossThinker by mobj type
 UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); // Hook for P_DamageMobj by mobj type (Should mobj take damage?)
 boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); // Hook for P_DamageMobj by mobj type (Mobj actually takes damage!)
@@ -77,5 +79,7 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook
 boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages
 boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); // Hook for hurt messages
 #define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer
+#define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb
+#define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities
 
 #endif
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index e95b75eda44cd9f41fb86f805d261f2046b2d2a4..f7ea252248d145c4360bf6663988798dacba295d 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -54,6 +54,8 @@ const char *const hookNames[hook_MAX+1] = {
 	"PlayerMsg",
 	"HurtMsg",
 	"PlayerSpawn",
+	"ShieldSpawn",
+	"ShieldSpecial",
 	NULL
 };
 
@@ -74,12 +76,30 @@ typedef struct hook_s* hook_p;
 
 #define FMT_HOOKID "hook_%d"
 
+// For each mobj type, a linked list to its thinker and collision hooks.
+// That way, we don't have to iterate through all the hooks.
+// We could do that with all other mobj hooks, but it would probably just be
+// a waste of memory since they are only called occasionally. Probably...
+static hook_p mobjthinkerhooks[NUMMOBJTYPES];
+static hook_p mobjcollidehooks[NUMMOBJTYPES];
+
+// For each mobj type, a linked list for other mobj hooks
+static hook_p mobjhooks[NUMMOBJTYPES];
+
+// A linked list for player hooks
+static hook_p playerhooks;
+
+// A linked list for linedef executor hooks
+static hook_p linedefexecutorhooks;
+
+// For other hooks, a unique linked list
 hook_p roothook;
 
 // Takes hook, function, and additional arguments (mobj type to act on, etc.)
 static int lib_addHook(lua_State *L)
 {
 	static struct hook_s hook = {NULL, 0, 0, {0}, false};
+	static UINT32 nextid;
 	hook_p hookp, *lastp;
 
 	hook.type = luaL_checkoption(L, 1, NULL, hookNames);
@@ -109,6 +129,7 @@ static int lib_addHook(lua_State *L)
 		hook.s.mt = MT_NULL;
 		if (lua_isnumber(L, 2))
 			hook.s.mt = lua_tonumber(L, 2);
+		luaL_argcheck(L, hook.s.mt < NUMMOBJTYPES, 2, "invalid mobjtype_t");
 		break;
 	case hook_BotAI:
 		hook.s.skinname = NULL;
@@ -141,18 +162,49 @@ static int lib_addHook(lua_State *L)
 
 	hooksAvailable[hook.type/8] |= 1<<(hook.type%8);
 
-	// iterate the hook metadata structs
 	// set hook.id to the highest id + 1
-	// set lastp to the last hook struct's "next" pointer.
-	lastp = &roothook;
-	hook.id = 0;
-	for (hookp = roothook; hookp; hookp = hookp->next)
+	hook.id = nextid++;
+
+	// Special cases for some hook types (see the comments above mobjthinkerhooks declaration)
+	switch(hook.type)
 	{
-		if (hookp->id >= hook.id)
-			hook.id = hookp->id+1;
-		lastp = &hookp->next;
+	case hook_MobjThinker:
+		lastp = &mobjthinkerhooks[hook.s.mt];
+		break;
+	case hook_MobjCollide:
+	case hook_MobjMoveCollide:
+		lastp = &mobjcollidehooks[hook.s.mt];
+		break;
+	case hook_MobjSpawn:
+	case hook_TouchSpecial:
+	case hook_MobjFuse:
+	case hook_BossThinker:
+	case hook_ShouldDamage:
+	case hook_MobjDamage:
+	case hook_MobjDeath:
+	case hook_BossDeath:
+	case hook_MobjRemoved:
+		lastp = &mobjhooks[hook.s.mt];
+		break;
+	case hook_JumpSpecial:
+	case hook_AbilitySpecial:
+	case hook_SpinSpecial:
+	case hook_JumpSpinSpecial:
+	case hook_PlayerSpawn:
+		lastp = &playerhooks;
+		break;
+	case hook_LinedefExecute:
+		lastp = &linedefexecutorhooks;
+		break;
+	default:
+		lastp = &roothook;
+		break;
 	}
 
+	// iterate the hook metadata structs
+	// set lastp to the last hook struct's "next" pointer.
+	for (hookp = *lastp; hookp; hookp = hookp->next)
+		lastp = &hookp->next;
 	// allocate a permanent memory struct to stuff hook.
 	hookp = ZZ_Alloc(sizeof(struct hook_s));
 	memcpy(hookp, &hook, sizeof(struct hook_s));
@@ -183,9 +235,29 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
 
 	lua_settop(gL, 0);
 
-	for (hookp = roothook; hookp; hookp = hookp->next)
-		if (hookp->type == which
-		&& (hookp->s.mt == MT_NULL || hookp->s.mt == mo->type))
+	// Look for all generic mobj hooks
+	for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
+		if (hookp->type == which)
+		{
+			if (lua_gettop(gL) == 0)
+				LUA_PushUserdata(gL, mo, META_MOBJ);
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -2);
+			if (lua_pcall(gL, 1, 1, 0)) {
+				if (!hookp->error || cv_debug & DBG_LUA)
+					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+				lua_pop(gL, 1);
+				hookp->error = true;
+				continue;
+			}
+			if (lua_toboolean(gL, -1))
+				hooked = true;
+			lua_pop(gL, 1);
+		}
+
+	for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next)
+		if (hookp->type == which)
 		{
 			if (lua_gettop(gL) == 0)
 				LUA_PushUserdata(gL, mo, META_MOBJ);
@@ -217,7 +289,7 @@ boolean LUAh_PlayerHook(player_t *plr, enum hook which)
 
 	lua_settop(gL, 0);
 
-	for (hookp = roothook; hookp; hookp = hookp->next)
+	for (hookp = playerhooks; hookp; hookp = hookp->next)
 		if (hookp->type == which)
 		{
 			if (lua_gettop(gL) == 0)
@@ -338,9 +410,38 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
 
 	lua_settop(gL, 0);
 
-	for (hookp = roothook; hookp; hookp = hookp->next)
-		if (hookp->type == which
-		&& (hookp->s.mt == MT_NULL || hookp->s.mt == thing1->type))
+	// Look for all generic mobj collision hooks
+	for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next)
+		if (hookp->type == which)
+		{
+			if (lua_gettop(gL) == 0)
+			{
+				LUA_PushUserdata(gL, thing1, META_MOBJ);
+				LUA_PushUserdata(gL, thing2, META_MOBJ);
+			}
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -3);
+			lua_pushvalue(gL, -3);
+			if (lua_pcall(gL, 2, 1, 0)) {
+				if (!hookp->error || cv_debug & DBG_LUA)
+					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+				lua_pop(gL, 1);
+				hookp->error = true;
+				continue;
+			}
+			if (!lua_isnil(gL, -1))
+			{ // if nil, leave shouldCollide = 0.
+				if (lua_toboolean(gL, -1))
+					shouldCollide = 1; // Force yes
+				else
+					shouldCollide = 2; // Force no
+			}
+			lua_pop(gL, 1);
+		}
+
+	for (hookp = mobjcollidehooks[thing1->type]; hookp; hookp = hookp->next)
+		if (hookp->type == which)
 		{
 			if (lua_gettop(gL) == 0)
 			{
@@ -372,6 +473,59 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
 	return shouldCollide;
 }
 
+// Hook for mobj thinkers
+boolean LUAh_MobjThinker(mobj_t *mo)
+{
+	hook_p hookp;
+	boolean hooked = false;
+	if (!gL || !(hooksAvailable[hook_MobjThinker/8] & (1<<(hook_MobjThinker%8))))
+		return false;
+
+	lua_settop(gL, 0);
+
+	// Look for all generic mobj thinker hooks
+	for (hookp = mobjthinkerhooks[MT_NULL]; hookp; hookp = hookp->next)
+	{
+		if (lua_gettop(gL) == 0)
+			LUA_PushUserdata(gL, mo, META_MOBJ);
+		lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+		lua_gettable(gL, LUA_REGISTRYINDEX);
+		lua_pushvalue(gL, -2);
+		if (lua_pcall(gL, 1, 1, 0)) {
+			if (!hookp->error || cv_debug & DBG_LUA)
+				CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+			lua_pop(gL, 1);
+			hookp->error = true;
+			continue;
+		}
+		if (lua_toboolean(gL, -1))
+			hooked = true;
+		lua_pop(gL, 1);
+	}
+
+	for (hookp = mobjthinkerhooks[mo->type]; hookp; hookp = hookp->next)
+	{
+		if (lua_gettop(gL) == 0)
+			LUA_PushUserdata(gL, mo, META_MOBJ);
+		lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+		lua_gettable(gL, LUA_REGISTRYINDEX);
+		lua_pushvalue(gL, -2);
+		if (lua_pcall(gL, 1, 1, 0)) {
+			if (!hookp->error || cv_debug & DBG_LUA)
+				CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+			lua_pop(gL, 1);
+			hookp->error = true;
+			continue;
+		}
+		if (lua_toboolean(gL, -1))
+			hooked = true;
+		lua_pop(gL, 1);
+	}
+
+	lua_settop(gL, 0);
+	return hooked;
+}
+
 // Hook for P_TouchSpecialThing by mobj type
 boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
 {
@@ -382,9 +536,33 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
 
 	lua_settop(gL, 0);
 
-	for (hookp = roothook; hookp; hookp = hookp->next)
-		if (hookp->type == hook_TouchSpecial
-		&& (hookp->s.mt == MT_NULL || hookp->s.mt == special->type))
+	// Look for all generic touch special hooks
+	for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
+		if (hookp->type == hook_TouchSpecial)
+		{
+			if (lua_gettop(gL) == 0)
+			{
+				LUA_PushUserdata(gL, special, META_MOBJ);
+				LUA_PushUserdata(gL, toucher, META_MOBJ);
+			}
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -3);
+			lua_pushvalue(gL, -3);
+			if (lua_pcall(gL, 2, 1, 0)) {
+				if (!hookp->error || cv_debug & DBG_LUA)
+					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+				lua_pop(gL, 1);
+				hookp->error = true;
+				continue;
+			}
+			if (lua_toboolean(gL, -1))
+				hooked = true;
+			lua_pop(gL, 1);
+		}
+
+	for (hookp = mobjhooks[special->type]; hookp; hookp = hookp->next)
+		if (hookp->type == hook_TouchSpecial)
 		{
 			if (lua_gettop(gL) == 0)
 			{
@@ -421,9 +599,42 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
 
 	lua_settop(gL, 0);
 
-	for (hookp = roothook; hookp; hookp = hookp->next)
-		if (hookp->type == hook_ShouldDamage
-		&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
+	// Look for all generic should damage hooks
+	for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
+		if (hookp->type == hook_ShouldDamage)
+		{
+			if (lua_gettop(gL) == 0)
+			{
+				LUA_PushUserdata(gL, target, META_MOBJ);
+				LUA_PushUserdata(gL, inflictor, META_MOBJ);
+				LUA_PushUserdata(gL, source, META_MOBJ);
+				lua_pushinteger(gL, damage);
+			}
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -5);
+			lua_pushvalue(gL, -5);
+			lua_pushvalue(gL, -5);
+			lua_pushvalue(gL, -5);
+			if (lua_pcall(gL, 4, 1, 0)) {
+				if (!hookp->error || cv_debug & DBG_LUA)
+					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+				lua_pop(gL, 1);
+				hookp->error = true;
+				continue;
+			}
+			if (!lua_isnil(gL, -1))
+			{
+				if (lua_toboolean(gL, -1))
+					shouldDamage = 1; // Force yes
+				else
+					shouldDamage = 2; // Force no
+			}
+			lua_pop(gL, 1);
+		}
+
+	for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next)
+		if (hookp->type == hook_ShouldDamage)
 		{
 			if (lua_gettop(gL) == 0)
 			{
@@ -471,9 +682,37 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32
 
 	lua_settop(gL, 0);
 
-	for (hookp = roothook; hookp; hookp = hookp->next)
-		if (hookp->type == hook_MobjDamage
-		&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
+	// Look for all generic mobj damage hooks
+	for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
+		if (hookp->type == hook_MobjDamage)
+		{
+			if (lua_gettop(gL) == 0)
+			{
+				LUA_PushUserdata(gL, target, META_MOBJ);
+				LUA_PushUserdata(gL, inflictor, META_MOBJ);
+				LUA_PushUserdata(gL, source, META_MOBJ);
+				lua_pushinteger(gL, damage);
+			}
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -5);
+			lua_pushvalue(gL, -5);
+			lua_pushvalue(gL, -5);
+			lua_pushvalue(gL, -5);
+			if (lua_pcall(gL, 4, 1, 0)) {
+				if (!hookp->error || cv_debug & DBG_LUA)
+					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+				lua_pop(gL, 1);
+				hookp->error = true;
+				continue;
+			}
+			if (lua_toboolean(gL, -1))
+				hooked = true;
+			lua_pop(gL, 1);
+		}
+
+	for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next)
+		if (hookp->type == hook_MobjDamage)
 		{
 			if (lua_gettop(gL) == 0)
 			{
@@ -516,9 +755,35 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8
 
 	lua_settop(gL, 0);
 
-	for (hookp = roothook; hookp; hookp = hookp->next)
-		if (hookp->type == hook_MobjDeath
-		&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
+	// Look for all generic mobj death hooks
+	for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
+		if (hookp->type == hook_MobjDeath)
+		{
+			if (lua_gettop(gL) == 0)
+			{
+				LUA_PushUserdata(gL, target, META_MOBJ);
+				LUA_PushUserdata(gL, inflictor, META_MOBJ);
+				LUA_PushUserdata(gL, source, META_MOBJ);
+			}
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -4);
+			lua_pushvalue(gL, -4);
+			lua_pushvalue(gL, -4);
+			if (lua_pcall(gL, 3, 1, 0)) {
+				if (!hookp->error || cv_debug & DBG_LUA)
+					CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
+				lua_pop(gL, 1);
+				hookp->error = true;
+				continue;
+			}
+			if (lua_toboolean(gL, -1))
+				hooked = true;
+			lua_pop(gL, 1);
+		}
+
+	for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next)
+		if (hookp->type == hook_MobjDeath)
 		{
 			if (lua_gettop(gL) == 0)
 			{
@@ -658,9 +923,8 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
 
 	lua_settop(gL, 0);
 
-	for (hookp = roothook; hookp; hookp = hookp->next)
-		if (hookp->type == hook_LinedefExecute
-		&& !strcmp(hookp->s.funcname, line->text))
+	for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next)
+		if (!strcmp(hookp->s.funcname, line->text))
 		{
 			if (lua_gettop(gL) == 0)
 			{
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 60cbbe5018f28fb657cee6ec608d275386b53411..5b3cd46ce8f86cf3f987dc716d2b4f0e0c86d7f3 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -226,7 +226,12 @@ static int hudinfo_num(lua_State *L)
 
 static int colormap_get(lua_State *L)
 {
-	return luaL_error(L, "colormap is not a struct.");
+	const UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP));
+	UINT32 i = luaL_checkinteger(L, 2);
+	if (i >= 256)
+		return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255);
+	lua_pushinteger(L, colormap[i]);
+	return 1;
 }
 
 static int patch_get(lua_State *L)
diff --git a/src/lua_libs.h b/src/lua_libs.h
index 931cf62d0bc11901d303969d821dd30a30266e6c..fd4937b6354207a63a73f1a4c9318d7e802083c7 100644
--- a/src/lua_libs.h
+++ b/src/lua_libs.h
@@ -38,12 +38,22 @@ extern lua_State *gL;
 #define META_SUBSECTOR "SUBSECTOR_T*"
 #define META_SECTOR "SECTOR_T*"
 #define META_FFLOOR "FFLOOR_T*"
+#ifdef HAVE_LUA_SEGS
+#define META_SEG "SEG_T*"
+#define META_NODE "NODE_T*"
+#endif
 #define META_MAPHEADER "MAPHEADER_T*"
 
 #define META_CVAR "CONSVAR_T*"
 
 #define META_SECTORLINES "SECTOR_T*LINES"
 #define META_SIDENUM "LINE_T*SIDENUM"
+#ifdef HAVE_LUA_SEGS
+#define META_NODEBBOX "NODE_T*BBOX"
+#define META_NODECHILDREN "NODE_T*CHILDREN"
+#endif
+
+#define META_BBOX "BOUNDING_BOX"
 
 #define META_HUDINFO "HUDINFO_T*"
 #define META_PATCH "PATCH_T*"
@@ -64,6 +74,7 @@ int LUA_PlayerLib(lua_State *L);
 int LUA_SkinLib(lua_State *L);
 int LUA_ThinkerLib(lua_State *L);
 int LUA_MapLib(lua_State *L);
+int LUA_BlockmapLib(lua_State *L);
 int LUA_HudLib(lua_State *L);
 
 #endif
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index c512bf3c5292cdb1030209b6aca5277fded6dd9c..9f6d3e7fa34a87d16518d72288f3700343b55da9 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -185,6 +185,82 @@ static const char *const ffloor_opt[] = {
 	"alpha",
 	NULL};
 
+#ifdef HAVE_LUA_SEGS
+enum seg_e {
+	seg_valid = 0,
+	seg_v1,
+	seg_v2,
+	seg_side,
+	seg_offset,
+	seg_angle,
+	seg_sidedef,
+	seg_linedef,
+	seg_frontsector,
+	seg_backsector,
+};
+
+static const char *const seg_opt[] = {
+	"valid",
+	"v1",
+	"v2",
+	"side",
+	"offset",
+	"angle",
+	"sidedef",
+	"linedef",
+	"frontsector",
+	"backsector",
+	NULL};
+
+enum node_e {
+	node_valid = 0,
+	node_x,
+	node_y,
+	node_dx,
+	node_dy,
+	node_bbox,
+	node_children,
+};
+
+static const char *const node_opt[] = {
+	"valid",
+	"x",
+	"y",
+	"dx",
+	"dy",
+	"bbox",
+	"children",
+	NULL};
+
+enum nodechild_e {
+	nodechild_valid = 0,
+	nodechild_right,
+	nodechild_left,
+};
+
+static const char *const nodechild_opt[] = {
+	"valid",
+	"right",
+	"left",
+	NULL};
+#endif
+
+enum bbox_e {
+	bbox_valid = 0,
+	bbox_top,
+	bbox_bottom,
+	bbox_left,
+	bbox_right,
+};
+
+static const char *const bbox_opt[] = {
+	"valid",
+	"top",
+	"bottom",
+	"left",
+	"right",
+	NULL};
+
 static const char *const array_opt[] ={"iterate",NULL};
 static const char *const valid_opt[] ={"valid",NULL};
 
@@ -348,22 +424,12 @@ static int sector_get(lua_State *L)
 	case sector_ceilingheight:
 		lua_pushfixed(L, sector->ceilingheight);
 		return 1;
-	case sector_floorpic: { // floorpic
-		levelflat_t *levelflat;
-		INT16 i;
-		for (i = 0, levelflat = levelflats; i != sector->floorpic; i++, levelflat++)
-			;
-		lua_pushlstring(L, levelflat->name, 8);
+	case sector_floorpic: // floorpic
+		lua_pushlstring(L, levelflats[sector->floorpic].name, 8);
 		return 1;
-	}
-	case sector_ceilingpic: { // ceilingpic
-		levelflat_t *levelflat;
-		INT16 i;
-		for (i = 0, levelflat = levelflats; i != sector->ceilingpic; i++, levelflat++)
-			;
-		lua_pushlstring(L, levelflat->name, 8);
+	case sector_ceilingpic: // ceilingpic
+		lua_pushlstring(L, levelflats[sector->ceilingpic].name, 8);
 		return 1;
-	}
 	case sector_lightlevel:
 		lua_pushinteger(L, sector->lightlevel);
 		return 1;
@@ -400,46 +466,6 @@ static int sector_get(lua_State *L)
 	return 0;
 }
 
-// help function for P_LoadSectors, find a flat in the active wad files,
-// allocate an id for it, and set the levelflat (to speedup search)
-//
-static INT32 P_AddLevelFlatRuntime(const char *flatname)
-{
-	size_t i;
-	levelflat_t *levelflat = levelflats;
-
-	//
-	//  first scan through the already found flats
-	//
-	for (i = 0; i < numlevelflats; i++, levelflat++)
-		if (strnicmp(levelflat->name,flatname,8)==0)
-			break;
-
-	// that flat was already found in the level, return the id
-	if (i == numlevelflats)
-	{
-		// allocate new flat memory
-		levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL);
-		levelflat = levelflats+i;
-
-		// store the name
-		strlcpy(levelflat->name, flatname, sizeof (levelflat->name));
-		strupr(levelflat->name);
-
-		// store the flat lump number
-		levelflat->lumpnum = R_GetFlatNumForName(flatname);
-
-#ifndef ZDEBUG
-		CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
-#endif
-
-		numlevelflats++;
-	}
-
-	// level flat id
-	return (INT32)i;
-}
-
 static int sector_set(lua_State *L)
 {
 	sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
@@ -818,6 +844,262 @@ static int vertex_num(lua_State *L)
 	return 1;
 }
 
+#ifdef HAVE_LUA_SEGS
+static int seg_get(lua_State *L)
+{
+	seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG));
+	enum seg_e field = luaL_checkoption(L, 2, seg_opt[0], seg_opt);
+
+	if (!seg)
+	{
+		if (field == seg_valid) {
+			lua_pushboolean(L, 0);
+			return 1;
+		}
+		return luaL_error(L, "accessed seg_t doesn't exist anymore.");
+	}
+
+	switch(field)
+	{
+	case seg_valid: // valid
+		lua_pushboolean(L, 1);
+		return 1;
+	case seg_v1:
+		LUA_PushUserdata(L, seg->v1, META_VERTEX);
+		return 1;
+	case seg_v2:
+		LUA_PushUserdata(L, seg->v2, META_VERTEX);
+		return 1;
+	case seg_side:
+		lua_pushinteger(L, seg->side);
+		return 1;
+	case seg_offset:
+		lua_pushfixed(L, seg->offset);
+		return 1;
+	case seg_angle:
+		lua_pushangle(L, seg->angle);
+		return 1;
+	case seg_sidedef:
+		LUA_PushUserdata(L, seg->sidedef, META_SIDE);
+		return 1;
+	case seg_linedef:
+		LUA_PushUserdata(L, seg->linedef, META_LINE);
+		return 1;
+	case seg_frontsector:
+		LUA_PushUserdata(L, seg->frontsector, META_SECTOR);
+		return 1;
+	case seg_backsector:
+		LUA_PushUserdata(L, seg->backsector, META_SECTOR);
+		return 1;
+	}
+	return 0;
+}
+
+static int seg_num(lua_State *L)
+{
+	seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG));
+	lua_pushinteger(L, seg-segs);
+	return 1;
+}
+
+static int node_get(lua_State *L)
+{
+	node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE));
+	enum node_e field = luaL_checkoption(L, 2, node_opt[0], node_opt);
+
+	if (!node)
+	{
+		if (field == node_valid) {
+			lua_pushboolean(L, 0);
+			return 1;
+		}
+		return luaL_error(L, "accessed node_t doesn't exist anymore.");
+	}
+
+	switch(field)
+	{
+	case node_valid: // valid
+		lua_pushboolean(L, 1);
+		return 1;
+	case node_x:
+		lua_pushfixed(L, node->x);
+		return 1;
+	case node_y:
+		lua_pushfixed(L, node->y);
+		return 1;
+	case node_dx:
+		lua_pushfixed(L, node->x);
+		return 1;
+	case node_dy:
+		lua_pushfixed(L, node->x);
+		return 1;
+	case node_bbox:
+		LUA_PushUserdata(L, node->bbox, META_NODEBBOX);
+		return 1;
+	case node_children:
+		LUA_PushUserdata(L, node->children, META_NODECHILDREN);
+		return 1;
+	}
+	return 0;
+}
+
+static int node_num(lua_State *L)
+{
+	node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE));
+	lua_pushinteger(L, node-nodes);
+	return 1;
+}
+/*
+// node.bbox[i][j]: i = 0 or 1, j = 0 1 2 or 3
+// NOTE: 2D arrays are NOT double pointers,
+//       the second bbox will be directly after the first in memory (hence the way the bbox is pushed here)
+// this function handles the [i] part, bbox_get handles the [j] part
+static int nodebbox_get(lua_State *L)
+{
+	fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX));
+	int i;
+	lua_settop(L, 2);
+	if (!lua_isnumber(L, 2))
+	{
+		int field = luaL_checkoption(L, 2, NULL, valid_opt);
+		if (!bbox)
+		{
+			if (field == 0) {
+				lua_pushboolean(L, 0);
+				return 1;
+			}
+			return luaL_error(L, "accessed node_t doesn't exist anymore.");
+		} else if (field == 0) {
+			lua_pushboolean(L, 1);
+			return 1;
+		}
+	}
+
+	i = lua_tointeger(L, 2);
+	if (i < 0 || i > 1)
+		return 0;
+	LUA_PushUserdata(L, bbox + i*4*sizeof(fixed_t), META_BBOX);
+	return 1;
+}
+*/
+static int nodebbox_call(lua_State *L)
+{
+	fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX));
+	int i, j;
+	int n = lua_gettop(L);
+
+	if (!bbox)
+		return luaL_error(L, "accessed node bbox doesn't exist anymore.");
+	if (n < 3)
+		return luaL_error(L, "arguments 2 and/or 3 not given (expected node.bbox(child, coord))");
+	// get child
+	if (!lua_isnumber(L, 2)) {
+		enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt);
+		switch (field) {
+			case nodechild_right: i = 0; break;
+			case nodechild_left:  i = 1; break;
+			default:
+				return luaL_error(L, "invalid node child \"%s\".", lua_tostring(L, 2));
+		}
+	}
+	else {
+		i = lua_tointeger(L, 2);
+		if (i < 0 || i > 1)
+			return 0;
+	}
+	// get bbox coord
+	if (!lua_isnumber(L, 3)) {
+		enum bbox_e field = luaL_checkoption(L, 3, bbox_opt[0], bbox_opt);
+		switch (field) {
+			case bbox_top:    j = BOXTOP;    break;
+			case bbox_bottom: j = BOXBOTTOM; break;
+			case bbox_left:   j = BOXLEFT;   break;
+			case bbox_right:  j = BOXRIGHT;  break;
+			default:
+				return luaL_error(L, "invalid bbox coordinate \"%s\".", lua_tostring(L, 3));
+		}
+	}
+	else {
+		j = lua_tointeger(L, 3);
+		if (j < 0 || j > 3)
+			return 0;
+	}
+	lua_pushinteger(L, bbox[i*4 + j]);
+	return 1;
+}
+
+// node.children[i]: i = 0 or 1
+static int nodechildren_get(lua_State *L)
+{
+	UINT16 *children = *((UINT16 **)luaL_checkudata(L, 1, META_NODECHILDREN));
+	int i;
+	lua_settop(L, 2);
+	if (!lua_isnumber(L, 2))
+	{
+		enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt);
+		if (!children)
+		{
+			if (field == nodechild_valid) {
+				lua_pushboolean(L, 0);
+				return 1;
+			}
+			return luaL_error(L, "accessed node_t doesn't exist anymore.");
+		} else if (field == nodechild_valid) {
+			lua_pushboolean(L, 1);
+			return 1;
+		} else switch (field) {
+			case nodechild_right: i = 0; break;
+			case nodechild_left:  i = 1; break;
+			default:              return 0;
+		}
+	}
+	else {
+		i = lua_tointeger(L, 2);
+		if (i < 0 || i > 1)
+			return 0;
+	}
+	lua_pushinteger(L, children[i]);
+	return 1;
+}
+#endif
+
+// bounding box (aka fixed_t array with four elements)
+// NOTE: may be useful for polyobjects or other things later
+static int bbox_get(lua_State *L)
+{
+	fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_BBOX));
+	int i;
+	lua_settop(L, 2);
+	if (!lua_isnumber(L, 2))
+	{
+		enum bbox_e field = luaL_checkoption(L, 2, bbox_opt[0], bbox_opt);
+		if (!bbox)
+		{
+			if (field == bbox_valid) {
+				lua_pushboolean(L, 0);
+				return 1;
+			}
+			return luaL_error(L, "accessed bbox doesn't exist anymore.");
+		} else if (field == bbox_valid) {
+			lua_pushboolean(L, 1);
+			return 1;
+		} else switch (field) {
+			case bbox_top:    i = BOXTOP;    break;
+			case bbox_bottom: i = BOXBOTTOM; break;
+			case bbox_left:   i = BOXLEFT;   break;
+			case bbox_right:  i = BOXRIGHT;  break;
+			default:          return 0;
+		}
+	}
+	else {
+		i = lua_tointeger(L, 2);
+		if (i < 0 || i > 3)
+			return 0;
+	}
+	lua_pushinteger(L, bbox[i]);
+	return 1;
+}
+
 static int lib_iterateSectors(lua_State *L)
 {
 	size_t i = 0;
@@ -1048,6 +1330,100 @@ static int lib_numvertexes(lua_State *L)
 	return 1;
 }
 
+#ifdef HAVE_LUA_SEGS
+static int lib_iterateSegs(lua_State *L)
+{
+	size_t i = 0;
+	if (lua_gettop(L) < 2)
+		return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do <block> end'.");
+	lua_settop(L, 2);
+	lua_remove(L, 1); // state is unused.
+	if (!lua_isnil(L, 1))
+		i = (size_t)(*((seg_t **)luaL_checkudata(L, 1, META_SEG)) - segs)+1;
+	if (i < numsegs)
+	{
+		LUA_PushUserdata(L, &segs[i], META_SEG);
+		return 1;
+	}
+	return 0;
+}
+
+static int lib_getSeg(lua_State *L)
+{
+	int field;
+	lua_settop(L, 2);
+	lua_remove(L, 1); // dummy userdata table is unused.
+	if (lua_isnumber(L, 1))
+	{
+		size_t i = lua_tointeger(L, 1);
+		if (i >= numsegs)
+			return 0;
+		LUA_PushUserdata(L, &segs[i], META_SEG);
+		return 1;
+	}
+	field = luaL_checkoption(L, 1, NULL, array_opt);
+	switch(field)
+	{
+	case 0: // iterate
+		lua_pushcfunction(L, lib_iterateSegs);
+		return 1;
+	}
+	return 0;
+}
+
+static int lib_numsegs(lua_State *L)
+{
+	lua_pushinteger(L, numsegs);
+	return 1;
+}
+
+static int lib_iterateNodes(lua_State *L)
+{
+	size_t i = 0;
+	if (lua_gettop(L) < 2)
+		return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do <block> end'.");
+	lua_settop(L, 2);
+	lua_remove(L, 1); // state is unused.
+	if (!lua_isnil(L, 1))
+		i = (size_t)(*((node_t **)luaL_checkudata(L, 1, META_NODE)) - nodes)+1;
+	if (i < numsegs)
+	{
+		LUA_PushUserdata(L, &nodes[i], META_NODE);
+		return 1;
+	}
+	return 0;
+}
+
+static int lib_getNode(lua_State *L)
+{
+	int field;
+	lua_settop(L, 2);
+	lua_remove(L, 1); // dummy userdata table is unused.
+	if (lua_isnumber(L, 1))
+	{
+		size_t i = lua_tointeger(L, 1);
+		if (i >= numnodes)
+			return 0;
+		LUA_PushUserdata(L, &nodes[i], META_NODE);
+		return 1;
+	}
+	field = luaL_checkoption(L, 1, NULL, array_opt);
+	switch(field)
+	{
+	case 0: // iterate
+		lua_pushcfunction(L, lib_iterateNodes);
+		return 1;
+	}
+	return 0;
+}
+
+static int lib_numnodes(lua_State *L)
+{
+	lua_pushinteger(L, numnodes);
+	return 1;
+}
+#endif
+
 static int ffloor_get(lua_State *L)
 {
 	ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
@@ -1367,6 +1743,41 @@ int LUA_MapLib(lua_State *L)
 		lua_setfield(L, -2, "__newindex");
 	lua_pop(L, 1);
 
+#ifdef HAVE_LUA_SEGS
+	luaL_newmetatable(L, META_SEG);
+		lua_pushcfunction(L, seg_get);
+		lua_setfield(L, -2, "__index");
+
+		lua_pushcfunction(L, seg_num);
+		lua_setfield(L, -2, "__len");
+	lua_pop(L, 1);
+
+	luaL_newmetatable(L, META_NODE);
+		lua_pushcfunction(L, node_get);
+		lua_setfield(L, -2, "__index");
+
+		lua_pushcfunction(L, node_num);
+		lua_setfield(L, -2, "__len");
+	lua_pop(L, 1);
+
+	luaL_newmetatable(L, META_NODEBBOX);
+		//lua_pushcfunction(L, nodebbox_get);
+		//lua_setfield(L, -2, "__index");
+		lua_pushcfunction(L, nodebbox_call);
+		lua_setfield(L, -2, "__call");
+	lua_pop(L, 1);
+
+	luaL_newmetatable(L, META_NODECHILDREN);
+		lua_pushcfunction(L, nodechildren_get);
+		lua_setfield(L, -2, "__index");
+	lua_pop(L, 1);
+#endif
+
+	luaL_newmetatable(L, META_BBOX);
+		lua_pushcfunction(L, bbox_get);
+		lua_setfield(L, -2, "__index");
+	lua_pop(L, 1);
+
 	luaL_newmetatable(L, META_MAPHEADER);
 		lua_pushcfunction(L, mapheaderinfo_get);
 		lua_setfield(L, -2, "__index");
@@ -1425,6 +1836,28 @@ int LUA_MapLib(lua_State *L)
 		lua_setmetatable(L, -2);
 	lua_setglobal(L, "vertexes");
 
+#ifdef HAVE_LUA_SEGS
+	lua_newuserdata(L, 0);
+		lua_createtable(L, 0, 2);
+			lua_pushcfunction(L, lib_getSeg);
+			lua_setfield(L, -2, "__index");
+
+			lua_pushcfunction(L, lib_numsegs);
+			lua_setfield(L, -2, "__len");
+		lua_setmetatable(L, -2);
+	lua_setglobal(L, "segs");
+
+	lua_newuserdata(L, 0);
+		lua_createtable(L, 0, 2);
+			lua_pushcfunction(L, lib_getNode);
+			lua_setfield(L, -2, "__index");
+
+			lua_pushcfunction(L, lib_numnodes);
+			lua_setfield(L, -2, "__len");
+		lua_setmetatable(L, -2);
+	lua_setglobal(L, "nodes");
+#endif
+
 	lua_newuserdata(L, 0);
 		lua_createtable(L, 0, 2);
 			lua_pushcfunction(L, lib_getMapheaderinfo);
diff --git a/src/lua_script.c b/src/lua_script.c
index acb306827ecf0687c8689fa1600ddd95dc52914b..d30790be1bc70359b7e13b566d4791b2271c0780 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -48,6 +48,7 @@ static lua_CFunction liblist[] = {
 	LUA_SkinLib, // skin_t, skins[]
 	LUA_ThinkerLib, // thinker_t
 	LUA_MapLib, // line_t, side_t, sector_t, subsector_t
+	LUA_BlockmapLib, // blockmap stuff
 	LUA_HudLib, // HUD stuff
 	NULL
 };
@@ -395,6 +396,7 @@ void LUA_InvalidateLevel(void)
 {
 	thinker_t *th;
 	size_t i;
+	ffloor_t *rover = NULL;
 	if (!gL)
 		return;
 
@@ -406,7 +408,15 @@ void LUA_InvalidateLevel(void)
 	for (i = 0; i < numsubsectors; i++)
 		LUA_InvalidateUserdata(&subsectors[i]);
 	for (i = 0; i < numsectors; i++)
+	{
 		LUA_InvalidateUserdata(&sectors[i]);
+		LUA_InvalidateUserdata(sectors[i].lines);
+		if (sectors[i].ffloors)
+		{
+			for (rover = sectors[i].ffloors; rover; rover = rover->next)
+				LUA_InvalidateUserdata(rover);
+		}
+	}
 	for (i = 0; i < numlines; i++)
 	{
 		LUA_InvalidateUserdata(&lines[i]);
@@ -416,6 +426,16 @@ void LUA_InvalidateLevel(void)
 		LUA_InvalidateUserdata(&sides[i]);
 	for (i = 0; i < numvertexes; i++)
 		LUA_InvalidateUserdata(&vertexes[i]);
+#ifdef HAVE_LUA_SEGS
+	for (i = 0; i < numsegs; i++)
+		LUA_InvalidateUserdata(&segs[i]);
+	for (i = 0; i < numnodes; i++)
+	{
+		LUA_InvalidateUserdata(&nodes[i]);
+		LUA_InvalidateUserdata(nodes[i].bbox);
+		LUA_InvalidateUserdata(nodes[i].children);
+	}
+#endif
 }
 
 void LUA_InvalidateMapthings(void)
@@ -455,6 +475,11 @@ enum
 	ARCH_SIDE,
 	ARCH_SUBSECTOR,
 	ARCH_SECTOR,
+#ifdef HAVE_LUA_SEGS
+	ARCH_SEG,
+	ARCH_NODE,
+#endif
+	ARCH_FFLOOR,
 	ARCH_MAPHEADER,
 
 	ARCH_TEND=0xFF,
@@ -474,6 +499,11 @@ static const struct {
 	{META_SIDE,     ARCH_SIDE},
 	{META_SUBSECTOR,ARCH_SUBSECTOR},
 	{META_SECTOR,   ARCH_SECTOR},
+#ifdef HAVE_LUA_SEGS
+	{META_SEG,      ARCH_SEG},
+	{META_NODE,     ARCH_NODE},
+#endif
+	{META_FFLOOR,	ARCH_FFLOOR},
 	{META_MAPHEADER,   ARCH_MAPHEADER},
 	{NULL,          ARCH_NULL}
 };
@@ -664,6 +694,56 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 			}
 			break;
 		}
+#ifdef HAVE_LUA_SEGS
+		case ARCH_SEG:
+		{
+			seg_t *seg = *((seg_t **)lua_touserdata(gL, myindex));
+			if (!seg)
+				WRITEUINT8(save_p, ARCH_NULL);
+			else {
+				WRITEUINT8(save_p, ARCH_SEG);
+				WRITEUINT16(save_p, seg - segs);
+			}
+			break;
+		}
+		case ARCH_NODE:
+		{
+			node_t *node = *((node_t **)lua_touserdata(gL, myindex));
+			if (!node)
+				WRITEUINT8(save_p, ARCH_NULL);
+			else {
+				WRITEUINT8(save_p, ARCH_NODE);
+				WRITEUINT16(save_p, node - nodes);
+			}
+			break;
+		}
+#endif
+		case ARCH_FFLOOR:
+		{
+			ffloor_t *rover = *((ffloor_t **)lua_touserdata(gL, myindex));
+			if (!rover)
+				WRITEUINT8(save_p, ARCH_NULL);
+			else {
+				ffloor_t *r2;
+				UINT16 i = 0;
+				// search for id
+				for (r2 = rover->target->ffloors; r2; r2 = r2->next)
+				{
+					if (r2 == rover)
+						break;
+					i++;
+				}
+				if (!r2)
+					WRITEUINT8(save_p, ARCH_NULL);
+				else
+				{
+					WRITEUINT8(save_p, ARCH_FFLOOR);
+					WRITEUINT16(save_p, rover->target - sectors);
+					WRITEUINT16(save_p, i);
+				}
+			}
+			break;
+		}
 		case ARCH_MAPHEADER:
 		{
 			mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex));
@@ -842,6 +922,23 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
 	case ARCH_SECTOR:
 		LUA_PushUserdata(gL, &sectors[READUINT16(save_p)], META_SECTOR);
 		break;
+#ifdef HAVE_LUA_SEGS
+	case ARCH_SEG:
+		LUA_PushUserdata(gL, &segs[READUINT16(save_p)], META_SEG);
+		break;
+	case ARCH_NODE:
+		LUA_PushUserdata(gL, &nodes[READUINT16(save_p)], META_NODE);
+		break;
+#endif
+	case ARCH_FFLOOR:
+	{
+		sector_t *sector = &sectors[READUINT16(save_p)];
+		UINT16 id = READUINT16(save_p);
+		ffloor_t *rover = P_GetFFloorByID(sector, id);
+		if (rover)
+			LUA_PushUserdata(gL, rover, META_FFLOOR);
+		break;
+	}
 	case ARCH_MAPHEADER:
 		LUA_PushUserdata(gL, &sectors[READUINT16(save_p)], META_MAPHEADER);
 		break;
diff --git a/src/lua_script.h b/src/lua_script.h
index 3b159234a5f75fc2561ad6ad65a94a9a367b8f1e..d143ed879a25944778f6105c6b123b0190184ab0 100644
--- a/src/lua_script.h
+++ b/src/lua_script.h
@@ -92,4 +92,7 @@ void COM_Lua_f(void);
 	}\
 }
 
+// uncomment if you want seg_t/node_t in Lua
+// #define HAVE_LUA_SEGS
+
 #endif
diff --git a/src/m_aatree.h b/src/m_aatree.h
index c9077b9740f1251eb4584120cd2f8283174d3eb3..eeaebca3b94320fb71c5b85579caf2c355503e00 100644
--- a/src/m_aatree.h
+++ b/src/m_aatree.h
@@ -28,4 +28,4 @@ void M_AATreeSet(aatree_t *aatree, INT32 key, void* value);
 void *M_AATreeGet(aatree_t *aatree, INT32 key);
 void M_AATreeIterate(aatree_t *aatree, aatree_iter_t callback);
 
-#endif
\ No newline at end of file
+#endif
diff --git a/src/m_fixed.h b/src/m_fixed.h
index 70402f27a0eafbe61eec8fa6e5f15a4d6e8363cc..1cf9abbae3c97e076e391bc41954eefaf0aa6b2c 100644
--- a/src/m_fixed.h
+++ b/src/m_fixed.h
@@ -46,41 +46,6 @@ typedef INT32 fixed_t;
 #define FLOAT_TO_FIXED(f) (fixed_t)((f) * ((float)FRACUNIT))
 
 
-/**	\brief	The TMulScale16 function
-
-	\param	a	a parameter of type fixed_t
-	\param	b	a parameter of type fixed_t
-	\param	c	a parameter of type fixed_t
-	\param	d	a parameter of type fixed_t
-	\param	e	a parameter of type fixed_t
-	\param	f	a parameter of type fixed_t
-
-	\return	fixed_t
-
-
-*/
-FUNCMATH FUNCINLINE static ATTRINLINE fixed_t TMulScale16(fixed_t a, fixed_t b, fixed_t c, fixed_t d, fixed_t e, fixed_t f) \
-{ \
-	return (fixed_t)((((INT64)a * (INT64)b) + ((INT64)c * (INT64)d) \
-		+ ((INT64)e * (INT64)f)) >> 16); \
-}
-
-/**	\brief	The DMulScale16 function
-
-	\param	a	a parameter of type fixed_t
-	\param	b	a parameter of type fixed_t
-	\param	c	a parameter of type fixed_t
-	\param	d	a parameter of type fixed_t
-
-	\return	fixed_t
-
-
-*/
-FUNCMATH FUNCINLINE static ATTRINLINE fixed_t DMulScale16(fixed_t a, fixed_t b, fixed_t c, fixed_t d) \
-{ \
-	return (fixed_t)((((INT64)a * (INT64)b) + ((INT64)c * (INT64)d)) >> 16); \
-}
-
 #if defined (__WATCOMC__) && FRACBITS == 16
 	#pragma aux FixedMul =  \
 		"imul ebx",         \
@@ -283,9 +248,16 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedFloor(fixed_t x)
 {
 	const fixed_t a = abs(x); //absolute of x
 	const fixed_t i = (a>>FRACBITS)<<FRACBITS; // cut out the fractional part
-	const fixed_t f = i-a; // cut out the integral part
+	const fixed_t f = a-i; // cut out the integral part
+	if (f == 0)
+		return x;
 	if (x != INT32_MIN)
-		return x-f; // return largest integral value not greater than argument
+	{ // return rounded down to nearest whole number
+		if (x > 0)
+			return x-f;
+		else
+			return x-(FRACUNIT-f);
+	}
 	return INT32_MIN;
 }
 
@@ -301,7 +273,7 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedTrunc(fixed_t x)
 {
 	const fixed_t a = abs(x); //absolute of x
 	const fixed_t i = (a>>FRACBITS)<<FRACBITS; // cut out the fractional part
-	const fixed_t f = i-a; // cut out the integral part
+	const fixed_t f = a-i; // cut out the integral part
 	if (x != INT32_MIN)
 	{ // return rounded to nearest whole number, towards zero
 		if (x > 0)
@@ -324,11 +296,18 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedCeil(fixed_t x)
 {
 	const fixed_t a = abs(x); //absolute of x
 	const fixed_t i = (a>>FRACBITS)<<FRACBITS; // cut out the fractional part
-	const fixed_t f = i-a; // cut out the integral part
+	const fixed_t f = a-i; // cut out the integral part
+	if (f == 0)
+		return x;
 	if (x == INT32_MIN)
 		return INT32_MIN;
 	else if (x < FixedFloor(INT32_MAX))
-		return x+(FRACUNIT-f); // return smallest integral value not less than argument
+	{ // return rounded up to nearest whole number
+		if (x > 0)
+			return x+(FRACUNIT-f);
+		else
+			return x+f;
+	}
 	return INT32_MAX;
 }
 
@@ -344,7 +323,9 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedRound(fixed_t x)
 {
 	const fixed_t a = abs(x); //absolute of x
 	const fixed_t i = (a>>FRACBITS)<<FRACBITS; // cut out the fractional part
-	const fixed_t f = i-a; // cut out the integral part
+	const fixed_t f = a-i; // cut out the integral part
+	if (f == 0)
+		return x;
 	if (x == INT32_MIN)
 		return INT32_MIN;
 	else if (x < FixedFloor(INT32_MAX))
diff --git a/src/m_misc.c b/src/m_misc.c
index cfe73d88fa60cad5f1d5c9bb93ea82f47eec5f30..d6ab40196694df21a9150ce799d596f89498b159 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -1617,6 +1617,11 @@ INT32 axtoi(const char *hexStg)
 	return intValue;
 }
 
+// Token parser variables
+
+static UINT32 oldendPos = 0; // old value of endPos, used by M_UnGetToken
+static UINT32 endPos = 0; // now external to M_GetToken, but still static
+
 /** Token parser for TEXTURES, ANIMDEFS, and potentially other lumps later down the line.
   * Was originally R_GetTexturesToken when I was coding up the TEXTURES parser, until I realized I needed it for ANIMDEFS too.
   * Parses up to the next whitespace character or comma. When finding the start of the next token, whitespace is skipped.
@@ -1631,7 +1636,7 @@ char *M_GetToken(const char *inputString)
 {
 	static const char *stringToUse = NULL; // Populated if inputString != NULL; used otherwise
 	static UINT32 startPos = 0;
-	static UINT32 endPos = 0;
+//	static UINT32 endPos = 0;
 	static UINT32 stringLength = 0;
 	static UINT8 inComment = 0; // 0 = not in comment, 1 = // Single-line, 2 = /* Multi-line */
 	char *texturesToken = NULL;
@@ -1641,12 +1646,12 @@ char *M_GetToken(const char *inputString)
 	{
 		stringToUse = inputString;
 		startPos = 0;
-		endPos = 0;
+		oldendPos = endPos = 0;
 		stringLength = strlen(inputString);
 	}
 	else
 	{
-		startPos = endPos;
+		startPos = oldendPos = endPos;
 	}
 	if (stringToUse == NULL)
 		return NULL;
@@ -1777,6 +1782,16 @@ char *M_GetToken(const char *inputString)
 	return texturesToken;
 }
 
+/** Undoes the last M_GetToken call
+  * The current position along the string being parsed is reset to the last saved position.
+  * This exists mostly because of R_ParseTexture/R_ParsePatch honestly, but could be useful elsewhere?
+  * -Monster Iestyn (22/10/16)
+ */
+void M_UnGetToken(void)
+{
+	endPos = oldendPos;
+}
+
 /** Count bits in a number.
   */
 UINT8 M_CountBits(UINT32 num, UINT8 size)
diff --git a/src/p_enemy.c b/src/p_enemy.c
index b688cbf039e7874390be8043ada646574faaf8c1..4423f50f34914fe53585a420c260bc9ce004121d 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -104,6 +104,9 @@ void A_BombShield(mobj_t *actor);
 void A_WaterShield(mobj_t *actor);
 void A_ForceShield(mobj_t *actor);
 void A_PityShield(mobj_t *actor);
+void A_FlameShield(mobj_t *actor);
+void A_BubbleShield(mobj_t *actor);
+void A_ThunderShield(mobj_t *actor);
 void A_GravityBox(mobj_t *actor);
 void A_ScoreRise(mobj_t *actor);
 void A_ParticleSpawn(mobj_t *actor);
@@ -239,6 +242,16 @@ void A_BrakFireShot(mobj_t *actor);
 void A_BrakLobShot(mobj_t *actor);
 void A_NapalmScatter(mobj_t *actor);
 void A_SpawnFreshCopy(mobj_t *actor);
+void A_FlickySpawn(mobj_t *actor);
+void A_FlickyAim(mobj_t *actor);
+void A_FlickyFly(mobj_t *actor);
+void A_FlickySoar(mobj_t *actor);
+void A_FlickyCoast(mobj_t *actor);
+void A_FlickyHop(mobj_t *actor);
+void A_FlickyFlounder(mobj_t *actor);
+void A_FlickyCheck(mobj_t *actor);
+void A_FlickyHeightCheck(mobj_t *actor);
+void A_FlickyFlutter(mobj_t *actor);
 
 //
 // ENEMY THINKING
@@ -738,7 +751,7 @@ static boolean P_LookForShield(mobj_t *actor)
 			(actor->type == MT_BLUETEAMRING && player->ctfteam != 2))
 			continue;
 
-		if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT
+		if ((player->powers[pw_shield] & SH_PROTECTELECTRIC)
 			&& (P_AproxDistance(P_AproxDistance(actor->x-player->mo->x, actor->y-player->mo->y), actor->z-player->mo->z) < FixedMul(RING_DIST, player->mo->scale)))
 		{
 			P_SetTarget(&actor->tracer, player->mo);
@@ -3059,11 +3072,7 @@ void A_JumpShield(mobj_t *actor)
 
 	player = actor->target->player;
 
-	if ((player->powers[pw_shield] & SH_NOSTACK) != SH_JUMP)
-	{
-		player->powers[pw_shield] = SH_JUMP|(player->powers[pw_shield] & SH_STACK);
-		P_SpawnShieldOrb(player);
-	}
+	P_SwitchShield(player, SH_WHIRLWIND);
 
 	S_StartSound(player->mo, actor->info->seesound);
 }
@@ -3091,11 +3100,7 @@ void A_RingShield(mobj_t *actor)
 
 	player = actor->target->player;
 
-	if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT)
-	{
-		player->powers[pw_shield] = SH_ATTRACT|(player->powers[pw_shield] & SH_STACK);
-		P_SpawnShieldOrb(player);
-	}
+	P_SwitchShield(player, SH_ATTRACT);
 
 	S_StartSound(player->mo, actor->info->seesound);
 }
@@ -3292,11 +3297,12 @@ void A_BombShield(mobj_t *actor)
 
 	player = actor->target->player;
 
-	if ((player->powers[pw_shield] & SH_NOSTACK) != SH_BOMB)
-	{
-		player->powers[pw_shield] = SH_BOMB|(player->powers[pw_shield] & SH_STACK);
-		P_SpawnShieldOrb(player);
-	}
+	// If you already have a bomb shield, use it!
+	if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ARMAGEDDON)
+		P_BlackOw(player);
+
+	// Now we know for certain that we don't have a bomb shield, so add one. :3
+	P_SwitchShield(player, SH_ARMAGEDDON);
 
 	S_StartSound(player->mo, actor->info->seesound);
 }
@@ -3324,22 +3330,8 @@ void A_WaterShield(mobj_t *actor)
 
 	player = actor->target->player;
 
-	if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ELEMENTAL)
-	{
-		player->powers[pw_shield] = SH_ELEMENTAL|(player->powers[pw_shield] & SH_STACK);
-		P_SpawnShieldOrb(player);
-	}
-
-	if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1)
-		P_RestoreMusic(player);
+	P_SwitchShield(player, SH_ELEMENTAL);
 
-	player->powers[pw_underwater] = 0;
-
-	if (player->powers[pw_spacetime] > 1)
-	{
-		player->powers[pw_spacetime] = 0;
-		P_RestoreMusic(player);
-	}
 	S_StartSound(player->mo, actor->info->seesound);
 }
 
@@ -3347,12 +3339,13 @@ void A_WaterShield(mobj_t *actor)
 //
 // Description: Awards the player a force shield.
 //
-// var1 = unused
+// var1 = Number of additional hitpoints to give
 // var2 = unused
 //
 void A_ForceShield(mobj_t *actor)
 {
 	player_t *player;
+	INT32 locvar1 = var1;
 
 #ifdef HAVE_BLUA
 	if (LUA_CallAction("A_ForceShield", actor))
@@ -3364,15 +3357,15 @@ void A_ForceShield(mobj_t *actor)
 		return;
 	}
 
-	player = actor->target->player;
-
-	if (!(player->powers[pw_shield] & SH_FORCE))
+	if (locvar1 & ~SH_FORCEHP)
 	{
-		player->powers[pw_shield] = SH_FORCE|(player->powers[pw_shield] & SH_STACK)|0x01;
-		P_SpawnShieldOrb(player);
+		CONS_Debug(DBG_GAMELOGIC, "Invalid number of additional hitpoints.\n");
+		return;
 	}
-	else
-		player->powers[pw_shield] = SH_FORCE|(player->powers[pw_shield] & SH_STACK)|0x01;
+
+	player = actor->target->player;
+
+	P_SwitchShield(player, SH_FORCE|locvar1);
 
 	S_StartSound(player->mo, actor->info->seesound);
 }
@@ -3404,12 +3397,92 @@ void A_PityShield(mobj_t *actor)
 
 	player = actor->target->player;
 
-	if ((player->powers[pw_shield] & SH_NOSTACK) != SH_PITY)
+	P_SwitchShield(player, SH_PITY);
+
+	S_StartSound(player->mo, actor->info->seesound);
+}
+
+// Function: A_FlameShield
+//
+// Description: Awards the player a flame shield.
+//
+// var1 = unused
+// var2 = unused
+//
+void A_FlameShield(mobj_t *actor)
+{
+	player_t *player;
+
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_FlameShield", actor))
+		return;
+#endif
+	if (!actor->target || !actor->target->player)
+	{
+		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
+		return;
+	}
+
+	player = actor->target->player;
+
+	P_SwitchShield(player, SH_FLAMEAURA);
+
+	S_StartSound(player->mo, actor->info->seesound);
+}
+
+// Function: A_BubbleShield
+//
+// Description: Awards the player a bubble shield.
+//
+// var1 = unused
+// var2 = unused
+//
+void A_BubbleShield(mobj_t *actor)
+{
+	player_t *player;
+
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_BubbleShield", actor))
+		return;
+#endif
+	if (!actor->target || !actor->target->player)
 	{
-		player->powers[pw_shield] = SH_PITY+(player->powers[pw_shield] & SH_STACK);
-		P_SpawnShieldOrb(player);
+		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
+		return;
+	}
+
+	player = actor->target->player;
+
+	P_SwitchShield(player, SH_BUBBLEWRAP);
+
+	S_StartSound(player->mo, actor->info->seesound);
+}
+
+// Function: A_ThunderShield
+//
+// Description: Awards the player a thunder shield.
+//
+// var1 = unused
+// var2 = unused
+//
+void A_ThunderShield(mobj_t *actor)
+{
+	player_t *player;
+
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_ThunderShield", actor))
+		return;
+#endif
+	if (!actor->target || !actor->target->player)
+	{
+		CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n");
+		return;
 	}
 
+	player = actor->target->player;
+
+	P_SwitchShield(player, SH_THUNDERCOIN);
+
 	S_StartSound(player->mo, actor->info->seesound);
 }
 
@@ -3436,9 +3509,10 @@ void A_GravityBox(mobj_t *actor)
 	}
 
 	player = actor->target->player;
-	player->powers[pw_gravityboots] = (UINT16)(actor->info->reactiontime + 1);
 
 	S_StartSound(player, actor->info->activesound);
+
+	player->powers[pw_gravityboots] = (UINT16)(actor->info->reactiontime + 1);
 }
 
 // Function: A_ScoreRise
@@ -3712,7 +3786,7 @@ void A_AttractChase(mobj_t *actor)
 
 	// Turn flingrings back into regular rings if attracted.
 	if (actor->tracer && actor->tracer->player
-		&& (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime)
+		&& !(actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime)
 	{
 		mobj_t *newring;
 		newring = P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->reactiontime);
@@ -3917,7 +3991,7 @@ void A_ThrownRing(mobj_t *actor)
 		// A non-homing ring getting attracted by a
 		// magnetic player. If he gets too far away, make
 		// sure to stop the attraction!
-		if ((!actor->tracer->health) || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT
+		if ((!actor->tracer->health) || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC)
 		    && P_AproxDistance(P_AproxDistance(actor->tracer->x-actor->x,
 		    actor->tracer->y-actor->y), actor->tracer->z-actor->z) > FixedMul(RING_DIST/4, actor->tracer->scale)))
 		{
@@ -3925,7 +3999,7 @@ void A_ThrownRing(mobj_t *actor)
 		}
 
 		if (actor->tracer && (actor->tracer->health)
-			&& (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)// Already found someone to follow.
+			&& (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC))// Already found someone to follow.
 		{
 			const INT32 temp = actor->threshold;
 			actor->threshold = 32000;
@@ -3993,7 +4067,7 @@ void A_ThrownRing(mobj_t *actor)
 		if (!P_CheckSight(actor, player->mo))
 			continue; // out of sight
 
-		if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT
+		if ((player->powers[pw_shield] & SH_PROTECTELECTRIC)
 			&& dist < FixedMul(RING_DIST/4, player->mo->scale))
 			P_SetTarget(&actor->tracer, player->mo);
 		return;
@@ -7772,7 +7846,7 @@ void A_SetObjectFlags(mobj_t *actor)
 	else if (locvar2 == 1)
 		locvar1 = actor->flags & ~locvar1;
 
-	if ((locvar1 & (MF_NOBLOCKMAP|MF_NOSECTOR)) != (actor->flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) // Blockmap/sector status has changed, so reset the links
+	if ((UINT32)(locvar1 & (MF_NOBLOCKMAP|MF_NOSECTOR)) != (actor->flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) // Blockmap/sector status has changed, so reset the links
 		unlinkthings = true;
 
 	if (unlinkthings) {
@@ -10280,3 +10354,392 @@ void A_SpawnFreshCopy(mobj_t *actor)
 	if (newObject->info->seesound)
 		S_StartSound(newObject, newObject->info->seesound);
 }
+
+// Internal Flicky spawning function.
+mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers)
+{
+	mobj_t *flicky;
+
+	if (!flickytype)
+	{
+		if (!mapheaderinfo[gamemap-1] || !mapheaderinfo[gamemap-1]->numFlickies) // No mapheader, no shoes, no service.
+			return NULL;
+		else
+		{
+			INT32 prandom = P_RandomKey(mapheaderinfo[gamemap-1]->numFlickies);
+			flickytype = mapheaderinfo[gamemap-1]->flickies[prandom];
+		}
+	}
+
+	flicky = P_SpawnMobjFromMobj(actor, 0, 0, 0, flickytype);
+	flicky->angle = actor->angle;
+
+	if (flickytype == MT_SEED)
+		flicky->z += P_MobjFlip(actor)*(actor->height - flicky->height)/2;
+
+	if (actor->eflags & MFE_UNDERWATER)
+		momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT));
+
+	P_SetObjectMomZ(flicky, momz, false);
+	flicky->movedir = (P_RandomChance(FRACUNIT/2) ?  -1 : 1);
+	flicky->fuse = P_RandomRange(595, 700);	// originally 300, 350
+	flicky->threshold = 0;
+
+	if (lookforplayers)
+		P_LookForPlayers(flicky, true, false, 0);
+
+	return flicky;
+}
+
+// Function: A_FlickySpawn
+//
+// Description: Flicky spawning function.
+//
+// var1:
+//		lower 16 bits: if 0, spawns random flicky based on level header. Else, spawns the designated thing type.
+//		upper 16 bits: if 0, no sound is played. Else, A_Scream is called.
+// var2 = upwards thrust for spawned flicky. If zero, default value is provided.
+//
+void A_FlickySpawn(mobj_t *actor)
+{
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_FlickySpawn", actor))
+		return;
+#endif
+
+	if (locvar1 >> 16) {
+		A_Scream(actor); // A shortcut for the truly lazy.
+		locvar1 &= 65535;
+	}
+
+	P_InternalFlickySpawn(actor, locvar1, ((locvar2) ? locvar2 : 8*FRACUNIT), true);
+}
+
+// Internal Flicky bubbling function.
+void P_InternalFlickyBubble(mobj_t *actor)
+{
+	if (actor->eflags & MFE_UNDERWATER)
+	{
+		mobj_t *overlay;
+
+		if (!((actor->z + 3*actor->height/2) < actor->watertop) || !mobjinfo[actor->type].raisestate || actor->tracer)
+			return;
+
+		overlay = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY);
+		P_SetMobjStateNF(overlay, mobjinfo[actor->type].raisestate);
+		P_SetTarget(&actor->tracer, overlay);
+		P_SetTarget(&overlay->target, actor);
+		return;
+	}
+
+	if (!actor->tracer || P_MobjWasRemoved(actor->tracer))
+		return;
+
+	P_RemoveMobj(actor->tracer);
+	P_SetTarget(&actor->tracer, NULL);
+}
+
+// Function: A_FlickyAim
+//
+// Description: Flicky aiming function.
+//
+// var1 = how far around the target (in angle constants) the flicky should look
+// var2 = distance from target to aim for
+//
+void A_FlickyAim(mobj_t *actor)
+{
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
+	boolean flickyhitwall = false;
+
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_FlickyAim", actor))
+		return;
+#endif
+
+	if (actor->momx == actor->momy && actor->momy == 0)
+		flickyhitwall = true;
+
+	P_InternalFlickyBubble(actor);
+	P_InstaThrust(actor, 0, 0);
+
+	if (!actor->target)
+	{
+		P_LookForPlayers(actor, true, false, 0);
+		actor->angle = P_RandomKey(36)*ANG10;
+		return;
+	}
+
+	if (actor->fuse > 2*TICRATE)
+	{
+		angle_t posvar;
+		fixed_t chasevar, chasex, chasey;
+		
+		if (flickyhitwall)
+			actor->movedir *= -1;
+
+		posvar = ((R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + actor->movedir*locvar1) >> ANGLETOFINESHIFT) & FINEMASK;
+		chasevar = FixedSqrt(max(FRACUNIT, P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y) - locvar2)) + locvar2;
+
+		chasex = actor->target->x + FixedMul(FINECOSINE(posvar), chasevar);
+		chasey = actor->target->y + FixedMul(FINESINE(posvar), chasevar);
+
+		if (P_AproxDistance(chasex - actor->x, chasey - actor->y))
+			actor->angle = R_PointToAngle2(actor->x, actor->y, chasex, chasey);
+	}
+	else if (flickyhitwall)
+	{
+		actor->angle += ANGLE_180;
+		actor->threshold = 0;
+	}
+}
+
+//Internal Flicky flying function. Also usuable as an underwater swim thrust.
+void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez)
+{
+	angle_t vertangle;
+
+	flyspeed = FixedMul(flyspeed, actor->scale);
+	actor->flags |= MF_NOGRAVITY;
+
+	var1 = ANG30;
+	var2 = 32*FRACUNIT;
+	A_FlickyAim(actor);
+
+	chasez *= 8;
+	if (!actor->target || !(actor->fuse > 2*TICRATE))
+		chasez += ((actor->eflags & MFE_VERTICALFLIP) ? actor->ceilingz - 24*FRACUNIT : actor->floorz + 24*FRACUNIT);
+	else
+	{
+		fixed_t add = actor->target->z + (actor->target->height - actor->height)/2;
+		if (add > (actor->ceilingz - 24*actor->scale - actor->height))
+			add = actor->ceilingz - 24*actor->scale - actor->height;
+		else if (add < (actor->floorz + 24*actor->scale))
+			add = actor->floorz + 24*actor->scale;
+		chasez += add;
+	}
+
+	if (!targetdist)
+		targetdist = 16*FRACUNIT; //Default!
+
+	if (actor->target && abs(chasez - actor->z) > targetdist)
+		targetdist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y);
+
+	vertangle = (R_PointToAngle2(0, actor->z, targetdist, chasez) >> ANGLETOFINESHIFT) & FINEMASK;
+	P_InstaThrust(actor, actor->angle, FixedMul(FINECOSINE(vertangle), flyspeed));
+	actor->momz = FixedMul(FINESINE(vertangle), flyspeed);
+}
+
+// Function: A_FlickyFly
+//
+// Description: Flicky flying function.
+//
+// var1 = how fast to fly
+// var2 = how far ahead the target should be considered
+//
+void A_FlickyFly(mobj_t *actor)
+{
+	// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyFly instead.
+	//INT32 locvar1 = var1;
+	//INT32 locvar2 = var2;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_FlickyFly", actor))
+		return;
+#endif
+	P_InternalFlickyFly(actor, var1, var2,
+	FINECOSINE((((actor->fuse % 36) * ANG10) >> ANGLETOFINESHIFT) & FINEMASK)
+	);
+}
+
+// Function: A_FlickySoar
+//
+// Description: Flicky soaring function - specific to puffin.
+//
+// var1 = how fast to fly
+// var2 = how far ahead the target should be considered
+//
+void A_FlickySoar(mobj_t *actor)
+{
+	// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyFly instead.
+	//INT32 locvar1 = var1;
+	//INT32 locvar2 = var2;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_FlickySoar", actor))
+		return;
+#endif
+	P_InternalFlickyFly(actor, var1, var2,
+	2*(FRACUNIT/2 - abs(FINECOSINE((((actor->fuse % 144) * 5*ANG1/2) >> ANGLETOFINESHIFT) & FINEMASK)))
+	);
+
+	if (P_MobjFlip(actor)*actor->momz > 0 && actor->frame == 1 && actor->sprite == SPR_FL10)
+		actor->frame = 3;
+}
+
+//Function: A_FlickyCoast
+//
+// Description: Flicky swim-coasting function.
+//
+// var1 = speed to change state upon reaching
+// var2 = state to change to upon slowing down
+// the spawnstate of the mobj = state to change to when above water
+//
+void A_FlickyCoast(mobj_t *actor)
+{
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_FlickyCoast", actor))
+		return;
+#endif
+	if (actor->eflags & MFE_UNDERWATER)
+	{
+		actor->momx = (11*actor->momx)/12;
+		actor->momy = (11*actor->momy)/12;
+		actor->momz = (11*actor->momz)/12;
+
+		if (P_AproxDistance(P_AproxDistance(actor->momx, actor->momy), actor->momz) < locvar1)
+			P_SetMobjState(actor, locvar2);
+
+		return;
+	}
+
+	actor->flags &= ~MF_NOGRAVITY;
+	P_SetMobjState(actor, mobjinfo[actor->type].spawnstate);
+}
+
+// Internal Flicky hopping function.
+void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle)
+{
+	if (((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)
+	|| ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)))
+	{
+		if (momz)
+		{
+			if (actor->eflags & MFE_UNDERWATER)
+				momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT));
+			P_SetObjectMomZ(actor, momz, false);
+		}
+		P_InstaThrust(actor, angle, FixedMul(momh, actor->scale));
+	}
+}
+
+// Function: A_FlickyHop
+//
+// Description: Flicky hopping function.
+//
+// var1 = vertical thrust
+// var2 = horizontal thrust
+//
+void A_FlickyHop(mobj_t *actor)
+{
+	// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyHop instead.
+	//INT32 locvar1 = var1;
+	//INT32 locvar2 = var2;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_FlickyHop", actor))
+		return;
+#endif
+	P_InternalFlickyHop(actor, var1, var2, actor->angle);
+}
+
+// Function: A_FlickyFlounder
+//
+// Description: Flicky floundering function.
+//
+// var1 = intended vertical thrust
+// var2 = intended horizontal thrust
+//
+void A_FlickyFlounder(mobj_t *actor)
+{
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
+	angle_t hopangle;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_FlickyFlounder", actor))
+		return;
+#endif
+	locvar1 *= (P_RandomKey(2) + 1);
+	locvar2 *= (P_RandomKey(2) + 1);
+	hopangle = (actor->angle + (P_RandomKey(9) - 4)*ANG2);
+	P_InternalFlickyHop(actor, locvar1, locvar2, hopangle);
+}
+
+// Function: A_FlickyCheck
+//
+// Description: Flicky airtime check function.
+//
+// var1 = state to change to upon touching the floor
+// var2 = state to change to upon falling
+// the meleestate of the mobj = state to change to when underwater
+//
+void A_FlickyCheck(mobj_t *actor)
+{
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_FlickyCheck", actor))
+		return;
+#endif
+	if (locvar2 && P_MobjFlip(actor)*actor->momz < 1)
+		P_SetMobjState(actor, locvar2);
+	else if (locvar1 && ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)
+	|| ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)))
+		P_SetMobjState(actor, locvar1);
+	else if (mobjinfo[actor->type].meleestate && (actor->eflags & MFE_UNDERWATER))
+		P_SetMobjState(actor, mobjinfo[actor->type].meleestate);
+	P_InternalFlickyBubble(actor);
+}
+
+// Function: A_FlickyHeightCheck
+//
+// Description: Flicky height check function.
+//
+// var1 = state to change to when falling below height relative to target
+// var2 = height relative to target to change state at
+//
+void A_FlickyHeightCheck(mobj_t *actor)
+{
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_FlickyHeightCheck", actor))
+		return;
+#endif
+	if (locvar1 && actor->target && P_MobjFlip(actor)*actor->momz < 1
+	&& ((P_MobjFlip(actor)*((actor->z + actor->height/2) - (actor->target->z + actor->target->height/2)) < locvar2)
+	|| (actor->z - actor->height < actor->floorz) || (actor->z + 2*actor->height > actor->ceilingz)))
+		P_SetMobjState(actor, locvar1);
+	P_InternalFlickyBubble(actor);
+}
+
+// Function: A_FlickyFlutter
+//
+// Description: Flicky fluttering function - specific to chicken.
+//
+// var1 = state to change to upon touching the floor
+// var2 = state to change to upon falling
+// the meleestate of the mobj = state to change to when underwater
+//
+void A_FlickyFlutter(mobj_t *actor)
+{
+	// We're not setting up locvars here - it passes var1 and var2 through to A_FlickyCheck instead.
+	//INT32 locvar1 = var1;
+	//INT32 locvar2 = var2;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_FlickyFlutter", actor))
+		return;
+#endif
+	A_FlickyCheck(actor);
+
+	var1 = ANG30;
+	var2 = 32*FRACUNIT;
+	A_FlickyAim(actor);
+
+	P_InstaThrust(actor, actor->angle, 2*actor->scale);
+	if (P_MobjFlip(actor)*actor->momz < -FRACUNIT/2)
+		actor->momz = -P_MobjFlip(actor)*actor->scale/2;
+}
+
+#undef FLICKYHITWALL
diff --git a/src/p_floor.c b/src/p_floor.c
index e8c3a60535e9e52240cbedc659cc09f39618eea4..f1678c934963d95af871357bd72bed7adf00ff3f 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1753,12 +1753,15 @@ static mobj_t *SearchMarioNode(msecnode_t *node)
 		case MT_GHOST:
 		case MT_OVERLAY:
 		case MT_EMERALDSPAWN:
-		case MT_GREENORB:
-		case MT_YELLOWORB:
-		case MT_BLUEORB:
-		case MT_BLACKORB:
-		case MT_WHITEORB:
-		case MT_PITYORB:
+		case MT_ELEMENTAL_ORB:
+		case MT_ATTRACT_ORB:
+		case MT_FORCE_ORB:
+		case MT_ARMAGEDDON_ORB:
+		case MT_WHIRLWIND_ORB:
+		case MT_PITY_ORB:
+		case MT_FLAMEAURA_ORB:
+		case MT_BUBBLEWRAP_ORB:
+		case MT_THUNDERCOIN_ORB:
 		case MT_IVSP:
 		case MT_SUPERSPARK:
 		case MT_RAIN:
@@ -1787,8 +1790,8 @@ static mobj_t *SearchMarioNode(msecnode_t *node)
 			break;
 		}
 		// Ignore popped monitors, too.
-		if (node->m_thing->flags & MF_MONITOR
-		&& node->m_thing->threshold == 68)
+		if (node->m_thing->health == 0 // this only really applies for monitors
+		|| (!(node->m_thing->flags & MF_MONITOR) && (mobjinfo[node->m_thing->type].flags & MF_MONITOR))) // gold monitor support
 			continue;
 		// Okay, we found something valid.
 		if (!thing // take either the first thing
@@ -3226,15 +3229,15 @@ INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
 			S_StartSound(puncher, sfx_mario9); // Puncher is "close enough"
 		}
 
-		if (itsamonitor)
+		if (itsamonitor && thing)
 		{
-			P_UnsetThingPosition(tmthing);
-			tmthing->x = oldx;
-			tmthing->y = oldy;
-			tmthing->z = oldz;
-			tmthing->momx = 1;
-			tmthing->momy = 1;
-			P_SetThingPosition(tmthing);
+			P_UnsetThingPosition(thing);
+			thing->x = oldx;
+			thing->y = oldy;
+			thing->z = oldz;
+			thing->momx = 1;
+			thing->momy = 1;
+			P_SetThingPosition(thing);
 		}
 	}
 	else
diff --git a/src/p_inter.c b/src/p_inter.c
index 6ad04f4776d810e149b9b4eccfdc8a1a1ae2f2a7..54badc2992614c4aef63917bbf636fa140057922 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -142,7 +142,10 @@ boolean P_CanPickupItem(player_t *player, boolean weapon)
 	if (player->bot && weapon)
 		return false;
 
-	if (player->powers[pw_flashing] > (flashingtics/4)*3 && player->powers[pw_flashing] <= flashingtics)
+	if (player->powers[pw_flashing] > (flashingtics/4)*3 && player->powers[pw_flashing] < UINT16_MAX)
+		return false;
+
+	if (player->mo && player->mo->health <= 0)
 		return false;
 
 	return true;
@@ -296,6 +299,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 {
 	player_t *player;
 	INT32 i;
+	UINT8 elementalpierce;
 
 	if (objectplacing)
 		return;
@@ -350,6 +354,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 		return;
 #endif
 
+	// 0 = none, 1 = elemental pierce, 2 = bubble bounce
+	elementalpierce = (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY)
+	? (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2)
+	: 0);
+
 	if (special->flags & MF_BOSS)
 	{
 		if (special->type == MT_BLACKEGGMAN)
@@ -359,14 +368,20 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 		}
 
 		if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING))
-		|| ((player->pflags & PF_JUMPED) && !(player->charflags & SF_NOJUMPDAMAGE && !(player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
+		|| ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
 		|| (player->pflags & (PF_SPINNING|PF_GLIDING))
 		|| (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)
 		|| ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0))
-		|| player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object?
+		|| player->powers[pw_invulnerability] || player->powers[pw_super]
+		|| elementalpierce) // Do you possess the ability to subdue the object?
 		{
-			if (P_MobjFlip(toucher)*toucher->momz < 0)
-				toucher->momz = -toucher->momz;
+			if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1))
+			{
+				if (elementalpierce == 2)
+					P_DoBubbleBounce(player);
+				else
+					toucher->momz = -toucher->momz;
+			}
 			toucher->momx = -toucher->momx;
 			toucher->momy = -toucher->momy;
 			P_DamageMobj(special, toucher, toucher, 1, 0);
@@ -392,7 +407,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 		/////ENEMIES!!//////////////////////////////////////////
 		////////////////////////////////////////////////////////
 		if (special->type == MT_GSNAPPER && !(((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING))
-		|| player->powers[pw_invulnerability] || player->powers[pw_super])
+		|| player->powers[pw_invulnerability] || player->powers[pw_super] || elementalpierce)
 		&& toucher->z < special->z + special->height && toucher->z + toucher->height > special->z)
 		{
 			// Can only hit snapper from above
@@ -405,14 +420,19 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 			P_DamageMobj(toucher, special, special, 1, 0);
 		}
 		else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING))
-		|| ((player->pflags & PF_JUMPED) && !(player->charflags & SF_NOJUMPDAMAGE && !(player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
+		|| ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
 		|| (player->pflags & (PF_SPINNING|PF_GLIDING))
 		|| (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)
 		|| ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0))
 		|| player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object?
 		{
-			if (P_MobjFlip(toucher)*toucher->momz < 0)
-				toucher->momz = -toucher->momz;
+			if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1))
+			{
+				if (elementalpierce == 2)
+					P_DoBubbleBounce(player);
+				else
+					toucher->momz = -toucher->momz;
+			}
 
 			P_DamageMobj(special, toucher, toucher, 1, 0);
 		}
@@ -1195,9 +1215,17 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 		case MT_FIREFLOWER:
 			if (player->bot)
 				return;
-			player->powers[pw_shield] |= SH_FIREFLOWER;
-			toucher->color = SKINCOLOR_WHITE;
-			G_GhostAddColor(GHC_FIREFLOWER);
+
+			S_StartSound(toucher, sfx_mario3);
+
+			player->powers[pw_shield] = (player->powers[pw_shield] & SH_NOSTACK)|SH_FIREFLOWER;
+
+			if (!(player->powers[pw_super] || (mariomode && player->powers[pw_invulnerability])))
+			{
+				player->mo->color = SKINCOLOR_WHITE;
+				G_GhostAddColor(GHC_FIREFLOWER);
+			}
+
 			break;
 
 // *************** //
@@ -1366,7 +1394,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 					return;
 				}
 				else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING))
-						|| ((player->pflags & PF_JUMPED) && !(player->charflags & SF_NOJUMPDAMAGE))
+						|| ((player->pflags & PF_JUMPED) && (player->pflags & PF_FORCEJUMPDAMAGE || !(player->charflags & SF_NOJUMPSPIN) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
 						|| ((player->charflags & SF_STOMPDAMAGE) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0))
 						|| (player->pflags & (PF_SPINNING|PF_GLIDING))
 						|| player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object?
@@ -1478,7 +1506,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 			return;
 
 		case MT_EXTRALARGEBUBBLE:
-			if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)
+			if (player->powers[pw_shield] & SH_PROTECTWATER)
 				return;
 			if (maptol & TOL_NIGHTS)
 				return;
@@ -1604,8 +1632,10 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
 			else switch (inflictor->type)
 			{
 				case MT_PLAYER:
-					if (damagetype == DMG_NUKE) // SH_BOMB, armageddon shield
+					if (damagetype == DMG_NUKE) // SH_ARMAGEDDON, armageddon shield
 						str = M_GetText("%s%s's armageddon blast %s %s.\n");
+					else if ((inflictor->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && (inflictor->player->pflags & PF_SHIELDABILITY))
+						str = M_GetText("%s%s's flame stomp %s %s.\n");
 					else if (inflictor->player->powers[pw_invulnerability])
 						str = M_GetText("%s%s's invincibility aura %s %s.\n");
 					else if (inflictor->player->powers[pw_super])
@@ -2013,7 +2043,6 @@ boolean P_CheckRacers(void)
   */
 void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype)
 {
-	mobjtype_t item;
 	mobj_t *mo;
 
 	if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL))
@@ -2229,81 +2258,80 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 	if (source && target && target->player && source->player)
 		P_PlayVictorySound(source); // Killer laughs at you. LAUGHS! BWAHAHAHA!
 
+#ifdef OLDANIMALSPAWNING
 	// Drop stuff.
 	// 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
 	&& target->flags & MF_ENEMY)
 	{
-		if (cv_soniccd.value)
-			item = MT_SEED;
-		else
-		{
-			INT32 prandom;
+		mobjtype_t item;
+		INT32 prandom;
 
-			switch (target->type)
-			{
-				case MT_REDCRAWLA:
-				case MT_GOLDBUZZ:
-				case MT_SKIM:
-				case MT_UNIDUS:
-					item = MT_BUNNY;
-					break;
+		switch (target->type)
+		{
+			case MT_REDCRAWLA:
+			case MT_GOLDBUZZ:
+			case MT_SKIM:
+			case MT_UNIDUS:
+				item = MT_FLICKY_02/*MT_BUNNY*/;
+				break;
 
-				case MT_BLUECRAWLA:
-				case MT_JETTBOMBER:
-				case MT_GFZFISH:
-					item = MT_BIRD;
-					break;
+			case MT_BLUECRAWLA:
+			case MT_JETTBOMBER:
+			case MT_GFZFISH:
+				item = MT_FLICKY_01/*MT_BIRD*/;
+				break;
 
-				case MT_JETTGUNNER:
-				case MT_CRAWLACOMMANDER:
-				case MT_REDBUZZ:
-				case MT_DETON:
-					item = MT_MOUSE;
-					break;
+			case MT_JETTGUNNER:
+			case MT_CRAWLACOMMANDER:
+			case MT_REDBUZZ:
+			case MT_DETON:
+				item = MT_FLICKY_12/*MT_MOUSE*/;
+				break;
 
-				case MT_GSNAPPER:
-				case MT_EGGGUARD:
-				case MT_SPRINGSHELL:
-					item = MT_COW;
-					break;
+			case MT_GSNAPPER:
+			case MT_EGGGUARD:
+			case MT_SPRINGSHELL:
+				item = MT_FLICKY_11/*MT_COW*/;
+				break;
 
-				case MT_MINUS:
-				case MT_VULTURE:
-				case MT_POINTY:
-				case MT_YELLOWSHELL:
-					item = MT_CHICKEN;
-					break;
+			case MT_MINUS:
+			case MT_VULTURE:
+			case MT_POINTY:
+			case MT_YELLOWSHELL:
+				item = MT_FLICKY_03/*MT_CHICKEN*/;
+				break;
 
-				case MT_AQUABUZZ:
-					item = MT_REDBIRD;
-					break;
+			case MT_AQUABUZZ:
+				item = MT_FLICKY_01/*MT_REDBIRD*/;
+				break;
 
-				default:
-					if (target->info->doomednum)
-						prandom = target->info->doomednum%5; // "Random" animal for new enemies.
-					else
-						prandom = P_RandomKey(5); // No placable object, just use a random number.
+			default:
+				if (target->info->doomednum)
+					prandom = target->info->doomednum%5; // "Random" animal for new enemies.
+				else
+					prandom = P_RandomKey(5); // No placable object, just use a random number.
 
-					switch(prandom)
-					{
-						default: item = MT_BUNNY; break;
-						case 1: item = MT_BIRD; break;
-						case 2: item = MT_MOUSE; break;
-						case 3: item = MT_COW; break;
-						case 4: item = MT_CHICKEN; break;
-					}
-					break;
-			}
+				switch(prandom)
+				{
+					default: item = MT_FLICKY_02/*MT_BUNNY*/; break;
+					case 1: item = MT_FLICKY_01/*MT_BIRD*/; break;
+					case 2: item = MT_FLICKY_12/*MT_MOUSE*/; break;
+					case 3: item = MT_FLICKY_11/*MT_COW*/; break;
+					case 4: item = MT_FLICKY_03/*MT_CHICKEN*/; break;
+				}
+				break;
 		}
 
 		mo = P_SpawnMobj(target->x, target->y, target->z + (target->height / 2) - FixedMul(mobjinfo[item].height / 2, target->scale), item);
 		mo->destscale = target->scale;
 		P_SetScale(mo, mo->destscale);
 	}
+	else
+#endif
 	// Other death animation effects
-	else switch(target->type)
+	switch(target->type)
 	{
 		case MT_BOUNCEPICKUP:
 		case MT_RAILPICKUP:
@@ -2321,24 +2349,27 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 			break;
 
 		case MT_PLAYER:
-			target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player)
-			target->momx = target->momy = target->momz = 0;
-			if (damagetype == DMG_DROWNED) // drowned
-			{
-				target->movedir = damagetype; // we're MOVING the Damage Into anotheR function... Okay, this is a bit of a hack.
-				if (target->player->charflags & SF_MACHINE)
-					S_StartSound(target, sfx_fizzle);
-				else
-					S_StartSound(target, sfx_drown);
-				// Don't jump up when drowning
-			}
-			else
 			{
-				P_SetObjectMomZ(target, 14*FRACUNIT, false);
-				if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // Spikes
-					S_StartSound(target, sfx_spkdth);
+				target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player)
+				target->momx = target->momy = target->momz = 0;
+
+				if (damagetype == DMG_DROWNED) // drowned
+				{
+					target->movedir = damagetype; // we're MOVING the Damage Into anotheR function... Okay, this is a bit of a hack.
+					if (target->player->charflags & SF_MACHINE)
+						S_StartSound(target, sfx_fizzle);
+					else
+						S_StartSound(target, sfx_drown);
+					// Don't jump up when drowning
+				}
 				else
-					P_PlayDeathSound(target);
+				{
+					P_SetObjectMomZ(target, 14*FRACUNIT, false);
+					if ((source && source->type == MT_SPIKE) || damagetype == DMG_SPIKE) // Spikes
+						S_StartSound(target, sfx_spkdth);
+					else
+						P_PlayDeathSound(target);
+				}
 			}
 			break;
 		default:
@@ -2786,22 +2817,21 @@ void P_RemoveShield(player_t *player)
 {
 	if (player->powers[pw_shield] & SH_FORCE)
 	{ // Multi-hit
-		if ((player->powers[pw_shield] & 0xFF) == 0)
-			player->powers[pw_shield] &= ~SH_FORCE;
-		else
+		if (player->powers[pw_shield] & SH_FORCEHP)
 			player->powers[pw_shield]--;
+		else
+			player->powers[pw_shield] &= SH_STACK;
 	}
 	else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_NONE)
 	{ // Second layer shields
-		player->powers[pw_shield] = SH_NONE;
-		// Reset fireflower
-		if (!player->powers[pw_super])
+		if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !(player->powers[pw_super] || (mariomode && player->powers[pw_invulnerability])))
 		{
 			player->mo->color = player->skincolor;
 			G_GhostAddColor(GHC_NORMAL);
 		}
+		player->powers[pw_shield] = SH_NONE;
 	}
-	else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB) // Give them what's coming to them!
+	else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ARMAGEDDON) // Give them what's coming to them!
 	{
 		P_BlackOw(player); // BAM!
 		player->pflags |= PF_JUMPDOWN;
@@ -3027,12 +3057,15 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 			switch (damagetype)
 			{
 				case DMG_WATER:
+					if (player->powers[pw_shield] & SH_PROTECTWATER)
+						return false; // Invincible to water damage
+					break;
 				case DMG_FIRE:
-					if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)
-						return false; // Invincible to water/fire damage
+					if (player->powers[pw_shield] & SH_PROTECTFIRE)
+						return false; // Invincible to fire damage
 					break;
 				case DMG_ELECTRIC:
-					if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)
+					if (player->powers[pw_shield] & SH_PROTECTELECTRIC)
 						return false; // Invincible to electric damage
 					break;
 				default:
@@ -3061,7 +3094,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 
 		if (!force && inflictor && inflictor->flags & MF_FIRE)
 		{
-			if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)
+			if (player->powers[pw_shield] & SH_PROTECTFIRE)
 				return false; // Invincible to fire objects
 
 			if (G_PlatformGametype() && inflictor && source && source->player)
diff --git a/src/p_local.h b/src/p_local.h
index 8c49e4f1805e64b720604fbcf6b61d093b068f5a..9b7c16702121bb514bfbe6cbd89cb09f40956a65 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -59,9 +59,10 @@
 
 #define AIMINGTOSLOPE(aiming) FINESINE((aiming>>ANGLETOFINESHIFT) & FINEMASK)
 
-#define mariomode (maptol & TOL_MARIO)
 #define twodlevel (maptol & TOL_2D)
 
+#define mariomode (maptol & TOL_MARIO)
+
 #define P_GetPlayerHeight(player) FixedMul(player->height, player->mo->scale)
 #define P_GetPlayerSpinHeight(player) FixedMul(player->spinheight, player->mo->scale)
 
@@ -143,6 +144,7 @@ boolean P_InQuicksand(mobj_t *mo);
 void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative);
 void P_RestoreMusic(player_t *player);
 void P_SpawnShieldOrb(player_t *player);
+void P_SwitchShield(player_t *player, UINT16 shieldtype);
 mobj_t *P_SpawnGhostMobj(mobj_t *mobj);
 void P_GivePlayerRings(player_t *player, INT32 num_rings);
 void P_GivePlayerLives(player_t *player, INT32 numlives);
@@ -152,8 +154,9 @@ void P_ResetScore(player_t *player);
 boolean P_AutoPause(void);
 
 void P_DoJumpShield(player_t *player);
+void P_DoBubbleBounce(player_t *player);
 void P_BlackOw(player_t *player);
-void P_ElementalFireTrail(player_t *player);
+void P_ElementalFire(player_t *player, boolean cropcircle);
 
 void P_DoPityCheck(player_t *player);
 void P_PlayerThink(player_t *player);
@@ -166,7 +169,7 @@ fixed_t P_ReturnThrustX(mobj_t *mo, angle_t angle, fixed_t move);
 fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move);
 void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move);
 
-boolean P_LookForEnemies(player_t *player);
+boolean P_LookForEnemies(player_t *player, boolean nonenemies);
 void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius);
 void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user
 boolean P_SuperReady(player_t *player);
@@ -292,6 +295,11 @@ boolean P_CheckMissileRange(mobj_t *actor);
 void P_NewChaseDir(mobj_t *actor);
 boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed_t dist);
 
+mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers);
+void P_InternalFlickyBubble(mobj_t *actor);
+void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez);
+void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle);
+
 //
 // P_MAP
 //
diff --git a/src/p_map.c b/src/p_map.c
index 6ac48a7c897585cc313564a3653943fbb3e8720b..7afd266fd0d51153bf84be0022b86f04d32578b0 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -203,7 +203,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
 			}
 		}
 
-		pflags = object->player->pflags & (PF_JUMPED|PF_SPINNING|PF_THOKKED); // I still need these.
+		pflags = object->player->pflags & (PF_JUMPED|PF_SPINNING|PF_THOKKED|PF_SHIELDABILITY); // I still need these.
 		jumping = object->player->jumping;
 		secondjump = object->player->secondjump;
 		P_ResetPlayer(object->player);
@@ -969,10 +969,10 @@ static boolean PIT_CheckThing(mobj_t *thing)
 	{
 		if (G_RingSlingerGametype() && (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam))
 		{
-			if ((tmthing->player->powers[pw_invulnerability] || tmthing->player->powers[pw_super])
+			if ((tmthing->player->powers[pw_invulnerability] || tmthing->player->powers[pw_super] || (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) && (tmthing->player->pflags & PF_SHIELDABILITY)))
 				&& !thing->player->powers[pw_super])
 				P_DamageMobj(thing, tmthing, tmthing, 1, 0);
-			else if ((thing->player->powers[pw_invulnerability] || thing->player->powers[pw_super])
+			else if ((thing->player->powers[pw_invulnerability] || thing->player->powers[pw_super] || (((thing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) && (thing->player->pflags & PF_SHIELDABILITY)))
 				&& !tmthing->player->powers[pw_super])
 				P_DamageMobj(tmthing, thing, thing, 1, 0);
 		}
@@ -1052,24 +1052,41 @@ static boolean PIT_CheckThing(mobj_t *thing)
 		else if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height
 			&& thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) >= tmthing->z)
 		{
+			// 0 = none, 1 = elemental pierce, 2 = bubble bounce
+			UINT8 elementalpierce = (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY)
+			? (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2)
+			: 0);
 			if (thing->flags & MF_MONITOR
 				&& (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING)
 				|| ((tmthing->player->pflags & PF_JUMPED)
-					&& !(tmthing->player->charflags & SF_NOJUMPDAMAGE
-					&& !(tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
+					&& (tmthing->player->pflags & PF_FORCEJUMPDAMAGE
+					|| !(tmthing->player->charflags & SF_NOJUMPSPIN)
+					|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
 				|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
 				|| ((tmthing->player->charflags & SF_STOMPDAMAGE)
-					&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))))
+					&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))
+				|| elementalpierce))
 			{
+				player_t *player = tmthing->player;
 				SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed.
 				fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;;
+				fixed_t *z = &tmthing->z; // aau.
 				P_DamageMobj(thing, tmthing, tmthing, 1, 0); // break the monitor
 				// Going down? Then bounce back up.
 				if ((P_MobjWasRemoved(thing) // Monitor was removed
 					|| !thing->health) // or otherwise popped
-				&& (flipval*(*momz) < 0)) // monitor is on the floor and you're going down, or on the ceiling and you're going up
-					*momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically.
-				return false;
+				&& (flipval*(*momz) < 0) // monitor is on the floor and you're going down, or on the ceiling and you're going up
+				&& (elementalpierce != 1)) // you're not piercing through the monitor...
+				{
+					if (elementalpierce == 2)
+						P_DoBubbleBounce(player);
+					else
+						*momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically.
+				}
+				if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough.
+					return false;
+				else
+					*z -= *momz; // to ensure proper collision.
 			}
 		}
 	}
@@ -1084,8 +1101,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
 	else if (thing->flags & MF_MONITOR && tmthing->player
 	&& (tmthing->player->pflags & (PF_SPINNING|PF_GLIDING)
 		|| ((tmthing->player->pflags & PF_JUMPED)
-			&& !(tmthing->player->charflags & SF_NOJUMPDAMAGE
-			&& !(tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
+			&& (tmthing->player->pflags & PF_FORCEJUMPDAMAGE
+			|| !(tmthing->player->charflags & SF_NOJUMPSPIN)
+			|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
 		|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
 		|| ((tmthing->player->charflags & SF_STOMPDAMAGE)
 			&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0)))
@@ -1124,6 +1142,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
 			if (tmthing->player && tmthing->z + tmthing->height > topz
 				&& tmthing->z + tmthing->height < tmthing->ceilingz)
 			{
+				if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->flags2 & MF2_STANDONME)) // Gold monitor hack...
+					return false;
+
 				tmfloorz = tmceilingz = INT32_MIN; // block while in air
 #ifdef ESLOPE
 				tmceilingslope = NULL;
@@ -1167,6 +1188,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
 			if (tmthing->player && tmthing->z < topz
 				&& tmthing->z > tmthing->floorz)
 			{
+				if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->flags2 & MF2_STANDONME)) // Gold monitor hack...
+					return false;
+
 				tmfloorz = tmceilingz = INT32_MAX; // block while in air
 #ifdef ESLOPE
 				tmfloorslope = NULL;
diff --git a/src/p_maputl.c b/src/p_maputl.c
index fea8530a125bf3a5d001d87507f5513a85bb1e06..46b033386410c2119d1af74292e7684ecfac5e36 100644
--- a/src/p_maputl.c
+++ b/src/p_maputl.c
@@ -572,51 +572,54 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
 			side_t *side = &sides[linedef->sidenum[0]];
 			fixed_t textop, texbottom, texheight;
 			fixed_t texmid, delta1, delta2;
+			INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid
 
-			// Get the midtexture's height
-			texheight = textures[texturetranslation[side->midtexture]]->height << FRACBITS;
+			if (texnum) {
+				// Get the midtexture's height
+				texheight = textures[texnum]->height << FRACBITS;
 
-			// Set texbottom and textop to the Z coordinates of the texture's boundaries
+				// Set texbottom and textop to the Z coordinates of the texture's boundaries
 #if 0 // #ifdef POLYOBJECTS
-			// don't remove this code unless solid midtextures
-			// on non-solid polyobjects should NEVER happen in the future
-			if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) {
-				if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat
-					texbottom = back->floorheight + side->rowoffset;
-					textop = back->ceilingheight + side->rowoffset;
-				} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
-					texbottom = back->floorheight + side->rowoffset;
-					textop = texbottom + texheight*(side->repeatcnt+1);
-				} else {
-					textop = back->ceilingheight + side->rowoffset;
-					texbottom = textop - texheight*(side->repeatcnt+1);
-				}
-			} else
+				// don't remove this code unless solid midtextures
+				// on non-solid polyobjects should NEVER happen in the future
+				if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) {
+					if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat
+						texbottom = back->floorheight + side->rowoffset;
+						textop = back->ceilingheight + side->rowoffset;
+					} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
+						texbottom = back->floorheight + side->rowoffset;
+						textop = texbottom + texheight*(side->repeatcnt+1);
+					} else {
+						textop = back->ceilingheight + side->rowoffset;
+						texbottom = textop - texheight*(side->repeatcnt+1);
+					}
+				} else
 #endif
-			{
-				if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat
-					texbottom = openbottom + side->rowoffset;
-					textop = opentop + side->rowoffset;
-				} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
-					texbottom = openbottom + side->rowoffset;
-					textop = texbottom + texheight*(side->repeatcnt+1);
-				} else {
-					textop = opentop + side->rowoffset;
-					texbottom = textop - texheight*(side->repeatcnt+1);
+				{
+					if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat
+						texbottom = openbottom + side->rowoffset;
+						textop = opentop + side->rowoffset;
+					} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
+						texbottom = openbottom + side->rowoffset;
+						textop = texbottom + texheight*(side->repeatcnt+1);
+					} else {
+						textop = opentop + side->rowoffset;
+						texbottom = textop - texheight*(side->repeatcnt+1);
+					}
 				}
-			}
 
-			texmid = texbottom+(textop-texbottom)/2;
+				texmid = texbottom+(textop-texbottom)/2;
 
-			delta1 = abs(mobj->z - texmid);
-			delta2 = abs(thingtop - texmid);
+				delta1 = abs(mobj->z - texmid);
+				delta2 = abs(thingtop - texmid);
 
-			if (delta1 > delta2) { // Below
-				if (opentop > texbottom)
-					opentop = texbottom;
-			} else { // Above
-				if (openbottom < textop)
-					openbottom = textop;
+				if (delta1 > delta2) { // Below
+					if (opentop > texbottom)
+						opentop = texbottom;
+				} else { // Above
+					if (openbottom < textop)
+						openbottom = textop;
+				}
 			}
 		}
 
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 66041c7dd504aa2f5b875b64540318dc87f12df2..b6971d533b78dba93f6940369f2e2bcc89959e44 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -2638,6 +2638,23 @@ static boolean P_ZMovement(mobj_t *mo)
 				mo->flags |= MF_NOGRAVITY;
 			}
 			break;
+		case MT_SPINFIRE:
+			if (P_CheckDeathPitCollide(mo))
+			{
+				P_RemoveMobj(mo);
+				return false;
+			}
+			if (mo->momz
+			&& !(mo->flags & MF_NOGRAVITY)
+			&& ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z <= mo->floorz)
+			|| ((mo->eflags & MFE_VERTICALFLIP) && mo->z+mo->height >= mo->ceilingz)))
+			{
+				mo->flags |= MF_NOGRAVITY;
+				mo->momx = 8; // this is a hack which is used to ensure it still behaves as a missile and can damage others
+				mo->momy = mo->momz = 0;
+				mo->z = ((mo->eflags & MFE_VERTICALFLIP) ? mo->ceilingz-mo->height : mo->floorz);
+			}
+			break;
 		case MT_GOOP:
 			if (P_CheckDeathPitCollide(mo))
 			{
@@ -3122,6 +3139,8 @@ static void P_PlayerZMovement(mobj_t *mo)
 
 		if (P_MobjFlip(mo)*mo->momz < 0) // falling
 		{
+			boolean clipmomz = !(P_CheckDeathPitCollide(mo));
+
 			mo->pmomz = 0; // We're on a new floor, don't keep doing platform movement.
 
 			// Squat down. Decrease viewheight for a moment after hitting the ground (hard),
@@ -3251,23 +3270,56 @@ static void P_PlayerZMovement(mobj_t *mo)
 						mo->player->pflags &= ~PF_SPINNING;
 
 					if (!(mo->player->pflags & PF_GLIDING))
-						mo->player->pflags &= ~PF_JUMPED;
+						mo->player->pflags &= ~(PF_JUMPED|PF_FORCEJUMPDAMAGE);
+
 					mo->player->pflags &= ~(PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/);
 					mo->player->jumping = 0;
 					mo->player->secondjump = 0;
 					mo->player->glidetime = 0;
 					mo->player->climbing = 0;
 					mo->player->powers[pw_tailsfly] = 0;
+
+					if (mo->player->pflags & PF_SHIELDABILITY)
+					{
+						mo->player->pflags &= ~PF_SHIELDABILITY;
+
+						if ((mo->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) // Elemental shield's stomp attack.
+						{
+							if (mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) // play a blunt sound
+								S_StartSound(mo, sfx_s3k4c);
+							else // create a fire pattern on the ground
+							{
+								S_StartSound(mo, sfx_s3k47);
+								P_ElementalFire(mo->player, true);
+							}
+							P_SetObjectMomZ(mo,
+							(mo->eflags & MFE_UNDERWATER)
+							? 6*FRACUNIT/5
+							: 5*FRACUNIT/2,
+							false);
+							P_SetPlayerMobjState(mo, S_PLAY_FALL);
+							mo->momx = mo->momy = 0;
+							clipmomz = false;
+						}
+						else if ((mo->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) // Bubble shield's bounce attack.
+						{
+							P_DoBubbleBounce(mo->player);
+							clipmomz = false;
+						}
+					}
 				}
 			}
 			if (!(mo->player->pflags & PF_SPINNING))
 				mo->player->pflags &= ~PF_STARTDASH;
 
-			if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR)
-			|| tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER))
-				mo->momz = tmfloorthing->momz;
-			else if (!tmfloorthing)
-				mo->momz = 0;
+			if (clipmomz)
+			{
+				if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR)
+				|| tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER))
+					mo->momz = tmfloorthing->momz;
+				else if (!tmfloorthing)
+					mo->momz = 0;
+			}
 		}
 		else if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR)
 		|| tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER))
@@ -3436,17 +3488,14 @@ static boolean P_SceneryZMovement(mobj_t *mo)
 			if ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z <= mo->floorz)
 			|| (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height >= mo->ceilingz))
 			{
-				// DO NOT use random numbers here.
-				// SonicCD mode is console togglable and
-				// affects demos.
-				UINT8 rltime = (leveltime & 4);
-
-				if (!rltime)
-					P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER3);
-				else if (rltime == 2)
-					P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER2);
-				else
-					P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER1);
+				mobjtype_t flowertype = ((P_RandomChance(FRACUNIT/2)) ? MT_GFZFLOWER1 : MT_GFZFLOWER3);
+				mobj_t *flower = P_SpawnMobjFromMobj(mo, 0, 0, 0, flowertype);
+				if (flower)
+				{
+					P_SetScale(flower, mo->scale/16);
+					flower->destscale = mo->scale;
+					flower->scalespeed = mo->scale/8;
+				}
 
 				P_RemoveMobj(mo);
 				return false;
@@ -3544,6 +3593,7 @@ void P_MobjCheckWater(mobj_t *mobj)
 	ffloor_t *rover;
 	player_t *p = mobj->player; // Will just be null if not a player.
 	fixed_t height = (p ? P_GetPlayerHeight(p) : mobj->height); // for players, calculation height does not necessarily match actual height for gameplay reasons (spin, etc)
+	boolean wasgroundpounding = (p && (mobj->eflags & MFE_GOOWATER) && ((p->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (p->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (p->pflags & PF_SHIELDABILITY));
 
 	// Default if no water exists.
 	mobj->watertop = mobj->waterbottom = mobj->z - 1000*FRACUNIT;
@@ -3614,15 +3664,24 @@ void P_MobjCheckWater(mobj_t *mobj)
 	{
 		if (!((p->powers[pw_super]) || (p->powers[pw_invulnerability])))
 		{
-			if ((p->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)
-			{ // Water removes attract shield.
+			boolean electric = !!(p->powers[pw_shield] & SH_PROTECTELECTRIC);
+#define SH_OP (SH_PROTECTFIRE|SH_PROTECTWATER|SH_PROTECTELECTRIC)
+			if ((p->powers[pw_shield] & SH_OP) == SH_OP) // No.
+				P_KillMobj(mobj, NULL, NULL, DMG_INSTAKILL);
+#undef SH_OP
+			else if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER)))
+			{ // Water removes electric and non-water fire shields...
+				P_FlashPal(p,
+				electric
+				? PAL_WHITE
+				: PAL_NUKE,
+				1);
 				p->powers[pw_shield] = p->powers[pw_shield] & SH_STACK;
-				P_FlashPal(p, PAL_WHITE, 1);
 			}
 		}
 
 		// Drown timer setting
-		if ((p->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL // Has elemental
+		if ((p->powers[pw_shield] & SH_PROTECTWATER) // Has water protection
 		 || (p->exiting) // Or exiting
 		 || (maptol & TOL_NIGHTS) // Or in NiGHTS mode
 		 || (mariomode)) // Or in Mario mode...
@@ -3635,6 +3694,12 @@ void P_MobjCheckWater(mobj_t *mobj)
 			// Then we'll set it!
 			p->powers[pw_underwater] = underwatertics + 1;
 		}
+
+		if (wasgroundpounding)
+		{
+			p->pflags &= ~PF_SHIELDABILITY;
+			mobj->momz >>= 1;
+		}
 	}
 
 	// The rest of this code only executes on a water state change.
@@ -3652,7 +3717,7 @@ void P_MobjCheckWater(mobj_t *mobj)
 			|| ((mobj->eflags & MFE_VERTICALFLIP) && mobj->ceilingz-mobj->waterbottom <= height>>1))
 			return;
 
-		if ((mobj->eflags & MFE_GOOWATER || wasingoo)) { // Decide what happens to your momentum when you enter/leave goopy water.
+		if (!wasgroundpounding && (mobj->eflags & MFE_GOOWATER || wasingoo)) { // Decide what happens to your momentum when you enter/leave goopy water.
 			if (P_MobjFlip(mobj)*mobj->momz < 0) // You are entering the goo?
 				mobj->momz = FixedMul(mobj->momz, FixedDiv(2*FRACUNIT, 5*FRACUNIT)); // kill momentum significantly, to make the goo feel thick.
 		}
@@ -4871,7 +4936,7 @@ static void P_Boss4MoveSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz)
 {
 	INT32 s;
 	mobj_t *base = mobj, *seg;
-	fixed_t dist, bz = (mobj->spawnpoint->z+16)<<FRACBITS;
+	fixed_t dist, bz = mobj->watertop+(16<<FRACBITS);
 	while ((base = base->tracer))
 	{
 		for (seg = base, dist = 172*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 124*FRACUNIT, --s)
@@ -4885,7 +4950,7 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz)
 {
 	INT32 s;
 	mobj_t *base = mobj, *seg;
-	fixed_t dist, bz = (mobj->spawnpoint->z+16)<<FRACBITS;
+	fixed_t dist, bz = mobj->watertop+(16<<FRACBITS);
 	while ((base = base->tracer))
 	{
 		for (seg = base, dist = 112*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 132*FRACUNIT, --s)
@@ -5001,7 +5066,7 @@ static void P_Boss4Thinker(mobj_t *mobj)
 			INT32 i, arm;
 			mobj_t *seg, *base = mobj;
 			// First frame init, spawn all the things.
-			mobj->spawnpoint->z = mobj->z>>FRACBITS;
+			mobj->watertop = mobj->z;
 			z = mobj->z + mobj->height/2 - mobjinfo[MT_EGGMOBILE4_MACE].height/2;
 			for (arm = 0; arm <3 ; arm++)
 			{
@@ -5057,7 +5122,7 @@ static void P_Boss4Thinker(mobj_t *mobj)
 	case 3:
 	{
 		fixed_t z;
-		if (mobj->z < (mobj->spawnpoint->z+512)<<FRACBITS)
+		if (mobj->z < mobj->watertop+(512<<FRACBITS))
 			mobj->momz = 8*FRACUNIT;
 		else
 		{
@@ -5066,7 +5131,7 @@ static void P_Boss4Thinker(mobj_t *mobj)
 		}
 		mobj->movecount += 400<<(FRACBITS>>1);
 		mobj->movecount %= 360*FRACUNIT;
-		z = mobj->z - (mobj->spawnpoint->z<<FRACBITS) - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2;
+		z = mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2;
 		if (z < 0) // We haven't risen high enough to pull the spikeballs along yet
 			P_Boss4MoveSpikeballs(mobj, FixedAngle(mobj->movecount), 0); // So don't pull the spikeballs along yet.
 		else
@@ -5076,13 +5141,13 @@ static void P_Boss4Thinker(mobj_t *mobj)
 	// Pinch phase!
 	case 4:
 	{
-		if (mobj->z < (mobj->spawnpoint->z+512+128*(mobj->info->damage-mobj->health))<<FRACBITS)
+		if (mobj->z < (mobj->watertop + ((512+128*(mobj->info->damage-mobj->health))<<FRACBITS)))
 			mobj->momz = 8*FRACUNIT;
 		else
 			mobj->momz = 0;
 		mobj->movecount += (800+800*(mobj->info->damage-mobj->health))<<(FRACBITS>>1);
 		mobj->movecount %= 360*FRACUNIT;
-		P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->z - (mobj->spawnpoint->z<<FRACBITS) - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2);
+		P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2);
 
 		if (!mobj->target || !mobj->target->health)
 			P_SupermanLook4Players(mobj);
@@ -6324,7 +6389,7 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
 
 	// TODO: Make an MT_SHIELDORB which changes color/states to always match the appropriate shield,
 	// instead of having completely seperate mobjtypes.
-	if (shield != SH_FORCE)
+	if (!(shield & SH_FORCE))
 	{ // Regular shields check for themselves only
 		if ((shieldtype_t)(thing->target->player->powers[pw_shield] & SH_NOSTACK) != shield)
 		{
@@ -6338,9 +6403,9 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
 		return false;
 	}
 
-	if (shield == SH_FORCE && thing->movecount != (thing->target->player->powers[pw_shield] & 0xFF))
+	if (shield & SH_FORCE && thing->movecount != (thing->target->player->powers[pw_shield] & SH_FORCEHP))
 	{
-		thing->movecount = (thing->target->player->powers[pw_shield] & 0xFF);
+		thing->movecount = (thing->target->player->powers[pw_shield] & SH_FORCEHP);
 		if (thing->movecount < 1)
 		{
 			if (thing->info->painstate)
@@ -6361,13 +6426,14 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
 	thing->eflags = (thing->eflags & ~MFE_VERTICALFLIP)|(thing->target->eflags & MFE_VERTICALFLIP);
 
 	P_SetScale(thing, FixedMul(thing->target->scale, thing->target->player->shieldscale));
+	thing->destscale = thing->scale;
 	P_UnsetThingPosition(thing);
 	thing->x = thing->target->x;
 	thing->y = thing->target->y;
 	if (thing->eflags & MFE_VERTICALFLIP)
-		thing->z = thing->target->z + thing->target->height - thing->height + FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT) - FixedMul(2*FRACUNIT, thing->target->scale);
+		thing->z = thing->target->z + (thing->target->height - thing->height + FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT)) - FixedMul(2*FRACUNIT, thing->target->scale);
 	else
-		thing->z = thing->target->z - FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT) + FixedMul(2*FRACUNIT, thing->target->scale);
+		thing->z = thing->target->z - (FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT)) + FixedMul(2*FRACUNIT, thing->target->scale);
 	P_SetThingPosition(thing);
 	P_CheckPosition(thing, thing->x, thing->y);
 
@@ -6390,7 +6456,7 @@ void P_RunShields(void)
 	// run shields
 	for (i = 0; i < numshields; i++)
 	{
-		P_ShieldLook(shields[i], shields[i]->info->speed);
+		P_ShieldLook(shields[i], shields[i]->threshold);
 		P_SetTarget(&shields[i], NULL);
 	}
 	numshields = 0;
@@ -6398,7 +6464,7 @@ void P_RunShields(void)
 
 static boolean P_AddShield(mobj_t *thing)
 {
-	shieldtype_t shield = thing->info->speed;
+	shieldtype_t shield = thing->threshold;
 
 	if (!thing->target || thing->target->health <= 0 || !thing->target->player
 		|| (thing->target->player->powers[pw_shield] & SH_NOSTACK) == SH_NONE || thing->target->player->powers[pw_super]
@@ -6408,7 +6474,7 @@ static boolean P_AddShield(mobj_t *thing)
 		return false;
 	}
 
-	if (shield != SH_FORCE)
+	if (!(shield & SH_FORCE))
 	{ // Regular shields check for themselves only
 		if ((shieldtype_t)(thing->target->player->powers[pw_shield] & SH_NOSTACK) != shield)
 		{
@@ -6446,6 +6512,13 @@ void P_RunOverlays(void)
 
 		if (!mo->target)
 			continue;
+
+		if (P_MobjWasRemoved(mo->target))
+		{
+			P_RemoveMobj(mo);
+			continue;
+		}
+
 		if (!splitscreen /*&& rendermode != render_soft*/)
 		{
 			angle_t viewingangle;
@@ -6625,7 +6698,7 @@ void P_MobjThinker(mobj_t *mobj)
 		fixed_t oldheight = mobj->height;
 		UINT8 correctionType = 0; // Don't correct Z position, just gain height
 
-		if (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz
+		if ((mobj->flags & MF_NOCLIPHEIGHT || (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz))
 		&& mobj->type != MT_EGGMOBILE_FIRE)
 			correctionType = 1; // Correct Z position by centering
 		else if (mobj->eflags & MFE_VERTICALFLIP)
@@ -6670,6 +6743,11 @@ void P_MobjThinker(mobj_t *mobj)
 		if (P_MobjWasRemoved(mobj))
 			return;
 #endif
+
+		if (mobj->flags2 & MF2_SHIELD)
+			if (!P_AddShield(mobj))
+				return;
+
 		switch (mobj->type)
 		{
 			case MT_HOOP:
@@ -6726,14 +6804,120 @@ void P_MobjThinker(mobj_t *mobj)
 				else
 					P_AddOverlay(mobj);
 				break;
-			case MT_BLACKORB:
-			case MT_WHITEORB:
-			case MT_GREENORB:
-			case MT_YELLOWORB:
-			case MT_BLUEORB:
-			case MT_PITYORB:
-				if (!P_AddShield(mobj))
+			case MT_PITY_ORB:
+			case MT_WHIRLWIND_ORB:
+			case MT_ARMAGEDDON_ORB:
+				if (!(mobj->flags2 & MF2_SHIELD))
+					return;
+				break;
+			case MT_ATTRACT_ORB:
+				if (!(mobj->flags2 & MF2_SHIELD))
+					return;
+				if (/*(mobj->target) -- the following is implicit by P_AddShield
+				&& (mobj->target->player)
+				&& */ (mobj->target->player->homing))
+				{
+					P_SetMobjState(mobj, mobj->info->painstate);
+					mobj->tics++;
+				}
+				break;
+			case MT_ELEMENTAL_ORB:
+				if (!(mobj->flags2 & MF2_SHIELD))
+					return;
+				if (mobj->tracer
+				/* && mobj->target -- the following is implicit by P_AddShield
+				&& mobj->target->player
+				&& (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL */
+				&& mobj->target->player->pflags & PF_SHIELDABILITY
+				&& ((statenum_t)(mobj->tracer->state-states) < mobj->info->raisestate
+					|| (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1)))
+				{
+					P_SetMobjState(mobj, mobj->info->painstate);
+					mobj->tics++;
+					P_SetMobjState(mobj->tracer, mobj->info->raisestate);
+					mobj->tracer->tics++;
+				}
+				break;
+			case MT_FORCE_ORB:
+				if (!(mobj->flags2 & MF2_SHIELD))
+					return;
+				if (/*
+				&& mobj->target -- the following is implicit by P_AddShield
+				&& mobj->target->player
+				&& (mobj->target->player->powers[pw_shield] & SH_FORCE)
+				&& */ (mobj->target->player->pflags & PF_SHIELDABILITY))
+				{
+					mobj_t *whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct
+					P_SetMobjState(whoosh, mobj->info->raisestate);
+					whoosh->destscale = whoosh->scale<<1;
+					whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale);
+					whoosh->height = 38*whoosh->scale;
+					whoosh->fuse = 10;
+					whoosh->flags |= MF_NOCLIPHEIGHT;
+					whoosh->momz = mobj->target->momz; // Stay reasonably centered for a few frames
+					mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal whoosh
+				}
+			case MT_FLAMEAURA_ORB:
+				if (!(mobj->flags2 & MF2_SHIELD))
+					return;
+				mobj->angle = mobj->target->angle; // implicitly okay because of P_AddShield
+				if (mobj->tracer
+				/* && mobj->target -- the following is implicit by P_AddShield
+				&& mobj->target->player
+				&& (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_FLAMEAURA */
+				&& mobj->target->player->pflags & PF_SHIELDABILITY
+				&& ((statenum_t)(mobj->tracer->state-states) < mobj->info->raisestate
+					|| (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1)))
+				{
+					P_SetMobjState(mobj, mobj->info->painstate);
+					mobj->tics++;
+					P_SetMobjState(mobj->tracer, mobj->info->raisestate);
+					mobj->tracer->tics++;
+				}
+				break;
+			case MT_BUBBLEWRAP_ORB:
+				if (!(mobj->flags2 & MF2_SHIELD))
+					return;
+				if (mobj->tracer
+				/* && mobj->target -- the following is implicit by P_AddShield
+				&& mobj->target->player
+				&& (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP */
+				)
+				{
+					if (mobj->target->player->pflags & PF_SHIELDABILITY
+					&& ((statenum_t)(mobj->state-states) < mobj->info->painstate
+						|| (mobj->state->nextstate < mobj->info->painstate && mobj->tics == 1)))
+					{
+						P_SetMobjState(mobj, mobj->info->painstate);
+						mobj->tics++;
+						P_SetMobjState(mobj->tracer, mobj->info->raisestate);
+						mobj->tracer->tics++;
+					}
+					else if (mobj->target->eflags & MFE_JUSTHITFLOOR
+					&& (statenum_t)(mobj->state-states) == mobj->info->painstate)
+					{
+						P_SetMobjState(mobj, mobj->info->painstate+1);
+						mobj->tics++;
+						P_SetMobjState(mobj->tracer, mobj->info->raisestate+1);
+						mobj->tracer->tics++;
+					}
+				}
+				break;
+			case MT_THUNDERCOIN_ORB:
+				if (!(mobj->flags2 & MF2_SHIELD))
 					return;
+				if (mobj->tracer
+				/* && mobj->target -- the following is implicit by P_AddShield
+				&& mobj->target->player
+				&& (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_THUNDERCOIN */
+				&& (mobj->target->player->pflags & PF_SHIELDABILITY))
+				{
+					P_SetMobjState(mobj, mobj->info->painstate);
+					mobj->tics++;
+					P_SetMobjState(mobj->tracer, mobj->info->raisestate);
+					mobj->tracer->tics++;
+					mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal spark
+				}
 				break;
 			case MT_WATERDROP:
 				P_SceneryCheckWater(mobj);
@@ -6868,7 +7052,8 @@ void P_MobjThinker(mobj_t *mobj)
 				}
 				break;
 			case MT_SEED:
-				mobj->momz = mobj->info->speed;
+				if (P_MobjFlip(mobj)*mobj->momz < mobj->info->speed)
+					mobj->momz = P_MobjFlip(mobj)*mobj->info->speed;
 				break;
 			case MT_ROCKCRUMBLE1:
 			case MT_ROCKCRUMBLE2:
@@ -7017,14 +7202,14 @@ void P_MobjThinker(mobj_t *mobj)
 			if (mobj->fuse > 0 && mobj->fuse < 2*TICRATE-(TICRATE/7)
 				&& (mobj->fuse & 3))
 			{
-				INT32 i,j;
+				INT32 i;
 				fixed_t x,y,z;
 				fixed_t ns;
 				mobj_t *mo2;
+				mobj_t *flicky;
 
-				i = P_RandomByte();
 				z = mobj->subsector->sector->floorheight + ((P_RandomByte()&63)*FRACUNIT);
-				for (j = 0; j < 2; j++)
+				for (i = 0; i < 2; i++)
 				{
 					const angle_t fa = (P_RandomByte()*FINEANGLES/16) & FINEMASK;
 					ns = 64 * FRACUNIT;
@@ -7032,25 +7217,22 @@ void P_MobjThinker(mobj_t *mobj)
 					y = mobj->y + FixedMul(FINECOSINE(fa),ns);
 
 					mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE);
+					P_SetMobjStateNF(mo2, S_XPLD_EGGTRAP); // so the flickies don't lose their target if they spawn
 					ns = 4 * FRACUNIT;
 					mo2->momx = FixedMul(FINESINE(fa),ns);
 					mo2->momy = FixedMul(FINECOSINE(fa),ns);
+					mo2->angle = fa << ANGLETOFINESHIFT;
 
-					i = P_RandomByte();
-
-					if (i % 5 == 0)
-						P_SpawnMobj(x, y, z, MT_CHICKEN);
-					else if (i % 4 == 0)
-						P_SpawnMobj(x, y, z, MT_COW);
-					else if (i % 3 == 0)
-					{
-						P_SpawnMobj(x, y, z, MT_BIRD);
+					if (P_RandomChance(FRACUNIT/4)) // I filled a spreadsheet trying to get the equivalent chance to the original P_RandomByte hack!
 						S_StartSound(mo2, mobj->info->deathsound);
-					}
-					else if ((i & 1) == 0)
-						P_SpawnMobj(x, y, z, MT_BUNNY);
-					else
-						P_SpawnMobj(x, y, z, MT_MOUSE);
+
+					flicky = P_InternalFlickySpawn(mo2, 0, 8*FRACUNIT, false);
+					if (!flicky)
+						break;
+
+					P_SetTarget(&flicky->target, mo2);
+					flicky->momx = mo2->momx;
+					flicky->momy = mo2->momy;
 				}
 
 				mobj->fuse--;
@@ -7111,6 +7293,8 @@ void P_MobjThinker(mobj_t *mobj)
 			}
 			break;
 		case MT_AQUABUZZ:
+			P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn
+			// no break here on purpose
 		case MT_BIGAIRMINE:
 			{
 				if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0
@@ -7569,11 +7753,26 @@ void P_MobjThinker(mobj_t *mobj)
 				mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE);
 #endif
 			break;
+		case MT_SPINDUST: // Spindash dust
+				mobj->momx = FixedMul(mobj->momx, (3*FRACUNIT)/4); // originally 50000
+				mobj->momy = FixedMul(mobj->momy, (3*FRACUNIT)/4); // same
+				//mobj->momz = mobj->momz+P_MobjFlip(mobj)/3; // no meaningful change in value to be frank
+				if (mobj->state >= &states[S_SPINDUST_BUBBLE1] && mobj->state <= &states[S_SPINDUST_BUBBLE4]) // bubble dust!
+				{
+					P_MobjCheckWater(mobj);
+					if (mobj->watertop != mobj->subsector->sector->floorheight - 1000*FRACUNIT
+						&& mobj->z+mobj->height >= mobj->watertop - 5*FRACUNIT)
+						mobj->flags2 |= MF2_DONTDRAW;
+				}
+			break;
 		case MT_SPINFIRE:
-			if (mobj->eflags & MFE_VERTICALFLIP)
-				mobj->z = mobj->ceilingz - mobj->height;
-			else
-				mobj->z = mobj->floorz;
+			if (mobj->flags & MF_NOGRAVITY)
+			{
+				if (mobj->eflags & MFE_VERTICALFLIP)
+					mobj->z = mobj->ceilingz - mobj->height;
+				else
+					mobj->z = mobj->floorz;
+			}
 			// THERE IS NO BREAK HERE ON PURPOSE
 		default:
 			// check mobj against possible water content, before movement code
@@ -8114,6 +8313,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 
 		if (mobj->type == MT_UNIDUS)
 			mobj->z -= FixedMul(mobj->info->mass, mobj->scale);
+
+		// defaults onground
+		if (mobj->z + mobj->height == mobj->ceilingz)
+			mobj->eflags |= MFE_ONGROUND;
 	}
 	else
 		mobj->z = z;
@@ -8202,13 +8405,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 			// Special condition for the 2nd boss.
 			mobj->watertop = mobj->info->speed;
 			break;
-		case MT_BIRD:
-		case MT_BUNNY:
-		case MT_MOUSE:
-		case MT_CHICKEN:
-		case MT_COW:
-		case MT_REDBIRD:
-			mobj->fuse = P_RandomRange(300, 350);
+		case MT_FLICKY_08:
+			mobj->color = (P_RandomChance(FRACUNIT/2) ? SKINCOLOR_RED : SKINCOLOR_AQUA);
 			break;
 		case MT_REDRING: // Make MT_REDRING red by default
 			mobj->color = skincolor_redring;
diff --git a/src/p_mobj.h b/src/p_mobj.h
index a8ec27f1a84911b14b3d8f0a1bfb70cae902d45d..f6ebd3cadc497465312a139860ee2975b74619cc 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -193,6 +193,7 @@ typedef enum
 	MF2_BOSSDEAD       = 1<<26, // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.)
 	MF2_AMBUSH         = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH
 	MF2_LINKDRAW       = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position)
+	MF2_SHIELD         = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use)
 	// free: to and including 1<<31
 } mobjflag2_t;
 
diff --git a/src/p_saveg.c b/src/p_saveg.c
index ee8e623fd6a65f650eed3a22b5140721a6ce9109..ed23ca7a223e56700e070caee080e353db35df42 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -470,6 +470,7 @@ static void P_NetUnArchivePlayers(void)
 #define SD_TAG       0x10
 #define SD_FLOORANG  0x20
 #define SD_CEILANG   0x40
+#define SD_TAGLIST   0x80
 
 #define LD_FLAG     0x01
 #define LD_SPECIAL  0x02
@@ -519,10 +520,9 @@ static void P_NetArchiveWorld(void)
 		//
 		// flats
 		//
-		// P_AddLevelFlat should not add but just return the number
-		if (ss->floorpic != P_AddLevelFlat(ms->floorpic, levelflats))
+		if (ss->floorpic != P_CheckLevelFlat(ms->floorpic))
 			diff |= SD_FLOORPIC;
-		if (ss->ceilingpic != P_AddLevelFlat(ms->ceilingpic, levelflats))
+		if (ss->ceilingpic != P_CheckLevelFlat(ms->ceilingpic))
 			diff |= SD_CEILPIC;
 
 		if (ss->lightlevel != SHORT(ms->lightlevel))
@@ -545,6 +545,8 @@ static void P_NetArchiveWorld(void)
 
 		if (ss->tag != SHORT(ms->tag))
 			diff2 |= SD_TAG;
+		if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag)
+			diff2 |= SD_TAGLIST;
 
 		// Check if any of the sector's FOFs differ from how they spawned
 		if (ss->ffloors)
@@ -592,16 +594,17 @@ static void P_NetArchiveWorld(void)
 				WRITEFIXED(put, ss->ceiling_xoffs);
 			if (diff2 & SD_CYOFFS)
 				WRITEFIXED(put, ss->ceiling_yoffs);
-			if (diff2 & SD_TAG)
-			{
+			if (diff2 & SD_TAG) // save only the tag
 				WRITEINT16(put, ss->tag);
-				WRITEINT32(put, ss->firsttag);
-				WRITEINT32(put, ss->nexttag);
-			}
 			if (diff2 & SD_FLOORANG)
 				WRITEANGLE(put, ss->floorpic_angle);
 			if (diff2 & SD_CEILANG)
 				WRITEANGLE(put, ss->ceilingpic_angle);
+			if (diff2 & SD_TAGLIST) // save both firsttag and nexttag
+			{ // either of these could be changed even if tag isn't
+				WRITEINT32(put, ss->firsttag);
+				WRITEINT32(put, ss->nexttag);
+			}
 
 			// Special case: save the stats of all modified ffloors along with their ffloor "number"s
 			// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed
@@ -762,12 +765,12 @@ static void P_NetUnArchiveWorld(void)
 			sectors[i].ceilingheight = READFIXED(get);
 		if (diff & SD_FLOORPIC)
 		{
-			sectors[i].floorpic = P_AddLevelFlat((char *)get, levelflats);
+			sectors[i].floorpic = P_AddLevelFlatRuntime((char *)get);
 			get += 8;
 		}
 		if (diff & SD_CEILPIC)
 		{
-			sectors[i].ceilingpic = P_AddLevelFlat((char *)get, levelflats);
+			sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)get);
 			get += 8;
 		}
 		if (diff & SD_LIGHT)
@@ -784,12 +787,11 @@ static void P_NetUnArchiveWorld(void)
 		if (diff2 & SD_CYOFFS)
 			sectors[i].ceiling_yoffs = READFIXED(get);
 		if (diff2 & SD_TAG)
+			sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag
+		if (diff2 & SD_TAGLIST)
 		{
-			INT16 tag;
-			tag = READINT16(get);
 			sectors[i].firsttag = READINT32(get);
 			sectors[i].nexttag = READINT32(get);
-			P_ChangeSectorTag(i, tag);
 		}
 		if (diff2 & SD_FLOORANG)
 			sectors[i].floorpic_angle  = READANGLE(get);
@@ -2628,6 +2630,7 @@ static void P_NetUnArchiveThinkers(void)
 	thinker_t *next;
 	UINT8 tclass;
 	UINT8 restoreNum = false;
+	UINT32 i;
 
 	if (READUINT32(save_p) != ARCHIVEBLOCK_THINKERS)
 		I_Error("Bad $$$.sav at archive block Thinkers");
@@ -2648,6 +2651,12 @@ static void P_NetUnArchiveThinkers(void)
 	iquetail = iquehead = 0;
 	P_InitThinkers();
 
+	// clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity
+	for (i = 0; i < numsectors; i++)
+	{
+		sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = NULL;
+	}
+
 	// read in saved thinkers
 	for (;;)
 	{
@@ -3306,7 +3315,7 @@ void P_SaveNetGame(void)
 {
 	thinker_t *th;
 	mobj_t *mobj;
-	INT32 i = 0;
+	INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise
 
 	CV_SaveNetVars(&save_p);
 	P_NetArchiveMisc();
diff --git a/src/p_setup.c b/src/p_setup.c
index 4daf7a7a7d74d593b66d9dce87e7231a4a81287a..6df1032551dbdcfebfd79fac95847c2883c7b41b 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -160,6 +160,33 @@ FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg)
 	I_Error("Invalid or corrupt map.\nLook in log file or text console for technical details.");
 }
 
+/** Sets a header's flickies to be equivalent to the original Freed Animals
+  *
+  * \param i The header to set flickies for
+  */
+void P_SetDemoFlickies(INT16 i)
+{
+	mapheaderinfo[i]->numFlickies = 5;
+	mapheaderinfo[i]->flickies = Z_Realloc(mapheaderinfo[i]->flickies, 5*sizeof(mobjtype_t), PU_STATIC, NULL);
+	mapheaderinfo[i]->flickies[0] = MT_FLICKY_02/*MT_BUNNY*/;
+	mapheaderinfo[i]->flickies[1] = MT_FLICKY_01/*MT_BIRD*/;
+	mapheaderinfo[i]->flickies[2] = MT_FLICKY_12/*MT_MOUSE*/;
+	mapheaderinfo[i]->flickies[3] = MT_FLICKY_11/*MT_COW*/;
+	mapheaderinfo[i]->flickies[4] = MT_FLICKY_03/*MT_CHICKEN*/;
+}
+
+/** Clears a header's flickies
+  *
+  * \param i The header to clear flickies for
+  */
+void P_DeleteFlickies(INT16 i)
+{
+	if (mapheaderinfo[i]->flickies)
+		Z_Free(mapheaderinfo[i]->flickies);
+	mapheaderinfo[i]->flickies = NULL;
+	mapheaderinfo[i]->numFlickies = 0;
+}
+
 #define NUMLAPS_DEFAULT 4
 
 /** Clears the data from a single map header.
@@ -223,6 +250,12 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
 	mapheaderinfo[num]->levelflags = 0;
 	DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE);
 	mapheaderinfo[num]->menuflags = 0;
+	// Flickies. Nope, no delfile support here either
+#if 1 // equivalent to "FlickyList = DEMO"
+	P_SetDemoFlickies(num);
+#else // equivalent to "FlickyList = NONE"
+	P_DeleteFlickies(num);
+#endif
 	// TODO grades support for delfile (pfft yeah right)
 	P_DeleteGrades(num);
 	// an even further impossibility, delfile custom opts support
@@ -241,6 +274,7 @@ void P_AllocMapHeader(INT16 i)
 	if (!mapheaderinfo[i])
 	{
 		mapheaderinfo[i] = Z_Malloc(sizeof(mapheader_t), PU_STATIC, NULL);
+		mapheaderinfo[i]->flickies = NULL;
 		mapheaderinfo[i]->grades = NULL;
 	}
 	P_ClearSingleMapHeaderInfo(i + 1);
@@ -574,6 +608,69 @@ INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat)
 	return (INT32)i;
 }
 
+// help function for Lua and $$$.sav reading
+// same as P_AddLevelFlat, except this is not setup so we must realloc levelflats to fit in the new flat
+// no longer a static func in lua_maplib.c because p_saveg.c also needs it
+//
+INT32 P_AddLevelFlatRuntime(const char *flatname)
+{
+	size_t i;
+	levelflat_t *levelflat = levelflats;
+
+	//
+	//  first scan through the already found flats
+	//
+	for (i = 0; i < numlevelflats; i++, levelflat++)
+		if (strnicmp(levelflat->name,flatname,8)==0)
+			break;
+
+	// that flat was already found in the level, return the id
+	if (i == numlevelflats)
+	{
+		// allocate new flat memory
+		levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL);
+		levelflat = levelflats+i;
+
+		// store the name
+		strlcpy(levelflat->name, flatname, sizeof (levelflat->name));
+		strupr(levelflat->name);
+
+		// store the flat lump number
+		levelflat->lumpnum = R_GetFlatNumForName(flatname);
+
+#ifndef ZDEBUG
+		CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
+#endif
+
+		numlevelflats++;
+	}
+
+	// level flat id
+	return (INT32)i;
+}
+
+// help function for $$$.sav checking
+// this simply returns the flat # for the name given
+//
+INT32 P_CheckLevelFlat(const char *flatname)
+{
+	size_t i;
+	levelflat_t *levelflat = levelflats;
+
+	//
+	//  scan through the already found flats
+	//
+	for (i = 0; i < numlevelflats; i++, levelflat++)
+		if (strnicmp(levelflat->name,flatname,8)==0)
+			break;
+
+	if (i == numlevelflats)
+		return 0; // ??? flat was not found, this should not happen!
+
+	// level flat id
+	return (INT32)i;
+}
+
 static void P_LoadSectors(lumpnum_t lumpnum)
 {
 	UINT8 *data;
@@ -614,6 +711,7 @@ static void P_LoadSectors(lumpnum_t lumpnum)
 		ss->special = SHORT(ms->special);
 		ss->tag = SHORT(ms->tag);
 		ss->nexttag = ss->firsttag = -1;
+		ss->spawn_nexttag = ss->spawn_firsttag = -1;
 
 		memset(&ss->soundorg, 0, sizeof(ss->soundorg));
 		ss->validcount = 0;
diff --git a/src/p_setup.h b/src/p_setup.h
index 0d735fd71caa8813f6a9c50660efdc753a8c305a..95976d2761587504315cdde6a5dfae3b8da727f9 100644
--- a/src/p_setup.h
+++ b/src/p_setup.h
@@ -47,6 +47,8 @@ typedef struct
 extern size_t numlevelflats;
 extern levelflat_t *levelflats;
 INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat);
+INT32 P_AddLevelFlatRuntime(const char *flatname);
+INT32 P_CheckLevelFlat(const char *flatname);
 
 extern size_t nummapthings;
 extern mapthing_t *mapthings;
@@ -66,6 +68,9 @@ void P_WriteThings(lumpnum_t lump);
 size_t P_PrecacheLevelFlats(void);
 void P_AllocMapHeader(INT16 i);
 
+void P_SetDemoFlickies(INT16 i);
+void P_DeleteFlickies(INT16 i);
+
 // Needed for NiGHTS
 void P_ReloadRings(void);
 void P_DeleteGrades(INT16 i);
diff --git a/src/p_spec.c b/src/p_spec.c
index a8561997bdccdc8f4637f5379c12c7958f06a46b..81f0112654a072b42f846158809cf97619f9a071 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -1522,6 +1522,8 @@ static inline void P_InitTagLists(void)
 		size_t j = (unsigned)sectors[i].tag % numsectors;
 		sectors[i].nexttag = sectors[j].firsttag;
 		sectors[j].firsttag = (INT32)i;
+		sectors[i].spawn_nexttag = sectors[i].nexttag;
+		sectors[j].spawn_firsttag = sectors[j].firsttag;
 	}
 
 	for (i = numlines - 1; i != (size_t)-1; i--)
@@ -3584,7 +3586,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
 				P_PlayerFlagBurst(player, false);
 			break;
 		case 12: // Space Countdown
-			if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ELEMENTAL && !player->powers[pw_spacetime])
+			if (!(player->powers[pw_shield] & SH_PROTECTWATER) && !player->powers[pw_spacetime])
 				player->powers[pw_spacetime] = spacetimetics + 1;
 			break;
 		case 13: // Ramp Sector (Increase step-up/down)
@@ -4785,6 +4787,13 @@ void P_UpdateSpecials(void)
 	}
 }
 
+/** Gets a 3Dfloor by control sector.
+  *
+  * \param sec  Target sector.
+  * \param sec2 Control sector.
+  * \return Pointer to found 3Dfloor, or NULL.
+  * \sa P_GetFFloorByID
+  */
 static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2)
 {
 	ffloor_t *rover;
@@ -4797,6 +4806,26 @@ static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2)
 	return NULL;
 }
 
+/** Gets a 3Dfloor by ID number.
+  *
+  * \param sec Target sector.
+  * \param id  ID of 3Dfloor in target sector. Note that the first FOF's ID is 0.
+  * \return Pointer to found 3Dfloor, or NULL.
+  * \sa P_GetFFloorBySec
+  */
+ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id)
+{
+	ffloor_t *rover;
+	UINT16 i = 0;
+
+	if (!sec->ffloors)
+		return NULL;
+	for (rover = sec->ffloors; rover; rover = rover->next)
+		if (i++ == id)
+			return rover;
+	return NULL;
+}
+
 /** Adds a newly formed 3Dfloor structure to a sector's ffloors list.
   *
   * \param sec    Target sector.
@@ -5377,6 +5406,10 @@ void T_LaserFlash(laserthink_t *flash)
 			&& thing->flags & MF_BOSS)
 			continue; // Don't hurt bosses
 
+		// Don't endlessly kill egg guard shields (or anything else for that matter)
+		if (thing->health <= 0)
+			continue;
+
 		top = P_GetSpecialTopZ(thing, sourcesec, sector);
 		bottom = P_GetSpecialBottomZ(thing, sourcesec, sector);
 
diff --git a/src/p_spec.h b/src/p_spec.h
index c7e7af0b30018885aa5cd59214e3110146af37ee..9a8a5611edaaa6e4e8a1684c2bdd0aacbfe4f38b 100644
--- a/src/p_spec.h
+++ b/src/p_spec.h
@@ -64,6 +64,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
 void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller);
 void P_ChangeSectorTag(UINT32 sector, INT16 newtag);
 
+ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id);
+
 //
 // P_LIGHTS
 //
diff --git a/src/p_user.c b/src/p_user.c
index 5b8523c0c38cc08884bcf909458afbb6945732d5..e47b03e6d22eb8957fe36756ba4d239b056535a7 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -650,7 +650,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
 	if (!(player->pflags & PF_NIGHTSMODE))
 		player->mo->height = P_GetPlayerHeight(player); // Just to make sure jumping into the drone doesn't result in a squashed hitbox.
 
-	player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_THOKKED|PF_SPINNING|PF_DRILLING);
+	player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING);
 	player->homing = 0;
 	player->mo->fuse = 0;
 	player->speed = 0;
@@ -790,58 +790,63 @@ boolean P_PlayerInPain(player_t *player)
 //
 void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
 {
-	angle_t ang;
-	fixed_t fallbackspeed;
+	if (player->powers[pw_carry] == CR_ROPEHANG)
+		P_SetTarget(&player->mo->tracer, NULL);
 
-	if (player->mo->eflags & MFE_VERTICALFLIP)
-		player->mo->z--;
-	else
-		player->mo->z++;
+	{
+		angle_t ang;
+		fixed_t fallbackspeed;
 
-	if (player->mo->eflags & MFE_UNDERWATER)
-		P_SetObjectMomZ(player->mo, FixedDiv(10511*FRACUNIT,2600*FRACUNIT), false);
-	else
-		P_SetObjectMomZ(player->mo, FixedDiv(69*FRACUNIT,10*FRACUNIT), false);
+		P_ResetPlayer(player);
+		P_SetPlayerMobjState(player->mo, player->mo->info->painstate);
 
-	if (inflictor)
-	{
-		ang = R_PointToAngle2(inflictor->x-inflictor->momx, inflictor->y - inflictor->momy, player->mo->x - player->mo->momx, player->mo->y - player->mo->momy);
+		if (player->mo->eflags & MFE_VERTICALFLIP)
+			player->mo->z--;
+		else
+			player->mo->z++;
 
-		// explosion and rail rings send you farther back, making it more difficult
-		// to recover
-		if ((inflictor->flags2 & MF2_SCATTER) && source)
+		if (player->mo->eflags & MFE_UNDERWATER)
+			P_SetObjectMomZ(player->mo, FixedDiv(10511*FRACUNIT,2600*FRACUNIT), false);
+		else
+			P_SetObjectMomZ(player->mo, FixedDiv(69*FRACUNIT,10*FRACUNIT), false);
+
+		if (inflictor)
 		{
-			fixed_t dist = P_AproxDistance(P_AproxDistance(source->x-player->mo->x, source->y-player->mo->y), source->z-player->mo->z);
+			ang = R_PointToAngle2(inflictor->x-inflictor->momx, inflictor->y - inflictor->momy, player->mo->x - player->mo->momx, player->mo->y - player->mo->momy);
 
-			dist = FixedMul(128*FRACUNIT, inflictor->scale) - dist/4;
+			// explosion and rail rings send you farther back, making it more difficult
+			// to recover
+			if ((inflictor->flags2 & MF2_SCATTER) && source)
+			{
+				fixed_t dist = P_AproxDistance(P_AproxDistance(source->x-player->mo->x, source->y-player->mo->y), source->z-player->mo->z);
 
-			if (dist < FixedMul(4*FRACUNIT, inflictor->scale))
-				dist = FixedMul(4*FRACUNIT, inflictor->scale);
+				dist = FixedMul(128*FRACUNIT, inflictor->scale) - dist/4;
 
-			fallbackspeed = dist;
-		}
-		else if (inflictor->flags2 & MF2_EXPLOSION)
-		{
-			if (inflictor->flags2 & MF2_RAILRING)
-				fallbackspeed = FixedMul(38*FRACUNIT, inflictor->scale); // 7x
+				if (dist < FixedMul(4*FRACUNIT, inflictor->scale))
+					dist = FixedMul(4*FRACUNIT, inflictor->scale);
+
+				fallbackspeed = dist;
+			}
+			else if (inflictor->flags2 & MF2_EXPLOSION)
+			{
+				if (inflictor->flags2 & MF2_RAILRING)
+					fallbackspeed = FixedMul(38*FRACUNIT, inflictor->scale); // 7x
+				else
+					fallbackspeed = FixedMul(30*FRACUNIT, inflictor->scale); // 5x
+			}
+			else if (inflictor->flags2 & MF2_RAILRING)
+				fallbackspeed = FixedMul(45*FRACUNIT, inflictor->scale); // 4x
 			else
-				fallbackspeed = FixedMul(30*FRACUNIT, inflictor->scale); // 5x
+				fallbackspeed = FixedMul(4*FRACUNIT, inflictor->scale); // the usual amount of force
 		}
-		else if (inflictor->flags2 & MF2_RAILRING)
-			fallbackspeed = FixedMul(45*FRACUNIT, inflictor->scale); // 4x
 		else
-			fallbackspeed = FixedMul(4*FRACUNIT, inflictor->scale); // the usual amount of force
-	}
-	else
-	{
-		ang = R_PointToAngle2(player->mo->momx, player->mo->momy, 0, 0);
-		fallbackspeed = FixedMul(4*FRACUNIT, player->mo->scale);
-	}
-
-	P_InstaThrust(player->mo, ang, fallbackspeed);
+		{
+			ang = R_PointToAngle2(player->mo->momx, player->mo->momy, 0, 0);
+			fallbackspeed = FixedMul(4*FRACUNIT, player->mo->scale);
+		}
 
-	if (player->powers[pw_carry] == CR_ROPEHANG)
-		P_SetTarget(&player->mo->tracer, NULL);
+		P_InstaThrust(player->mo, ang, fallbackspeed);
+	}
 
 	// Point penalty for hitting a hazard during tag.
 	// Discourages players from intentionally hurting themselves to avoid being tagged.
@@ -853,8 +858,6 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
 			player->score = 0;
 	}
 
-	P_ResetPlayer(player);
-	P_SetPlayerMobjState(player->mo, player->mo->info->painstate);
 	player->powers[pw_flashing] = flashingtics;
 
 	if (player->timeshit != UINT8_MAX)
@@ -867,7 +870,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
 // Useful when you want to kill everything the player is doing.
 void P_ResetPlayer(player_t *player)
 {
-	player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_JUMPED|PF_GLIDING|PF_THOKKED|PF_CANCARRY);
+	player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_JUMPED|PF_FORCEJUMPDAMAGE|PF_GLIDING|PF_THOKKED|PF_CANCARRY|PF_SHIELDABILITY);
 	player->powers[pw_carry] = CR_NONE;
 	player->jumping = 0;
 	player->secondjump = 0;
@@ -1348,24 +1351,38 @@ void P_SpawnShieldOrb(player_t *player)
 		I_Error("P_SpawnShieldOrb: player->mo is NULL!\n");
 #endif
 
+#ifdef HAVE_BLUA
+	if (LUAh_ShieldSpawn(player))
+		return;
+#endif
+
 	if (player->powers[pw_shield] & SH_FORCE)
-		orbtype = MT_BLUEORB;
+		orbtype = MT_FORCE_ORB;
 	else switch (player->powers[pw_shield] & SH_NOSTACK)
 	{
-	case SH_JUMP:
-		orbtype = MT_WHITEORB;
+	case SH_WHIRLWIND:
+		orbtype = MT_WHIRLWIND_ORB;
 		break;
 	case SH_ATTRACT:
-		orbtype = MT_YELLOWORB;
+		orbtype = MT_ATTRACT_ORB;
 		break;
 	case SH_ELEMENTAL:
-		orbtype = MT_GREENORB;
+		orbtype = MT_ELEMENTAL_ORB;
 		break;
-	case SH_BOMB:
-		orbtype = MT_BLACKORB;
+	case SH_ARMAGEDDON:
+		orbtype = MT_ARMAGEDDON_ORB;
 		break;
 	case SH_PITY:
-		orbtype = MT_PITYORB;
+		orbtype = MT_PITY_ORB;
+		break;
+	case SH_FLAMEAURA:
+		orbtype = MT_FLAMEAURA_ORB;
+		break;
+	case SH_BUBBLEWRAP:
+		orbtype = MT_BUBBLEWRAP_ORB;
+		break;
+	case SH_THUNDERCOIN:
+		orbtype = MT_THUNDERCOIN_ORB;
 		break;
 	default:
 		return;
@@ -1384,14 +1401,17 @@ void P_SpawnShieldOrb(player_t *player)
 	}
 
 	shieldobj = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, orbtype);
+	shieldobj->flags2 |= MF2_SHIELD;
 	P_SetTarget(&shieldobj->target, player->mo);
 	shieldobj->color = (UINT8)shieldobj->info->painchance;
+	shieldobj->threshold = (player->powers[pw_shield] & SH_FORCE) ? SH_FORCE : (player->powers[pw_shield] & SH_NOSTACK);
 
 	if (shieldobj->info->seestate)
 	{
 		ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY);
 		P_SetTarget(&ov->target, shieldobj);
 		P_SetMobjState(ov, shieldobj->info->seestate);
+		P_SetTarget(&shieldobj->tracer, ov);
 	}
 	if (shieldobj->info->meleestate)
 	{
@@ -1408,7 +1428,7 @@ void P_SpawnShieldOrb(player_t *player)
 	if (player->powers[pw_shield] & SH_FORCE)
 	{
 		//Copy and pasted from P_ShieldLook in p_mobj.c
-		shieldobj->movecount = (player->powers[pw_shield] & 0xFF);
+		shieldobj->movecount = (player->powers[pw_shield] & SH_FORCEHP);
 		if (shieldobj->movecount < 1)
 		{
 			if (shieldobj->info->painstate)
@@ -1419,6 +1439,51 @@ void P_SpawnShieldOrb(player_t *player)
 	}
 }
 
+//
+// P_SwitchShield
+//
+// Handles the possibility of switching between
+// the non-stack layer of shields thoroughly,
+// then adds the desired one.
+//
+void P_SwitchShield(player_t *player, UINT16 shieldtype)
+{
+	boolean donthavealready = (shieldtype & SH_FORCE)
+	? (!(player->powers[pw_shield] & SH_FORCE) || (player->powers[pw_shield] & SH_FORCEHP) < (shieldtype & ~SH_FORCE))
+	: ((player->powers[pw_shield] & SH_NOSTACK) != shieldtype);
+
+	if (donthavealready)
+	{
+		boolean stopshieldability = (shieldtype & SH_FORCE)
+		? (!(player->powers[pw_shield] & SH_FORCE))
+		: true;
+
+		// Just in case.
+		if (stopshieldability && player->pflags & PF_SHIELDABILITY)
+		{
+			player->pflags &= ~(PF_SPINNING|PF_SHIELDABILITY); // They'll still have PF_THOKKED...
+			player->homing = 0;
+		}
+
+		player->powers[pw_shield] = shieldtype|(player->powers[pw_shield] & SH_STACK);
+		P_SpawnShieldOrb(player);
+
+		if (shieldtype & SH_PROTECTWATER)
+		{
+			if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1)
+				P_RestoreMusic(player);
+
+			player->powers[pw_underwater] = 0;
+
+			if (player->powers[pw_spacetime] > 1)
+			{
+				player->powers[pw_spacetime] = 0;
+				P_RestoreMusic(player);
+			}
+		}
+	}
+}
+
 //
 // P_SpawnGhostMobj
 //
@@ -2120,7 +2185,7 @@ static void P_CheckInvincibilityTimer(player_t *player)
 		{
 			if (mariomode)
 			{
-				if (player->powers[pw_shield] & SH_FIREFLOWER)
+				if ((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER)
 				{
 					player->mo->color = SKINCOLOR_WHITE;
 					G_GhostAddColor(GHC_FIREFLOWER);
@@ -2157,7 +2222,7 @@ static void P_DoBubbleBreath(player_t *player)
 	fixed_t z = player->mo->z;
 	mobj_t *bubble = NULL;
 
-	if (!(player->mo->eflags & MFE_UNDERWATER) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && !(player->pflags & PF_NIGHTSMODE)) || player->spectator)
+	if (!(player->mo->eflags & MFE_UNDERWATER) || ((player->powers[pw_shield] & SH_PROTECTWATER) && !(player->pflags & PF_NIGHTSMODE)) || player->spectator)
 		return;
 
 	if (player->charflags & SF_MACHINE)
@@ -3143,7 +3208,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
 
 	if (cmd->buttons & BT_ATTACK || cmd->buttons & BT_FIRENORMAL)
 	{
-		if (!(player->pflags & PF_ATTACKDOWN) && player->powers[pw_shield] & SH_FIREFLOWER && !player->climbing)
+		if (!(player->pflags & PF_ATTACKDOWN) && (player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER && !player->climbing)
 		{
 			player->pflags |= PF_ATTACKDOWN;
 			P_SpawnPlayerMissile(player->mo, MT_FIREBALL, 0);
@@ -3359,7 +3424,7 @@ static void P_DoSuperStuff(player_t *player)
 			P_SpawnShieldOrb(player);
 
 			// Restore color
-			if (player->powers[pw_shield] & SH_FIREFLOWER)
+			if ((player->powers[pw_shield] & SH_NOSTACK) == SH_FIREFLOWER)
 			{
 				player->mo->color = SKINCOLOR_WHITE;
 				G_GhostAddColor(GHC_FIREFLOWER);
@@ -3406,7 +3471,7 @@ static void P_DoSuperStuff(player_t *player)
 			player->powers[pw_super] = 0;
 
 			// Restore color
-			if (player->powers[pw_shield] & SH_FIREFLOWER)
+			if ((player->powers[pw_shield] & SH_NOSTACK) == SH_FIREFLOWER)
 			{
 				player->mo->color = SKINCOLOR_WHITE;
 				G_GhostAddColor(GHC_FIREFLOWER);
@@ -3666,6 +3731,35 @@ void P_DoJump(player_t *player, boolean soundandstate)
 	}
 }
 
+static void P_DoSpinDashDust(player_t *player)
+{
+	UINT32 i;
+	mobj_t *particle;
+	INT32 prandom[3];
+	for (i = 0; i <= (leveltime%7)/2; i++) { // 1, 2, 3 or 4 particles
+		particle = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_SPINDUST);
+
+		if (player->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) // overrides fire version
+			P_SetMobjState(particle, S_SPINDUST_BUBBLE1);
+		else if (player->powers[pw_shield] == SH_ELEMENTAL)
+			P_SetMobjState(particle, S_SPINDUST_FIRE1);
+
+		P_SetTarget(&particle->target, player->mo);
+		particle->destscale = (2*player->mo->scale)/3;
+		P_SetScale(particle, particle->destscale);
+		if (player->mo->eflags & MFE_VERTICALFLIP) // readjust z position if needed
+			particle->z = player->mo->z + player->mo->height - particle->height;
+		prandom[0] = P_RandomFixed()<<2; // P_RandomByte()<<10
+		prandom[1] = P_RandomRange(-30, 30); // P_RandomRange(-ANG30/FRACUNIT, ANG30/FRACUNIT)*FRACUNIT
+		prandom[2] = P_RandomFixed()<<3; // P_RandomByte()<<11
+		P_SetObjectMomZ(particle, player->dashspeed/50 + prandom[0], false);
+		P_InstaThrust(particle,
+				player->mo->angle + (prandom[1]*ANG1),
+				-FixedMul(player->dashspeed/12 + FRACUNIT + prandom[2], player->mo->scale));
+		P_TryMove(particle, particle->x+particle->momx, particle->y+particle->momy, true);
+	}
+}
+
 //
 // P_DoSpinAbility
 //
@@ -3673,6 +3767,7 @@ void P_DoJump(player_t *player, boolean soundandstate)
 //
 static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
 {
+	boolean canstand = true; // can we stand on the ground? (mostly relevant for slopes)
 	if (player->pflags & PF_STASIS)
 		return;
 
@@ -3684,69 +3779,92 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
 	}
 #endif
 
-	// Spinning and Spindashing
-	if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_SLIDING) && !player->exiting
-		&& !P_PlayerInPain(player)) // subsequent revs
-	{
-		if ((cmd->buttons & BT_USE) && player->speed < FixedMul(5<<FRACBITS, player->mo->scale) && !player->mo->momz && onground && !(player->pflags & PF_USEDOWN) && !(player->pflags & PF_SPINNING)
 #ifdef ESLOPE
-			&& (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2)
+	canstand = (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2);
 #endif
-			)
-		{
-			player->mo->momx = player->cmomx;
-			player->mo->momy = player->cmomy;
-			player->pflags |= PF_STARTDASH|PF_SPINNING;
-			player->dashspeed = player->mindash;
-			P_SetPlayerMobjState(player->mo, S_PLAY_DASH);
-			player->pflags |= PF_USEDOWN;
-			if (!player->spectator)
-				S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh.
-		}
-		else if ((cmd->buttons & BT_USE) && (player->pflags & PF_STARTDASH))
+
+	///////////////////////////////
+	// ability-specific behavior //
+	///////////////////////////////
+	if (!(player->pflags & PF_SLIDING) && !player->exiting && !P_PlayerInPain(player))
+	{
+		switch (player->charability2)
 		{
-			if (player->dashspeed < player->maxdash)
-			{
+			case CA2_SPINDASH: // Spinning and Spindashing
+				 // Start revving
+				if ((cmd->buttons & BT_USE) && player->speed < FixedMul(5<<FRACBITS, player->mo->scale)
+					&& !player->mo->momz && onground && !(player->pflags & (PF_USEDOWN|PF_SPINNING))
+						&& canstand)
+				{
+					player->mo->momx = player->cmomx;
+					player->mo->momy = player->cmomy;
+					player->pflags |= PF_STARTDASH|PF_SPINNING;
+					player->dashspeed = player->mindash;
+					P_SetPlayerMobjState(player->mo, S_PLAY_DASH);
+					player->pflags |= PF_USEDOWN;
+					if (!player->spectator)
+						S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh.
+				}
+				 // Revving
+				else if ((cmd->buttons & BT_USE) && (player->pflags & PF_STARTDASH))
+				{
+					if (player->dashspeed < player->maxdash)
+					{
 #define chargecalculation (6*(player->dashspeed - player->mindash))/(player->maxdash - player->mindash)
-				fixed_t soundcalculation = chargecalculation;
-				player->dashspeed += FRACUNIT;
-				if (!player->spectator && soundcalculation != chargecalculation)
-					S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh.
+						fixed_t soundcalculation = chargecalculation;
+						player->dashspeed += FRACUNIT;
+						if (!player->spectator && soundcalculation != chargecalculation)
+							S_StartSound(player->mo, sfx_s3kab); // Make the rev sound! Previously sfx_spndsh.
 #undef chargecalculation
-			}
-			if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle.
-			{
-				P_SpawnSpinMobj(player, player->revitem);
-				if (demorecording)
-					G_GhostAddRev();
-			}
-		}
+					}
+					if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle.
+					{
+						P_SpawnSpinMobj(player, player->revitem);
+						if (demorecording)
+							G_GhostAddRev();
+					}
+				}
 
-		// If not moving up or down, and travelling faster than a speed of four while not holding
-		// down the spin button and not spinning.
-		// AKA Just go into a spin on the ground, you idiot. ;)
-		else if ((cmd->buttons & BT_USE || ((twodlevel || (player->mo->flags2 & MF2_TWOD)) && cmd->forwardmove < -20))
-			&& !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<<FRACBITS, player->mo->scale)
-#ifdef ESLOPE
-			|| (player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)
-#endif
-			) && !(player->pflags & PF_USEDOWN) && !(player->pflags & PF_SPINNING))
-		{
-			player->pflags |= PF_SPINNING;
-			P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
-			if (!player->spectator)
-				S_StartSound(player->mo, sfx_spin);
-			player->pflags |= PF_USEDOWN;
+				// If not moving up or down, and travelling faster than a speed of four while not holding
+				// down the spin button and not spinning.
+				// AKA Just go into a spin on the ground, you idiot. ;)
+				else if ((cmd->buttons & BT_USE || ((twodlevel || (player->mo->flags2 & MF2_TWOD)) && cmd->forwardmove < -20))
+					&& !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<<FRACBITS, player->mo->scale)
+						|| !canstand) && !(player->pflags & (PF_USEDOWN|PF_SPINNING)))
+				{
+					player->pflags |= PF_SPINNING;
+					P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+					if (!player->spectator)
+						S_StartSound(player->mo, sfx_spin);
+					player->pflags |= PF_USEDOWN;
+				}
+				break;
+			case CA2_MELEE: // Melee attack
+				if (!(player->panim == PA_ABILITY2) && (cmd->buttons & BT_USE) && player->speed < FixedMul(10<<FRACBITS, player->mo->scale)
+				&& !player->mo->momz && onground && !(player->pflags & PF_USEDOWN)
+				&& canstand)
+				{
+					P_ResetPlayer(player);
+					player->mo->z += P_MobjFlip(player->mo);
+					player->mo->momx = player->cmomx = 0;
+					player->mo->momy = player->cmomy = 0;
+					P_SetObjectMomZ(player->mo, player->mindash, false);
+					P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->maxdash, player->mo->scale));
+					P_SetPlayerMobjState(player->mo, S_PLAY_MELEE);
+					player->pflags |= PF_USEDOWN;
+					S_StartSound(player->mo, sfx_s3k8b);
+				}
+				break;
 		}
 	}
 
+	///////////////////////////////
+	// general spinning behavior //
+	///////////////////////////////
+
 	// Rolling normally
 	if (onground && player->pflags & PF_SPINNING && !(player->pflags & PF_STARTDASH)
-		&& player->speed < FixedMul(5*FRACUNIT,player->mo->scale)
-#ifdef ESLOPE
-			&& (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2)
-#endif
-			)
+		&& player->speed < FixedMul(5*FRACUNIT,player->mo->scale) && canstand)
 	{
 		if (GETSECSPECIAL(player->mo->subsector->sector->special, 4) == 7 || (player->mo->ceilingz - player->mo->floorz < P_GetPlayerHeight(player)))
 			P_InstaThrust(player->mo, player->mo->angle, FixedMul(10*FRACUNIT, player->mo->scale));
@@ -3791,29 +3909,12 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
 	{
 		if (player->mo->state-states != S_PLAY_DASH)
 			P_SetPlayerMobjState(player->mo, S_PLAY_DASH);
+		// Spawn spin dash dust
+		if (!(player->charflags & SF_NOSPINDASHDUST) && !(player->mo->eflags & MFE_GOOWATER))
+			P_DoSpinDashDust(player);
 	}
 	else if (onground && player->pflags & PF_SPINNING && !(player->panim == PA_ROLL))
 		P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
-
-	// Melee attack
-	if ((player->charability2 == CA2_MELEE) && !(player->panim == PA_ABILITY2) && !player->exiting
-		&& !P_PlayerInPain(player) && (cmd->buttons & BT_USE) && player->speed < FixedMul(10<<FRACBITS, player->mo->scale)
-		&& !player->mo->momz && onground && !(player->pflags & PF_USEDOWN)
-#ifdef ESLOPE
-		&& (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2)
-#endif
-		)
-	{
-		P_ResetPlayer(player);
-		player->mo->z += P_MobjFlip(player->mo);
-		player->mo->momx = player->cmomx = 0;
-		player->mo->momy = player->cmomy = 0;
-		P_SetObjectMomZ(player->mo, player->mindash, false);
-		P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->maxdash, player->mo->scale));
-		P_SetPlayerMobjState(player->mo, S_PLAY_MELEE);
-		player->pflags |= PF_USEDOWN;
-		S_StartSound(player->mo, sfx_s3k8b);
-	}
 }
 
 //
@@ -3823,18 +3924,59 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
 //
 void P_DoJumpShield(player_t *player)
 {
+	boolean electric = ((player->powers[pw_shield] & SH_PROTECTELECTRIC) == SH_PROTECTELECTRIC);
+
 	if (player->pflags & PF_THOKKED)
 		return;
 
 	player->pflags &= ~PF_JUMPED;
 	P_DoJump(player, false);
-	player->pflags &= ~PF_JUMPED;
-	player->secondjump = 0;
 	player->jumping = 0;
-	player->pflags |= PF_THOKKED;
+	player->secondjump = 0;
+	player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
 	player->pflags &= ~PF_SPINNING;
-	P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
-	S_StartSound(player->mo, sfx_wdjump);
+	if (electric)
+	{
+		mobj_t *spark;
+		INT32 i;
+#define numangles 6
+#define limitangle (360/numangles)
+		angle_t travelangle = player->mo->angle + P_RandomRange(-limitangle, limitangle)*ANG1;
+		for (i = 0; i < numangles; i++)
+		{
+			spark = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_THUNDERCOIN_SPARK);
+			P_InstaThrust(spark, travelangle + i*(ANGLE_MAX/numangles), FixedMul(4*FRACUNIT, spark->scale));
+			if (i % 2)
+				P_SetObjectMomZ(spark, -4*FRACUNIT, false);
+		}
+#undef limitangle
+#undef numangles
+		S_StartSound(player->mo, sfx_s3k45);
+	}
+	else
+	{
+		player->pflags &= ~PF_JUMPED;
+		P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
+		S_StartSound(player->mo, sfx_wdjump);
+	}
+}
+
+//
+// P_DoBubbleBounce
+//
+// Bubblewrap shield landing handling
+//
+void P_DoBubbleBounce(player_t *player)
+{
+	player->pflags &= ~(PF_JUMPED|PF_SHIELDABILITY);
+	S_StartSound(player->mo, sfx_s3k44);
+	P_DoJump(player, false);
+	if (player->charflags & SF_NOJUMPSPIN)
+		P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
+	player->pflags |= PF_THOKKED;
+	player->jumping = 0;
+	player->secondjump = UINT8_MAX;
+	player->mo->momz = FixedMul(player->mo->momz, 5*FRACUNIT/4);
 }
 
 //
@@ -3905,6 +4047,10 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 		{}
 		else if (onground || player->climbing || (player->mo->tracer && player->powers[pw_carry]))
 		{}
+		else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND
+		&& !(player->pflags & PF_JUMPED)
+		&& !(player->pflags & PF_USEDOWN))
+			P_DoJumpShield(player);
 		else if (!(player->pflags & PF_SLIDING) && ((gametype != GT_CTF) || (!player->gotflag)))
 		{
 #ifdef HAVE_BLUA
@@ -4047,7 +4193,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 
 						if (player->charability == CA_HOMINGTHOK && !player->homing)
 						{
-							if (P_LookForEnemies(player))
+							if (P_LookForEnemies(player, true))
 							{
 								if (player->mo->tracer)
 									player->homing = 3*TICRATE;
@@ -4175,7 +4321,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
 					break;
 			}
 		}
-		else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_JUMP && !player->powers[pw_super])
+		else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_WHIRLWIND && !player->powers[pw_super])
 			P_DoJumpShield(player);
 	}
 
@@ -5497,11 +5643,13 @@ static void P_DoNiGHTSCapsule(player_t *player)
 				}
 				else
 				{
-					fixed_t z;
-
-					z = player->capsule->z + player->capsule->height/2;
 					for (i = 0; i < 16; i++)
-						P_SpawnMobj(player->capsule->x, player->capsule->y, z, MT_BIRD);
+					{
+						mobj_t *flicky = P_InternalFlickySpawn(player->capsule, 0, ((i%4) + 1)*2*FRACUNIT, true);
+						flicky->z += player->capsule->height/2;
+						flicky->angle = (i*(ANGLE_MAX/16));
+						P_InstaThrust(flicky, flicky->angle, 8*FRACUNIT);
+					}
 				}
 				for (i = 0; i < MAXPLAYERS; i++)
 					if (playeringame[i] && players[i].mare == player->mare)
@@ -6146,7 +6294,7 @@ void P_BlackOw(player_t *player)
 	player->powers[pw_shield] = player->powers[pw_shield] & SH_STACK;
 }
 
-void P_ElementalFireTrail(player_t *player)
+void P_ElementalFire(player_t *player, boolean cropcircle)
 {
 	fixed_t newx;
 	fixed_t newy;
@@ -6164,40 +6312,65 @@ void P_ElementalFireTrail(player_t *player)
 	else
 		ground = player->mo->floorz;
 
-	travelangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
-
-	for (i = 0; i < 2; i++)
+	if (cropcircle)
 	{
-		newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(24*FRACUNIT, player->mo->scale));
-		newy = player->mo->y + P_ReturnThrustY(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(24*FRACUNIT, player->mo->scale));
-#ifdef ESLOPE
-		if (player->mo->standingslope)
+#define numangles 8
+#define limitangle (180/numangles)
+		travelangle = player->mo->angle + P_RandomRange(-limitangle, limitangle)*ANG1;
+		for (i = 0; i < numangles; i++)
 		{
-			ground = P_GetZAt(player->mo->standingslope, newx, newy);
-			if (player->mo->eflags & MFE_VERTICALFLIP)
-				ground -= FixedMul(mobjinfo[MT_SPINFIRE].height, player->mo->scale);
+			flame = P_SpawnMobj(player->mo->x, player->mo->y, ground, MT_SPINFIRE);
+			flame->flags &= ~MF_NOGRAVITY;
+			P_SetTarget(&flame->target, player->mo);
+			flame->angle = travelangle + i*(ANGLE_MAX/numangles);
+			flame->fuse = TICRATE*7; // takes about an extra second to hit the ground
+			flame->destscale = player->mo->scale;
+			P_SetScale(flame, player->mo->scale);
+			flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP);
+			P_InstaThrust(flame, flame->angle, FixedMul(3*FRACUNIT, flame->scale));
+			P_SetObjectMomZ(flame, 3*FRACUNIT, false);
 		}
+#undef limitangle
+#undef numangles
+	}
+	else
+	{
+		travelangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
+		for (i = 0; i < 2; i++)
+		{
+
+			newx = player->mo->x + P_ReturnThrustX(player->mo, (travelangle + ((i&1) ? -1 : 1)*ANGLE_135), FixedMul(24*FRACUNIT, player->mo->scale));
+			newy = player->mo->y + P_ReturnThrustY(player->mo, (travelangle + ((i&1) ? -1 : 1)*ANGLE_135), FixedMul(24*FRACUNIT, player->mo->scale));
+
+#ifdef ESLOPE
+			if (player->mo->standingslope)
+			{
+				ground = P_GetZAt(player->mo->standingslope, newx, newy);
+				if (player->mo->eflags & MFE_VERTICALFLIP)
+					ground -= FixedMul(mobjinfo[MT_SPINFIRE].height, player->mo->scale);
+			}
 #endif
-		flame = P_SpawnMobj(newx, newy, ground, MT_SPINFIRE);
-		P_SetTarget(&flame->target, player->mo);
-		flame->angle = travelangle;
-		flame->fuse = TICRATE*6;
-		flame->destscale = player->mo->scale;
-		P_SetScale(flame, player->mo->scale);
-		flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP);
-
-		flame->momx = 8;
-		P_XYMovement(flame);
-		if (P_MobjWasRemoved(flame))
-			continue;
+			flame = P_SpawnMobj(newx, newy, ground, MT_SPINFIRE);
+			P_SetTarget(&flame->target, player->mo);
+			flame->angle = travelangle;
+			flame->fuse = TICRATE*6;
+			flame->destscale = player->mo->scale;
+			P_SetScale(flame, player->mo->scale);
+			flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP);
+
+			flame->momx = 8; // this is a hack which is used to ensure it still behaves as a missile and can damage others
+			P_XYMovement(flame);
+			if (P_MobjWasRemoved(flame))
+				continue;
 
-		if (player->mo->eflags & MFE_VERTICALFLIP)
-		{
-			if (flame->z + flame->height < flame->ceilingz)
+			if (player->mo->eflags & MFE_VERTICALFLIP)
+			{
+				if (flame->z + flame->height < flame->ceilingz)
+					P_RemoveMobj(flame);
+			}
+			else if (flame->z > flame->floorz)
 				P_RemoveMobj(flame);
 		}
-		else if (flame->z > flame->floorz)
-			P_RemoveMobj(flame);
 	}
 }
 
@@ -6494,7 +6667,7 @@ static void P_MovePlayer(player_t *player)
 			P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
 	}
 
-	// If Springing (or nojumpspinning), but travelling DOWNWARD, change back! (nojumpspin also turns to fall once PF_THOKKED is added.)
+	// If Springing (or nojumpspinning), but travelling DOWNWARD, change back!
 	if ((player->panim == PA_SPRING && P_MobjFlip(player->mo)*player->mo->momz < 0)
 		|| ((((player->charflags & SF_NOJUMPSPIN) && (player->pflags & PF_JUMPED) && player->panim == PA_JUMP))
 			&& (P_MobjFlip(player->mo)*player->mo->momz < 0)))
@@ -6751,7 +6924,7 @@ static void P_MovePlayer(player_t *player)
 	if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL
 	&& (player->pflags & PF_SPINNING) && player->speed > FixedMul(4<<FRACBITS, player->mo->scale) && onground && (leveltime & 1)
 	&& !(player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)))
-		P_ElementalFireTrail(player);
+		P_ElementalFire(player, false);
 
 	P_DoSpinAbility(player, cmd);
 
@@ -6819,51 +6992,121 @@ static void P_MovePlayer(player_t *player)
 			localangle2 = player->mo->angle;
 	}
 
-	///////////////////////////
-	//BOMB SHIELD ACTIVATION,//
-	//HOMING, AND OTHER COOL //
-	//STUFF!                 //
-	///////////////////////////
+	//////////////////
+	//SHIELD ACTIVES//
+	//& SUPER FLOAT!//
+	//////////////////
 
-	if (cmd->buttons & BT_USE) // Spin button effects
+	if (player->pflags & PF_JUMPED && !player->exiting && player->mo->health)
 	{
-		if (player->pflags & PF_JUMPED) // If the player is jumping
+		if (cmd->buttons & BT_USE) // Spin button effects
 		{
-			if (!(player->pflags & PF_USEDOWN)) // If the player is not holding down BT_USE
+			if (player->powers[pw_super]) // Super can't use shield actives, only passives
 			{
-				// Jump shield activation
-				if (!P_PlayerInPain(player) // If the player is not in pain
-				&& !player->climbing // If the player is not climbing
-				&& !(player->pflags & (PF_GLIDING|PF_SLIDING|PF_THOKKED)) // If the player is not gliding or sliding and hasn't used their ability
-				&& !onground) // If the player isn't on the ground
-				{
-					if ((player->powers[pw_shield] & SH_NOSTACK) == SH_JUMP && !player->powers[pw_super])
-						P_DoJumpShield(player);
-				}
-				// Bomb shield activation
-				if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB)
+				if ((player->charability == CA_THOK) // Super Sonic float
+				&& (player->speed > 5*player->mo->scale) // FixedMul(5<<FRACBITS, player->mo->scale), but scale is FRACUNIT-based
+				&& (P_MobjFlip(player->mo)*player->mo->momz <= 0))
 				{
-					// Don't let Super Sonic or invincibility use it
-					if (!(player->powers[pw_super] || player->powers[pw_invulnerability]))
-						P_BlackOw(player);
+					if (player->panim == PA_PAIN || player->panim == PA_JUMP || player->panim == PA_FALL
+					|| (player->panim == PA_WALK && player->mo->state-states != S_PLAY_SUPER_FLOAT))
+						P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_FLOAT);
+
+					player->mo->momz = 0;
+					player->pflags &= ~PF_SPINNING;
+					player->jumping = 0; // don't cut jump height after bouncing off something
 				}
 			}
-			// Super Sonic move
-			if (player->skin == 0 && player->powers[pw_super] && player->speed > FixedMul(5<<FRACBITS, player->mo->scale)
-			&& P_MobjFlip(player->mo)*player->mo->momz <= 0)
+			else
+#ifdef HAVE_BLUA
+			if (!LUAh_ShieldSpecial(player))
+#endif
 			{
-				if (player->panim == PA_ROLL || player->panim == PA_JUMP || player->mo->state-states == S_PLAY_PAIN || player->panim == PA_WALK)
-					P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_FLOAT);
-
-				player->mo->momz = 0;
-				player->pflags &= ~PF_SPINNING;
-				player->jumping = 0; // don't cut jump height after bouncing off something
+				if (!(player->pflags & (PF_USEDOWN|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player is not holding down BT_USE, or having used an ability previously
+					&& (!(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped
+				{
+					// Force shield activation
+					if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE)
+					{
+						player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
+						player->mo->momx = player->mo->momy = player->mo->momz = 0;
+						S_StartSound(player->mo, sfx_ngskid);
+					}
+					else
+					{
+						switch (player->powers[pw_shield] & SH_NOSTACK)
+						{
+							// Whirlwind/Thundercoin shield activation
+							case SH_WHIRLWIND:
+							case SH_THUNDERCOIN:
+								P_DoJumpShield(player);
+								break;
+							// Armageddon shield activation
+							case SH_ARMAGEDDON:
+								player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
+								P_BlackOw(player);
+								break;
+							// Attract shield activation
+							case SH_ATTRACT:
+								player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
+								player->homing = 2;
+								if (P_LookForEnemies(player, false) && player->mo->tracer)
+								{
+									player->pflags |= PF_FORCEJUMPDAMAGE;
+									P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+									S_StartSound(player->mo, sfx_s3k40);
+									player->homing = 3*TICRATE;
+								}
+								else
+									S_StartSound(player->mo, sfx_s3ka6);
+								break;
+							// Elemental/Bubblewrap shield activation
+							case SH_ELEMENTAL:
+							case SH_BUBBLEWRAP:
+								player->pflags |= PF_FORCEJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY;
+								P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+								player->secondjump = 0;
+								player->mo->momx = player->mo->momy = 0;
+								P_SetObjectMomZ(player->mo, -24*FRACUNIT, false);
+								S_StartSound(player->mo,
+									((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)
+									? sfx_s3k43
+									: sfx_s3k44);
+								break;
+							// Flame shield activation
+							case SH_FLAMEAURA:
+								player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
+								P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale));
+								S_StartSound(player->mo, sfx_s3k43);
+							default:
+								break;
+						}
+					}
+				}
 			}
 		}
 	}
 
 	// HOMING option.
-	if (player->charability == CA_HOMINGTHOK)
+	if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT // Sonic 3D Blast.
+	&& player->pflags & PF_SHIELDABILITY)
+	{
+		if (player->homing && player->mo->tracer)
+		{
+			P_HomingAttack(player->mo, player->mo->tracer);
+			if (player->mo->tracer->health <= 0 || (player->mo->tracer->flags2 & MF2_FRET))
+			{
+				P_SetObjectMomZ(player->mo, 6*FRACUNIT, false);
+				if (player->mo->eflags & MFE_UNDERWATER)
+					player->mo->momz = FixedMul(player->mo->momz, FRACUNIT/3);
+				player->homing = 0;
+			}
+		}
+
+		// If you're not jumping, then you obviously wouldn't be homing.
+		if (!(player->pflags & PF_JUMPED))
+			player->homing = 0;
+	}
+	else if (player->charability == CA_HOMINGTHOK) // Sonic Adventure.
 	{
 		// If you've got a target, chase after it!
 		if (player->homing && player->mo->tracer)
@@ -7166,13 +7409,6 @@ static void P_DoZoomTube(player_t *player)
 			P_SetTarget(&player->mo->tracer, waypoint);
 
 			// calculate MOMX/MOMY/MOMZ for next waypoint
-			// change angle
-			player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y);
-
-			if (player == &players[consoleplayer])
-				localangle = player->mo->angle;
-			else if (player == &players[secondarydisplayplayer])
-				localangle2 = player->mo->angle;
 
 			// change slope
 			dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - player->mo->z);
@@ -7192,6 +7428,17 @@ static void P_DoZoomTube(player_t *player)
 			CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found, releasing from track...\n");
 		}
 	}
+
+	// change angle
+	if (player->mo->tracer)
+	{
+		player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y);
+
+		if (player == &players[consoleplayer])
+			localangle = player->mo->angle;
+		else if (player == &players[secondarydisplayplayer])
+			localangle2 = player->mo->angle;
+	}
 }
 
 //
@@ -7447,9 +7694,9 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
 //
 // P_LookForEnemies
 // Looks for something you can hit - Used for homing attack
-// Includes monitors and springs!
+// If nonenemies is true, includes monitors and springs!
 //
-boolean P_LookForEnemies(player_t *player)
+boolean P_LookForEnemies(player_t *player, boolean nonenemies)
 {
 	mobj_t *mo;
 	thinker_t *think;
@@ -7462,7 +7709,8 @@ boolean P_LookForEnemies(player_t *player)
 			continue; // not a mobj thinker
 
 		mo = (mobj_t *)think;
-		if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING)))
+		if ((nonenemies && !(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING)))
+		|| (!nonenemies && !(mo->flags & (MF_ENEMY|MF_BOSS))))
 			continue; // not a valid enemy
 
 		if (mo->health <= 0) // dead
@@ -7560,7 +7808,12 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target
 			ns = FixedMul(source->info->speed, source->scale);
 	}
 	else if (source->player)
-		ns = FixedDiv(FixedMul(source->player->actionspd, source->scale), 3*FRACUNIT/2);
+	{
+		if (source->player->charability == CA_HOMINGTHOK && !(source->player->pflags & PF_SHIELDABILITY))
+			ns = FixedDiv(FixedMul(source->player->actionspd, source->scale), 3*FRACUNIT/2);
+		else
+			ns = FixedMul(45*FRACUNIT, source->scale);
+	}
 
 	source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns);
 	source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns);
@@ -8674,8 +8927,13 @@ void P_PlayerThink(player_t *player)
 		if (player->panim != PA_ABILITY)
 			P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE);
 	}
-	else if ((player->pflags & PF_JUMPED) && !player->powers[pw_super] && player->panim != PA_JUMP && !(player->charflags & SF_NOJUMPSPIN))
-		P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
+	else if ((player->pflags & PF_JUMPED) && !player->powers[pw_super] && ((player->charflags & SF_NOJUMPSPIN && player->pflags & PF_FORCEJUMPDAMAGE && player->panim != PA_ROLL) || (!(player->charflags & SF_NOJUMPSPIN) && player->panim != PA_JUMP)))
+	{
+		if (!(player->charflags & SF_NOJUMPSPIN))
+			P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
+		else if (player->pflags & PF_FORCEJUMPDAMAGE)
+			P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+	}
 
 	if (player->flashcount)
 		player->flashcount--;
@@ -8994,7 +9252,7 @@ void P_PlayerThink(player_t *player)
 	if (player->powers[pw_tailsfly] && player->powers[pw_tailsfly] < UINT16_MAX && player->charability != CA_SWIM) // tails fly counter
 		player->powers[pw_tailsfly]--;
 
-	if (player->powers[pw_underwater] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL))
+	if (player->powers[pw_underwater] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_PROTECTWATER)))
 	{
 		if (player->powers[pw_underwater] <= 12*TICRATE+1)
 			P_RestoreMusic(player); //incase they were about to drown
@@ -9004,7 +9262,7 @@ void P_PlayerThink(player_t *player)
 	else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer
 		player->powers[pw_underwater]--;
 
-	if (player->powers[pw_spacetime] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL))
+	if (player->powers[pw_spacetime] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_PROTECTWATER)))
 		player->powers[pw_spacetime] = 0;
 	else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer
 		player->powers[pw_spacetime]--;
@@ -9419,7 +9677,7 @@ void P_PlayerAfterThink(player_t *player)
 		player->mo->momy = (player->mo->tracer->y - player->mo->y)*2;
 		player->mo->momz = (player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2) - player->mo->z)*2;
 		P_TeleportMove(player->mo, player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2));
-		player->pflags |= PF_JUMPED;
+		player->pflags |= PF_JUMPED|PF_FORCEJUMPDAMAGE;
 		player->secondjump = 0;
 		player->pflags &= ~PF_THOKKED;
 
diff --git a/src/r_bsp.c b/src/r_bsp.c
index 69aa7be2902770ecb89a1c8b683a6039fae9b5e4..2562cff666217e75e5c43be0acf065c6dbc20980 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -859,6 +859,7 @@ static void R_Subsector(size_t num)
 	static sector_t tempsec; // Deep water hack
 	extracolormap_t *floorcolormap;
 	extracolormap_t *ceilingcolormap;
+	fixed_t floorcenterz, ceilingcenterz;
 
 #ifdef RANGECHECK
 	if (num >= numsubsectors)
@@ -879,6 +880,18 @@ static void R_Subsector(size_t num)
 
 	floorcolormap = ceilingcolormap = frontsector->extra_colormap;
 
+	floorcenterz =
+#ifdef ESLOPE
+		frontsector->f_slope ? P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
+#endif
+		frontsector->floorheight;
+
+	ceilingcenterz =
+#ifdef ESLOPE
+		frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
+#endif
+		frontsector->ceilingheight;
+
 	// Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps.
 	if (frontsector->ffloors)
 	{
@@ -891,19 +904,11 @@ static void R_Subsector(size_t num)
 			sub->sector->moved = frontsector->moved = false;
 		}
 
-		light = R_GetPlaneLight(frontsector,
-#ifdef ESLOPE
-								frontsector->f_slope ? P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
-#endif
-								frontsector->floorheight, false);
+		light = R_GetPlaneLight(frontsector, floorcenterz, false);
 		if (frontsector->floorlightsec == -1)
 			floorlightlevel = *frontsector->lightlist[light].lightlevel;
 		floorcolormap = frontsector->lightlist[light].extra_colormap;
-		light = R_GetPlaneLight(frontsector,
-#ifdef ESLOPE
-								frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
-#endif
-								frontsector->ceilingheight, false);
+		light = R_GetPlaneLight(frontsector, ceilingcenterz, false);
 		if (frontsector->ceilinglightsec == -1)
 			ceilinglightlevel = *frontsector->lightlist[light].lightlevel;
 		ceilingcolormap = frontsector->lightlist[light].extra_colormap;
@@ -920,6 +925,9 @@ static void R_Subsector(size_t num)
 	{
 		floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel,
 			frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL
+#ifdef POLYOBJECTS_PLANES
+			, NULL
+#endif
 #ifdef ESLOPE
 			, frontsector->f_slope
 #endif
@@ -939,6 +947,9 @@ static void R_Subsector(size_t num)
 		ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic,
 			ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle,
 			ceilingcolormap, NULL
+#ifdef POLYOBJECTS_PLANES
+			, NULL
+#endif
 #ifdef ESLOPE
 			, frontsector->c_slope
 #endif
@@ -956,7 +967,7 @@ static void R_Subsector(size_t num)
 	if (frontsector->ffloors)
 	{
 		ffloor_t *rover;
-		fixed_t heightcheck, planecenterz, floorcenterz, ceilingcenterz;
+		fixed_t heightcheck, planecenterz;
 
 		for (rover = frontsector->ffloors; rover && numffloors < MAXFFLOORS; rover = rover->next)
 		{
@@ -975,18 +986,6 @@ static void R_Subsector(size_t num)
 			ffloor[numffloors].plane = NULL;
 			ffloor[numffloors].polyobj = NULL;
 
-			floorcenterz =
-#ifdef ESLOPE
-				frontsector->f_slope ? P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
-#endif
-				frontsector->floorheight;
-
-			ceilingcenterz =
-#ifdef ESLOPE
-				frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
-#endif
-				frontsector->ceilingheight;
-
 			heightcheck =
 #ifdef ESLOPE
 				*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) :
@@ -1009,6 +1008,9 @@ static void R_Subsector(size_t num)
 				ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic,
 					*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs,
 					*rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover
+#ifdef POLYOBJECTS_PLANES
+					, NULL
+#endif
 #ifdef ESLOPE
 					, *rover->b_slope
 #endif
@@ -1052,6 +1054,9 @@ static void R_Subsector(size_t num)
 				ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic,
 					*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle,
 					frontsector->lightlist[light].extra_colormap, rover
+#ifdef POLYOBJECTS_PLANES
+					, NULL
+#endif
 #ifdef ESLOPE
 					, *rover->t_slope
 #endif
@@ -1093,8 +1098,8 @@ static void R_Subsector(size_t num)
 			polysec = po->lines[0]->backsector;
 			ffloor[numffloors].plane = NULL;
 
-			if (polysec->floorheight <= frontsector->ceilingheight
-				&& polysec->floorheight >= frontsector->floorheight
+			if (polysec->floorheight <= ceilingcenterz
+				&& polysec->floorheight >= floorcenterz
 				&& (viewz < polysec->floorheight))
 			{
 				fixed_t xoff, yoff;
@@ -1118,11 +1123,13 @@ static void R_Subsector(size_t num)
 						polysec->floorpic_angle-po->angle,
 						NULL,
 						NULL
+#ifdef POLYOBJECTS_PLANES
+					, po
+#endif
 #ifdef ESLOPE
 					, NULL // will ffloors be slopable eventually?
 #endif
 					);
-				//ffloor[numffloors].plane->polyobj = po;
 
 				ffloor[numffloors].height = polysec->floorheight;
 				ffloor[numffloors].polyobj = po;
@@ -1139,8 +1146,8 @@ static void R_Subsector(size_t num)
 
 			ffloor[numffloors].plane = NULL;
 
-			if (polysec->ceilingheight >= frontsector->floorheight
-				&& polysec->ceilingheight <= frontsector->ceilingheight
+			if (polysec->ceilingheight >= floorcenterz
+				&& polysec->ceilingheight <= ceilingcenterz
 				&& (viewz > polysec->ceilingheight))
 			{
 				fixed_t xoff, yoff;
@@ -1162,11 +1169,13 @@ static void R_Subsector(size_t num)
 				ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
 					polysec->lightlevel, xoff, yoff, polysec->ceilingpic_angle-po->angle,
 					NULL, NULL
+#ifdef POLYOBJECTS_PLANES
+					, po
+#endif
 #ifdef ESLOPE
 					, NULL // will ffloors be slopable eventually?
 #endif
 					);
-				//ffloor[numffloors].plane->polyobj = po;
 
 				ffloor[numffloors].polyobj = po;
 				ffloor[numffloors].height = polysec->ceilingheight;
diff --git a/src/r_data.c b/src/r_data.c
index b92d88f1943e96e276f79a739a94aebfc08020b3..cd9ff627332cf9edf9307638747306adb547c6c3 100644
--- a/src/r_data.c
+++ b/src/r_data.c
@@ -160,6 +160,7 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig
 		if (position < 0)
 		{
 			count += position;
+			source -= position; // start further down the column
 			position = 0;
 		}
 
@@ -173,6 +174,44 @@ static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 orig
 	}
 }
 
+static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, INT32 originy, INT32 cacheheight, INT32 patchheight)
+{
+	INT32 count, position;
+	UINT8 *source, *dest;
+	INT32 topdelta, prevdelta = -1;
+
+	while (patch->topdelta != 0xff)
+	{
+		topdelta = patch->topdelta;
+		if (topdelta <= prevdelta)
+			topdelta += prevdelta;
+		prevdelta = topdelta;
+		topdelta = patchheight-patch->length-topdelta;
+		source = (UINT8 *)patch + 2 + patch->length; // patch + 3 + (patch->length-1)
+		count = patch->length;
+		position = originy + topdelta;
+
+		if (position < 0)
+		{
+			count += position;
+			source += position; // start further UP the column
+			position = 0;
+		}
+
+		if (position + count > cacheheight)
+			count = cacheheight - position;
+
+		dest = cache + position;
+		if (count > 0)
+		{
+			for (; dest < cache + position + count; --source)
+				*dest++ = *source;
+		}
+
+		patch = (column_t *)((UINT8 *)patch + patch->length + 4);
+	}
+}
+
 //
 // R_GenerateTexture
 //
@@ -191,7 +230,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
 	texture_t *texture;
 	texpatch_t *patch;
 	patch_t *realpatch;
-	int x, x1, x2, i;
+	int x, x1, x2, i, width, height;
 	size_t blocksize;
 	column_t *patchcol;
 	UINT32 *colofs;
@@ -239,6 +278,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
 		if (holey)
 		{
 			texture->holes = true;
+			texture->flip = patch->flip;
 			blocksize = W_LumpLengthPwad(patch->wad, patch->lump);
 			block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function
 				&texturecache[texnum]);
@@ -249,6 +289,14 @@ static UINT8 *R_GenerateTexture(size_t texnum)
 			colofs = (UINT32 *)(void *)(block + 8);
 			texturecolumnofs[texnum] = colofs;
 			blocktex = block;
+			if (patch->flip & 1) // flip the patch horizontally
+			{
+				UINT32 *realcolofs = (UINT32 *)realpatch->columnofs;
+				for (x = 0; x < texture->width; x++)
+					colofs[x] = realcolofs[texture->width-1-x]; // swap with the offset of the other side of the texture
+			}
+			// we can't as easily flip the patch vertically sadly though,
+			//  we have wait until the texture itself is drawn to do that
 			for (x = 0; x < texture->width; x++)
 				colofs[x] = LONG(LONG(colofs[x]) + 3);
 			goto done;
@@ -259,6 +307,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
 
 	// multi-patch textures (or 'composite')
 	texture->holes = false;
+	texture->flip = 0;
 	blocksize = (texture->width * 4) + (texture->width * texture->height);
 	texturememory += blocksize;
 	block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]);
@@ -277,7 +326,9 @@ static UINT8 *R_GenerateTexture(size_t texnum)
 	{
 		realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE);
 		x1 = patch->originx;
-		x2 = x1 + SHORT(realpatch->width);
+		width = SHORT(realpatch->width);
+		height = SHORT(realpatch->height);
+		x2 = x1 + width;
 
 		if (x1 < 0)
 			x = 0;
@@ -289,11 +340,17 @@ static UINT8 *R_GenerateTexture(size_t texnum)
 
 		for (; x < x2; x++)
 		{
-			patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1]));
+			if (patch->flip & 1)
+				patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[(x1+width-1)-x]));
+			else
+				patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1]));
 
 			// generate column ofset lookup
 			colofs[x] = LONG((x * texture->height) + (texture->width*4));
-			R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height);
+			if (patch->flip & 2)
+				R_DrawFlippedColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height, height);
+			else
+				R_DrawColumnInCache(patchcol, block + LONG(colofs[x]), patch->originy, texture->height);
 		}
 	}
 
@@ -303,6 +360,32 @@ done:
 	return blocktex;
 }
 
+//
+// R_GetTextureNum
+//
+// Returns the actual texture id that we should use.
+// This can either be texnum, the current frame for texnum's anim (if animated),
+// or 0 if not valid.
+//
+INT32 R_GetTextureNum(INT32 texnum)
+{
+	if (texnum < 0 || texnum >= numtextures)
+		return 0;
+	return texturetranslation[texnum];
+}
+
+//
+// R_CheckTextureCache
+//
+// Use this if you need to make sure the texture is cached before R_GetColumn calls
+// e.g.: midtextures and FOF walls
+//
+void R_CheckTextureCache(INT32 tex)
+{
+	if (!texturecache[tex])
+		R_GenerateTexture(tex);
+}
+
 //
 // R_GetColumn
 //
@@ -469,6 +552,7 @@ void R_LoadTextures(void)
 				texture->height = SHORT(patchlump->height)*patchcount;
 				texture->patchcount = patchcount;
 				texture->holes = false;
+				texture->flip = 0;
 
 				// Allocate information for the texture's patches.
 				for (k = 0; k < patchcount; k++)
@@ -479,6 +563,7 @@ void R_LoadTextures(void)
 					patch->originy = (INT16)(k*patchlump->height);
 					patch->wad = (UINT16)w;
 					patch->lump = texstart + j;
+					patch->flip = 0;
 				}
 
 				Z_Unlock(patchlump);
@@ -502,6 +587,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
 	char *patchName = NULL;
 	INT16 patchXPos;
 	INT16 patchYPos;
+	UINT8 flip = 0;
 	texpatch_t *resultPatch = NULL;
 	lumpnum_t patchLumpNum;
 
@@ -598,6 +684,47 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
 	}
 	Z_Free(texturesToken);
 
+	// Patch parameters block (OPTIONAL)
+	// added by Monster Iestyn (22/10/16)
+
+	// Left Curly Brace
+	texturesToken = M_GetToken(NULL);
+	if (texturesToken == NULL)
+		; // move on and ignore, R_ParseTextures will deal with this
+	else
+	{
+		if (strcmp(texturesToken,"{")==0)
+		{
+			Z_Free(texturesToken);
+			texturesToken = M_GetToken(NULL);
+			if (texturesToken == NULL)
+			{
+				I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s parameters should be",patchName);
+			}
+			while (strcmp(texturesToken,"}")!=0)
+			{
+				if (stricmp(texturesToken, "FLIPX")==0)
+					flip |= 1;
+				else if (stricmp(texturesToken, "FLIPY")==0)
+					flip |= 2;
+				Z_Free(texturesToken);
+
+				texturesToken = M_GetToken(NULL);
+				if (texturesToken == NULL)
+				{
+					I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s parameters or right curly brace should be",patchName);
+				}
+			}
+		}
+		else
+		{
+			 // this is not what we wanted...
+			 // undo last read so R_ParseTextures can re-get the token for its own purposes
+			M_UnGetToken();
+		}
+		Z_Free(texturesToken);
+	}
+
 	if (actuallyLoadPatch == true)
 	{
 		// Check lump exists
@@ -608,6 +735,7 @@ static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch)
 		resultPatch->originy = patchYPos;
 		resultPatch->lump = patchLumpNum & 65535;
 		resultPatch->wad = patchLumpNum>>16;
+		resultPatch->flip = flip;
 		// Clean up a little after ourselves
 		Z_Free(patchName);
 		// Then return it
diff --git a/src/r_data.h b/src/r_data.h
index 69a2882af52da27a55f2dca8a43a4006c8a66554..bea1cba3b018d1eb4fe4c475e6167e901a87fb29 100644
--- a/src/r_data.h
+++ b/src/r_data.h
@@ -31,6 +31,7 @@ typedef struct
 	// Block origin (always UL), which has already accounted for the internal origin of the patch.
 	INT16 originx, originy;
 	UINT16 wad, lump;
+	UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both
 } texpatch_t;
 
 // A maptexturedef_t describes a rectangular texture,
@@ -42,6 +43,7 @@ typedef struct
 	char name[8];
 	INT16 width, height;
 	boolean holes;
+	UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both
 
 	// All the patches[patchcount] are drawn back to front into the cached texture.
 	INT16 patchcount;
@@ -65,6 +67,9 @@ extern CV_PossibleValue_t Color_cons_t[];
 void R_LoadTextures(void);
 void R_FlushTextureCache(void);
 
+INT32 R_GetTextureNum(INT32 texnum);
+void R_CheckTextureCache(INT32 tex);
+
 // Retrieve column data for span blitting.
 UINT8 *R_GetColumn(fixed_t tex, INT32 col);
 
diff --git a/src/r_defs.h b/src/r_defs.h
index 9109ac7c36af43d5a2cde3019b50544d3e58cb48..32be7c4c8d360a6de6bbef0dbbff78fdf9175861 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -203,6 +203,7 @@ typedef struct r_lightlist_s
 	fixed_t heightstep;
 	fixed_t botheight;
 	fixed_t botheightstep;
+	fixed_t startheight; // for repeating midtextures
 	INT16 lightlevel;
 	extracolormap_t *extra_colormap;
 	lighttable_t *rcolormap;
@@ -224,15 +225,6 @@ typedef struct linechain_s
 
 
 
-// ZDoom C++ to Legacy C conversion Tails 04-29-2002 (for slopes)
-typedef struct secplane_t
-{
-	// the plane is defined as a*x + b*y + c*z + d = 0
-	// ic is 1/c, for faster Z calculations
-
-	fixed_t a, b, c, d, ic;
-} secplane_t;
-
 // Slopes
 #ifdef ESLOPE
 typedef enum {
@@ -392,6 +384,7 @@ typedef struct sector_s
 #endif
 
 	// these are saved for netgames, so do not let Lua touch these!
+	INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed
 
 	// offsets sector spawned with (via linedef type 7)
 	fixed_t spawn_flr_xoffs, spawn_flr_yoffs;
diff --git a/src/r_draw.h b/src/r_draw.h
index 60c3c9db6edeccb2afa25e9a25ed8347be149c12..4a105b5b082e7d2f99a23d952b35a79cd296b172 100644
--- a/src/r_draw.h
+++ b/src/r_draw.h
@@ -162,6 +162,7 @@ void R_DrawSplat_8(void);
 void R_DrawTranslucentSplat_8(void);
 void R_DrawTranslucentSpan_8(void);
 void R_Draw2sMultiPatchColumn_8(void);
+void R_Draw2sMultiPatchTranslucentColumn_8(void);
 void R_DrawFogSpan_8(void);
 void R_DrawFogColumn_8(void);
 void R_DrawColumnShadowed_8(void);
diff --git a/src/r_draw8.c b/src/r_draw8.c
index c1b7da11b2949def9e4a07261583c5a609c046ea..9340b61c6135059228a8280ccfe58237b9deb6a9 100644
--- a/src/r_draw8.c
+++ b/src/r_draw8.c
@@ -203,6 +203,103 @@ void R_Draw2sMultiPatchColumn_8(void)
 	}
 }
 
+void R_Draw2sMultiPatchTranslucentColumn_8(void)
+{
+	INT32 count;
+	register UINT8 *dest;
+	register fixed_t frac;
+	fixed_t fracstep;
+
+	count = dc_yh - dc_yl;
+
+	if (count < 0) // Zero length, column does not exceed a pixel.
+		return;
+
+#ifdef RANGECHECK
+	if ((unsigned)dc_x >= (unsigned)vid.width || dc_yl < 0 || dc_yh >= vid.height)
+		return;
+#endif
+
+	// Framebuffer destination address.
+	// Use ylookup LUT to avoid multiply with ScreenWidth.
+	// Use columnofs LUT for subwindows?
+
+	//dest = ylookup[dc_yl] + columnofs[dc_x];
+	dest = &topleft[dc_yl*vid.width + dc_x];
+
+	count++;
+
+	// Determine scaling, which is the only mapping to be done.
+	fracstep = dc_iscale;
+	//frac = dc_texturemid + (dc_yl - centery)*fracstep;
+	frac = (dc_texturemid + FixedMul((dc_yl << FRACBITS) - centeryfrac, fracstep))*(!dc_hires);
+
+	// Inner loop that does the actual texture mapping, e.g. a DDA-like scaling.
+	// This is as fast as it gets.
+	{
+		register const UINT8 *source = dc_source;
+		register const UINT8 *transmap = dc_transmap;
+		register const lighttable_t *colormap = dc_colormap;
+		register INT32 heightmask = dc_texheight-1;
+		register UINT8 val;
+		if (dc_texheight & heightmask)   // not a power of 2 -- killough
+		{
+			heightmask++;
+			heightmask <<= FRACBITS;
+
+			if (frac < 0)
+				while ((frac += heightmask) <  0);
+			else
+				while (frac >= heightmask)
+					frac -= heightmask;
+
+			do
+			{
+				// Re-map color indices from wall texture column
+				//  using a lighting/special effects LUT.
+				// heightmask is the Tutti-Frutti fix
+				val = source[frac>>FRACBITS];
+
+				if (val != TRANSPARENTPIXEL)
+					*dest = colormap[*(transmap + (val<<8) + (*dest))];
+
+				dest += vid.width;
+
+				// Avoid overflow.
+				if (fracstep > 0x7FFFFFFF - frac)
+					frac += fracstep - heightmask;
+				else
+					frac += fracstep;
+
+				while (frac >= heightmask)
+					frac -= heightmask;
+			} while (--count);
+		}
+		else
+		{
+			while ((count -= 2) >= 0) // texture height is a power of 2
+			{
+				val = source[(frac>>FRACBITS) & heightmask];
+				if (val != TRANSPARENTPIXEL)
+					*dest = colormap[*(transmap + (val<<8) + (*dest))];
+				dest += vid.width;
+				frac += fracstep;
+				val = source[(frac>>FRACBITS) & heightmask];
+				if (val != TRANSPARENTPIXEL)
+					*dest = colormap[*(transmap + (val<<8) + (*dest))];
+				dest += vid.width;
+				frac += fracstep;
+			}
+			if (count & 1)
+			{
+				val = source[(frac>>FRACBITS) & heightmask];
+				if (val != TRANSPARENTPIXEL)
+					*dest = colormap[*(transmap + (val<<8) + (*dest))];
+			}
+		}
+	}
+}
+
 /**	\brief The R_DrawShadeColumn_8 function
 	Experiment to make software go faster. Taken from the Boom source
 */
diff --git a/src/r_main.c b/src/r_main.c
index b05e37b53904974720c7be402147743dacaab949..4cff0ff8302c843b97497b1961673d7d171cf328 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -148,7 +148,6 @@ consvar_t cv_flipcam2 = {"flipcam2", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo,
 consvar_t cv_shadow = {"shadow", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_shadowoffs = {"offsetshadows", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
-consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
 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};
@@ -366,69 +365,6 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y)
 	return R_PointToDist2(viewx, viewy, x, y);
 }
 
-/***************************************
-*** Zdoom C++ to Legacy C conversion ***
-****************************************/
-
-// Utility to find the Z height at an XY location in a sector (for slopes)
-fixed_t R_SecplaneZatPoint(secplane_t *secplane, fixed_t x, fixed_t y)
-{
-	return FixedMul(secplane->ic, -secplane->d - DMulScale16(secplane->a, x, secplane->b, y));
-}
-
-// Returns the value of z at (x,y) if d is equal to dist
-fixed_t R_SecplaneZatPointDist (secplane_t *secplane, fixed_t x, fixed_t y, fixed_t dist)
-{
-	return FixedMul(secplane->ic, -dist - DMulScale16(secplane->a, x, secplane->b, y));
-}
-
-// Flips the plane's vertical orientiation, so that if it pointed up,
-// it will point down, and vice versa.
-void R_SecplaneFlipVert(secplane_t *secplane)
-{
-	secplane->a = -secplane->a;
-	secplane->b = -secplane->b;
-	secplane->c = -secplane->c;
-	secplane->d = -secplane->d;
-	secplane->ic = -secplane->ic;
-}
-
-// Returns true if 2 planes are the same
-boolean R_ArePlanesSame(secplane_t *original, secplane_t *other)
-{
-	return original->a == other->a && original->b == other->b
-		&& original->c == other->c && original->d == other->d;
-}
-
-// Returns true if 2 planes are different
-boolean R_ArePlanesDifferent(secplane_t *original, secplane_t *other)
-{
-	return original->a != other->a || original->b != other->b
-		|| original->c != other->c || original->d != other->d;
-}
-
-// Moves a plane up/down by hdiff units
-void R_SecplaneChangeHeight(secplane_t *secplane, fixed_t hdiff)
-{
-	secplane->d = secplane->d - FixedMul(hdiff, secplane->c);
-}
-
-// Returns how much this plane's height would change if d were set to oldd
-fixed_t R_SecplaneHeightDiff(secplane_t *secplane, fixed_t oldd)
-{
-	return FixedMul(oldd - secplane->d, secplane->ic);
-}
-
-fixed_t R_SecplanePointToDist(secplane_t *secplane, fixed_t x, fixed_t y, fixed_t z)
-{
-	return -TMulScale16(secplane->a, x, y, secplane->b, z, secplane->c);
-}
-
-fixed_t R_SecplanePointToDist2(secplane_t *secplane, fixed_t x, fixed_t y, fixed_t z)
-{
-	return -TMulScale16(secplane->a, x, secplane->b, y, z, secplane->c);
-}
-
 //
 // R_ScaleFromGlobalAngle
 // Returns the texture mapping scale for the current line (horizontal span)
@@ -1424,7 +1360,6 @@ void R_RegisterEngineStuff(void)
 {
 	CV_RegisterVar(&cv_gravity);
 	CV_RegisterVar(&cv_tailspickup);
-	CV_RegisterVar(&cv_soniccd);
 	CV_RegisterVar(&cv_allowmlook);
 	CV_RegisterVar(&cv_homremoval);
 	CV_RegisterVar(&cv_flipcam);
diff --git a/src/r_main.h b/src/r_main.h
index 8f46a938e525f00bd08147b3ff2c5dbcc0fced1b..2e768cb9c91cfeff09f67f6ce520427aefc292b1 100644
--- a/src/r_main.h
+++ b/src/r_main.h
@@ -61,18 +61,6 @@ angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
 fixed_t R_PointToDist(fixed_t x, fixed_t y);
 fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1);
 
-// ZDoom C++ to Legacy C conversion Tails 04-29-2002
-fixed_t R_SecplaneZatPoint(secplane_t *secplane, fixed_t x, fixed_t y);
-fixed_t R_SecplaneZatPointDist(secplane_t *secplane, fixed_t x, fixed_t y,
-	fixed_t dist);
-void R_SecplaneFlipVert(secplane_t *secplane);
-boolean R_ArePlanesSame(secplane_t *original,  secplane_t *other);
-boolean R_ArePlanesDifferent(secplane_t *original,  secplane_t *other);
-void R_SecplaneChangeHeight(secplane_t *secplane, fixed_t hdiff);
-fixed_t R_SecplaneHeightDiff(secplane_t *secplane, fixed_t oldd);
-fixed_t R_SecplanePointToDist(secplane_t *secplane, fixed_t x, fixed_t y, fixed_t z);
-fixed_t R_SecplanePointToDist2(secplane_t *secplane, fixed_t x, fixed_t y, fixed_t z);
-
 fixed_t R_ScaleFromGlobalAngle(angle_t visangle);
 subsector_t *R_PointInSubsector(fixed_t x, fixed_t y);
 subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y);
diff --git a/src/r_plane.c b/src/r_plane.c
index e21e15d1ac551f70bb75d28bb6c78d6f254fcbbf..11dd79d41e7a8aa4ac4862411feb8655cf168505 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -431,6 +431,9 @@ static visplane_t *new_visplane(unsigned hash)
 visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 	fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap,
 	ffloor_t *pfloor
+#ifdef POLYOBJECTS_PLANES
+			, polyobj_t *polyobj
+#endif
 #ifdef ESLOPE
 			, pslope_t *slope
 #endif
@@ -470,6 +473,8 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 #ifdef POLYOBJECTS_PLANES
 		if (check->polyobj && pfloor)
 			continue;
+		if (polyobj != check->polyobj)
+			continue;
 #endif
 		if (height == check->height && picnum == check->picnum
 			&& lightlevel == check->lightlevel
@@ -504,7 +509,7 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 	check->viewangle = viewangle;
 	check->plangle = plangle;
 #ifdef POLYOBJECTS_PLANES
-	check->polyobj = NULL;
+	check->polyobj = polyobj;
 #endif
 #ifdef ESLOPE
 	check->slope = slope;
@@ -720,7 +725,11 @@ void R_DrawPlanes(void)
 				continue;
 			}
 
-			if (pl->ffloor != NULL)
+			if (pl->ffloor != NULL
+#ifdef POLYOBJECTS_PLANES
+			|| pl->polyobj != NULL
+#endif
+			)
 				continue;
 
 			R_DrawSinglePlane(pl);
diff --git a/src/r_plane.h b/src/r_plane.h
index ec19407162a0e7bcdec3fd153aaef974ed1524b5..16c8c12a448e6cd5b905b066391404889b0b8eb9 100644
--- a/src/r_plane.h
+++ b/src/r_plane.h
@@ -97,6 +97,9 @@ void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2);
 void R_DrawPlanes(void);
 visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle,
 	extracolormap_t *planecolormap, ffloor_t *ffloor
+#ifdef POLYOBJECTS_PLANES
+	, polyobj_t *polyobj
+#endif
 #ifdef ESLOPE
 	, pslope_t *slope
 #endif
diff --git a/src/r_segs.c b/src/r_segs.c
index 257be29891cfcb4725dd9c36635d048edfe5dba4..a4264eea5d7259ed9b34ba941d5c91c04174b9c1 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -271,11 +271,20 @@ static void R_Render2sidedMultiPatchColumn(column_t *column)
 
 		if (colfunc == wallcolfunc)
 			twosmultipatchfunc();
+		else if (colfunc == fuzzcolfunc)
+			twosmultipatchtransfunc();
 		else
 			colfunc();
 	}
 }
 
+// quick wrapper for R_DrawFlippedMaskedColumn so it can be set as a colfunc_2s value
+// uses column2s_length for texture->height as above
+static void R_DrawFlippedMaskedSegColumn(column_t *column)
+{
+	R_DrawFlippedMaskedColumn(column, column2s_length);
+}
+
 void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 {
 	size_t pindex;
@@ -300,7 +309,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 	curline = ds->curline;
 	frontsector = curline->frontsector;
 	backsector = curline->backsector;
-	texnum = texturetranslation[curline->sidedef->midtexture];
+	texnum = R_GetTextureNum(curline->sidedef->midtexture);
 	windowbottom = windowtop = sprbotscreen = INT32_MAX;
 
 	// hack translucent linedef types (900-909 for transtables 1-9)
@@ -344,10 +353,21 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 	rw_scalestep = ds->scalestep;
 	spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
 
+	// Texture must be cached before setting colfunc_2s,
+	// otherwise texture[texnum]->holes may be false when it shouldn't be
+	R_CheckTextureCache(texnum);
 	// handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
 	// are not stored per-column with post info in SRB2
 	if (textures[texnum]->holes)
-		colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture
+	{
+		if (textures[texnum]->flip & 2) // vertically flipped?
+		{
+			colfunc_2s = R_DrawFlippedMaskedSegColumn;
+			column2s_length = textures[texnum]->height;
+		}
+		else
+			colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture
+	}
 	else
 	{
 		colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info)
@@ -391,6 +411,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 			rlight->height = (centeryfrac) - FixedMul((light->height - viewz), spryscale);
 			rlight->heightstep = -FixedMul(rw_scalestep, (light->height - viewz));
 #endif
+			rlight->startheight = rlight->height; // keep starting value here to reset for each repeat
 			rlight->lightlevel = *light->lightlevel;
 			rlight->extra_colormap = light->extra_colormap;
 			rlight->flags = light->flags;
@@ -484,6 +505,14 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 		{
 			rw_scalestep = ds->scalestep;
 			spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
+			if (dc_numlights)
+			{ // reset all lights to their starting heights
+				for (i = 0; i < dc_numlights; i++)
+				{
+					rlight = &dc_lightlist[i];
+					rlight->height = rlight->startheight;
+				}
+			}
 		}
 
 #ifndef ESLOPE
@@ -700,6 +729,14 @@ static void R_DrawRepeatMaskedColumn(column_t *col)
 	} while (sprtopscreen < sprbotscreen);
 }
 
+static void R_DrawRepeatFlippedMaskedColumn(column_t *col)
+{
+	do {
+		R_DrawFlippedMaskedColumn(col, column2s_length);
+		sprtopscreen += dc_texheight*spryscale;
+	} while (sprtopscreen < sprbotscreen);
+}
+
 //
 // R_RenderThickSideRange
 // Renders all the thick sides in the given range.
@@ -746,7 +783,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	curline = ds->curline;
 	backsector = pfloor->target;
 	frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector;
-	texnum = texturetranslation[sides[pfloor->master->sidenum[0]].midtexture];
+	texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture);
 
 	colfunc = wallcolfunc;
 
@@ -754,7 +791,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	{
 		size_t linenum = curline->linedef-backsector->lines[0];
 		newline = pfloor->master->frontsector->lines[0] + linenum;
-		texnum = texturetranslation[sides[newline->sidenum[0]].midtexture];
+		texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture);
 	}
 
 	if (pfloor->flags & FF_TRANSLUCENT)
@@ -1024,10 +1061,21 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 
 	dc_texturemid += offsetvalue;
 
+	// Texture must be cached before setting colfunc_2s,
+	// otherwise texture[texnum]->holes may be false when it shouldn't be
+	R_CheckTextureCache(texnum);
 	//faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures
 	//     are not stored per-column with post info anymore in Doom Legacy
 	if (textures[texnum]->holes)
-		colfunc_2s = R_DrawRepeatMaskedColumn;                    //render the usual 2sided single-patch packed texture
+	{
+		if (textures[texnum]->flip & 2) // vertically flipped?
+		{
+			colfunc_2s = R_DrawRepeatFlippedMaskedColumn;
+			column2s_length = textures[texnum]->height;
+		}
+		else
+			colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture
+	}
 	else
 	{
 		colfunc_2s = R_Render2sidedMultiPatchColumn;        //render multipatch with no holes (no post_t info)
@@ -1936,14 +1984,16 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 	if (!backsector)
 	{
+		fixed_t texheight;
 		// single sided line
-		midtexture = texturetranslation[sidedef->midtexture];
+		midtexture = R_GetTextureNum(sidedef->midtexture);
+		texheight = textureheight[midtexture];
 		// a single sided line is terminal, so it must mark ends
 		markfloor = markceiling = true;
 #ifdef ESLOPE
 		if (linedef->flags & ML_EFFECT2) {
 			if (linedef->flags & ML_DONTPEGBOTTOM)
-				rw_midtexturemid = frontsector->floorheight + textureheight[sidedef->midtexture] - viewz;
+				rw_midtexturemid = frontsector->floorheight + texheight - viewz;
 			else
 				rw_midtexturemid = frontsector->ceilingheight - viewz;
 		}
@@ -1952,10 +2002,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		if (linedef->flags & ML_DONTPEGBOTTOM)
 		{
 #ifdef ESLOPE
-			rw_midtexturemid = worldbottom + textureheight[sidedef->midtexture];
+			rw_midtexturemid = worldbottom + texheight;
 			rw_midtextureslide = floorfrontslide;
 #else
-			vtop = frontsector->floorheight + textureheight[sidedef->midtexture];
+			vtop = frontsector->floorheight + texheight;
 			// bottom of texture at bottom
 			rw_midtexturemid = vtop - viewz;
 #endif
@@ -2187,76 +2237,50 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 #endif
 			)
 		{
+			fixed_t texheight;
 			// top texture
 			if ((linedef->flags & (ML_DONTPEGTOP) && (linedef->flags & ML_DONTPEGBOTTOM))
 				&& linedef->sidenum[1] != 0xffff)
 			{
 				// Special case... use offsets from 2nd side but only if it has a texture.
 				side_t *def = &sides[linedef->sidenum[1]];
-				toptexture = texturetranslation[def->toptexture];
+				toptexture = R_GetTextureNum(def->toptexture);
 
 				if (!toptexture) //Second side has no texture, use the first side's instead.
-					toptexture = texturetranslation[sidedef->toptexture];
-
+					toptexture = R_GetTextureNum(sidedef->toptexture);
+				texheight = textureheight[toptexture];
+			}
+			else
+			{
+				toptexture = R_GetTextureNum(sidedef->toptexture);
+				texheight = textureheight[toptexture];
+			}
 #ifdef ESLOPE
-				if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
-					if (linedef->flags & ML_DONTPEGTOP)
-						rw_toptexturemid = frontsector->ceilingheight - viewz;
-					else
-						rw_toptexturemid = backsector->ceilingheight - viewz;
-				} else
-#endif
+			if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
 				if (linedef->flags & ML_DONTPEGTOP)
-				{
-					// top of texture at top
-					rw_toptexturemid = worldtop;
-#ifdef ESLOPE
-					rw_toptextureslide = ceilingfrontslide;
-#endif
-				}
+					rw_toptexturemid = frontsector->ceilingheight - viewz;
 				else
-				{
+					rw_toptexturemid = backsector->ceilingheight - viewz;
+			} else
+#endif
+			if (linedef->flags & ML_DONTPEGTOP)
+			{
+				// top of texture at top
+				rw_toptexturemid = worldtop;
 #ifdef ESLOPE
-					rw_toptexturemid = worldhigh + textureheight[def->toptexture];
-					rw_toptextureslide = ceilingbackslide;
-#else
-					vtop = backsector->ceilingheight + textureheight[def->toptexture];
-					// bottom of texture
-					rw_toptexturemid = vtop - viewz;
+				rw_toptextureslide = ceilingfrontslide;
 #endif
-				}
 			}
 			else
 			{
-				toptexture = texturetranslation[sidedef->toptexture];
-
-#ifdef ESLOPE
-				if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
-					if (linedef->flags & ML_DONTPEGTOP)
-						rw_toptexturemid = frontsector->ceilingheight - viewz;
-					else
-						rw_toptexturemid = backsector->ceilingheight - viewz;
-				} else
-#endif
-				if (linedef->flags & ML_DONTPEGTOP)
-				{
-					// top of texture at top
-					rw_toptexturemid = worldtop;
 #ifdef ESLOPE
-					rw_toptextureslide = ceilingfrontslide;
-#endif
-				}
-				else
-				{
-#ifdef ESLOPE
-					rw_toptexturemid = worldhigh + textureheight[sidedef->toptexture];
-					rw_toptextureslide = ceilingbackslide;
+				rw_toptexturemid = worldhigh + texheight;
+				rw_toptextureslide = ceilingbackslide;
 #else
-					vtop = backsector->ceilingheight + textureheight[sidedef->toptexture];
-					// bottom of texture
-					rw_toptexturemid = vtop - viewz;
+				vtop = backsector->ceilingheight + texheight;
+				// bottom of texture
+				rw_toptexturemid = vtop - viewz;
 #endif
-				}
 			}
 		}
 		// check BOTTOM TEXTURE
@@ -2267,7 +2291,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			)     //seulement si VISIBLE!!!
 		{
 			// bottom texture
-			bottomtexture = texturetranslation[sidedef->bottomtexture];
+			bottomtexture = R_GetTextureNum(sidedef->bottomtexture);
 
 #ifdef ESLOPE
 			if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
@@ -2552,7 +2576,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 			ds_p->numthicksides = numthicksides = i;
 		}
-		if (sidedef->midtexture)
+		if (sidedef->midtexture > 0 && sidedef->midtexture < numtextures)
 		{
 			// masked midtexture
 			if (!ds_p->thicksidecol)
@@ -3164,12 +3188,12 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	if (maskedtexture && !(ds_p->silhouette & SIL_TOP))
 	{
 		ds_p->silhouette |= SIL_TOP;
-		ds_p->tsilheight = sidedef->midtexture ? INT32_MIN: INT32_MAX;
+		ds_p->tsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MIN: INT32_MAX;
 	}
 	if (maskedtexture && !(ds_p->silhouette & SIL_BOTTOM))
 	{
 		ds_p->silhouette |= SIL_BOTTOM;
-		ds_p->bsilheight = sidedef->midtexture ? INT32_MAX: INT32_MIN;
+		ds_p->bsilheight = (sidedef->midtexture > 0 && sidedef->midtexture < numtextures) ? INT32_MAX: INT32_MIN;
 	}
 	ds_p++;
 }
diff --git a/src/r_things.c b/src/r_things.c
index 9f6cad5298011a3e29141e120ea4016864eff5f8..e9080dc050a7a66979f8fee8ab040602dd665a40 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -712,7 +712,7 @@ void R_DrawMaskedColumn(column_t *column)
 	dc_texturemid = basetexturemid;
 }
 
-static void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight)
+void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight)
 {
 	INT32 topscreen;
 	INT32 bottomscreen;
@@ -1885,21 +1885,25 @@ static void R_CreateDrawNodes(void)
 				entry->ffloor = ds->thicksides[i];
 			}
 		}
-		if (ds->maskedtexturecol)
-		{
 #ifdef POLYOBJECTS_PLANES
-			// Check for a polyobject plane, but only if this is a front line
-			if (ds->curline->polyseg && ds->curline->polyseg->visplane && !ds->curline->side) {
-				// Put it in!
+		// Check for a polyobject plane, but only if this is a front line
+		if (ds->curline->polyseg && ds->curline->polyseg->visplane && !ds->curline->side) {
+			plane = ds->curline->polyseg->visplane;
+			R_PlaneBounds(plane);
 
+			if (plane->low < con_clipviewtop || plane->high > vid.height || plane->high > plane->low)
+				;
+			else {
+				// Put it in!
 				entry = R_CreateDrawNode(&nodehead);
-				entry->plane = ds->curline->polyseg->visplane;
+				entry->plane = plane;
 				entry->seg = ds;
-				ds->curline->polyseg->visplane->polyobj = ds->curline->polyseg;
-				ds->curline->polyseg->visplane = NULL;
 			}
+			ds->curline->polyseg->visplane = NULL;
+		}
 #endif
-
+		if (ds->maskedtexturecol)
+		{
 			entry = R_CreateDrawNode(&nodehead);
 			entry->seg = ds;
 		}
@@ -1942,6 +1946,29 @@ static void R_CreateDrawNodes(void)
 		}
 	}
 
+#ifdef POLYOBJECTS_PLANES
+	// find all the remaining polyobject planes and add them on the end of the list
+	// probably this is a terrible idea if we wanted them to be sorted properly
+	// but it works getting them in for now
+	for (i = 0; i < numPolyObjects; i++)
+	{
+		if (!PolyObjects[i].visplane)
+			continue;
+		plane = PolyObjects[i].visplane;
+		R_PlaneBounds(plane);
+
+		if (plane->low < con_clipviewtop || plane->high > vid.height || plane->high > plane->low)
+		{
+			PolyObjects[i].visplane = NULL;
+			continue;
+		}
+		entry = R_CreateDrawNode(&nodehead);
+		entry->plane = plane;
+		// note: no seg is set, for what should be obvious reasons
+		PolyObjects[i].visplane = NULL;
+	}
+#endif
+
 	if (visspritecount == 0)
 		return;
 
@@ -1998,13 +2025,16 @@ static void R_CreateDrawNodes(void)
 				if (x1 < r2->plane->minx) x1 = r2->plane->minx;
 				if (x2 > r2->plane->maxx) x2 = r2->plane->maxx;
 
-				for (i = x1; i <= x2; i++)
+				if (r2->seg) // if no seg set, assume the whole thing is in front or something stupid
 				{
-					if (r2->seg->frontscale[i] > rover->sortscale)
-						break;
+					for (i = x1; i <= x2; i++)
+					{
+						if (r2->seg->frontscale[i] > rover->sortscale)
+							break;
+					}
+					if (i > x2)
+						continue;
 				}
-				if (i > x2)
-					continue;
 
 				entry = R_CreateDrawNode(NULL);
 				(entry->prev = r2->prev)->next = entry;
@@ -2880,6 +2910,7 @@ void R_AddSkins(UINT16 wadnum)
 			GETFLAG(STOMPDAMAGE)
 			GETFLAG(MARIODAMAGE)
 			GETFLAG(MACHINE)
+			GETFLAG(NOSPINDASHDUST)
 #undef GETFLAG
 
 			else // let's check if it's a sound, otherwise error out
diff --git a/src/r_things.h b/src/r_things.h
index 20dd25abf83ab2f70dd99438466909a8dc6c2b19..572884d21149071f0ad25797f5ac5bbf3a6486ae 100644
--- a/src/r_things.h
+++ b/src/r_things.h
@@ -46,6 +46,7 @@ extern fixed_t windowtop;
 extern fixed_t windowbottom;
 
 void R_DrawMaskedColumn(column_t *column);
+void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight);
 void R_SortVisSprites(void);
 
 //faB: find sprites in wadfile, replace existing, add new ones
diff --git a/src/s_sound.c b/src/s_sound.c
index 47a9555614532bc0631f5cd1d6c6db93d0e30e15..971961897344cca46ed3f5481303f484025855a0 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -607,6 +607,13 @@ void S_StartSound(const void *origin, sfxenum_t sfx_id)
 				sfx_id = sfx_mario6;
 				break;
 			case sfx_shield:
+			case sfx_wirlsg:
+			case sfx_forcsg:
+			case sfx_elemsg:
+			case sfx_armasg:
+			case sfx_s3k3e:
+			case sfx_s3k3f:
+			case sfx_s3k41:
 				sfx_id = sfx_mario3;
 				break;
 			case sfx_itemup:
diff --git a/src/screen.c b/src/screen.c
index d001557853297ddd3289b10994d14d6f9813cad7..97c865a97f05d086cb515649c13d3111adb159dd 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -49,6 +49,7 @@ void (*splatfunc)(void); // span drawer w/ transparency
 void (*basespanfunc)(void); // default span func for color mode
 void (*transtransfunc)(void); // translucent translated column drawer
 void (*twosmultipatchfunc)(void); // for cols with transparent pixels
+void (*twosmultipatchtransfunc)(void); // for cols with transparent pixels AND translucency
 
 // ------------------
 // global video state
@@ -127,6 +128,7 @@ void SCR_SetMode(void)
 		fuzzcolfunc = R_DrawTranslucentColumn_8;
 		walldrawerfunc = R_DrawWallColumn_8;
 		twosmultipatchfunc = R_Draw2sMultiPatchColumn_8;
+		twosmultipatchtransfunc = R_Draw2sMultiPatchTranslucentColumn_8;
 #ifdef RUSEASM
 		if (R_ASM)
 		{
diff --git a/src/screen.h b/src/screen.h
index 2dff4590ed6e35f54682ea5a335063582da2ae48..a61de7f92c4e8910424a71d0a74919f75562498e 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -136,6 +136,7 @@ extern void (*basespanfunc)(void);
 extern void (*splatfunc)(void);
 extern void (*transtransfunc)(void);
 extern void (*twosmultipatchfunc)(void);
+extern void (*twosmultipatchtransfunc)(void);
 
 // -----
 // CPUID
diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj
index 820192649d981adeaa477f0791d200f46d3ddfe9..abf6d76d2935d7546f445cf9b53880963d0b1433 100644
--- a/src/sdl/Srb2SDL-vc10.vcxproj
+++ b/src/sdl/Srb2SDL-vc10.vcxproj
@@ -295,6 +295,7 @@
     </ClCompile>
     <ClCompile Include="..\i_tcp.c" />
     <ClCompile Include="..\lua_baselib.c" />
+    <ClCompile Include="..\lua_blockmaplib.c" />
     <ClCompile Include="..\lua_consolelib.c" />
     <ClCompile Include="..\lua_hooklib.c" />
     <ClCompile Include="..\lua_hudlib.c" />
diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters
index d04007dd77d026e48e8480bf93a54b86d279b7c5..bdb029cf9437e8c960a84a111bbcbfaf5dc9b82b 100644
--- a/src/sdl/Srb2SDL-vc10.vcxproj.filters
+++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters
@@ -633,6 +633,9 @@
     <ClCompile Include="..\lua_baselib.c">
       <Filter>LUA</Filter>
     </ClCompile>
+    <ClCompile Include="..\lua_blockmaplib.c">
+      <Filter>LUA</Filter>
+    </ClCompile>
     <ClCompile Include="..\lua_consolelib.c">
       <Filter>LUA</Filter>
     </ClCompile>
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index 71baca510dabd7e21fd247721a10b050e2981f46..aa572e6e036fe41323c4cbcbc3802b5d13aa7c9d 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -33,14 +33,6 @@
 #pragma warning(default : 4214 4244)
 #endif
 
-#if SDL_VERSION_ATLEAST(1,3,0)
-#define SDLK_EQUALS SDLK_KP_EQUALSAS400
-#define SDLK_LMETA SDLK_LGUI
-#define SDLK_RMETA SDLK_RGUI
-#else
-#define HAVE_SDLMETAKEYS
-#endif
-
 #ifdef HAVE_TTF
 #include "i_ttf.h"
 #endif
@@ -189,14 +181,14 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
 			wasfullscreen = SDL_TRUE;
 			SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
 		}
-		else if (!fullscreen && wasfullscreen)
+		else if (wasfullscreen)
 		{
 			wasfullscreen = SDL_FALSE;
 			SDL_SetWindowFullscreen(window, 0);
 			SDL_SetWindowSize(window, width, height);
 			SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(1), SDL_WINDOWPOS_CENTERED_DISPLAY(1));
 		}
-		else if (!wasfullscreen)
+		else
 		{
 			// Reposition window only in windowed mode
 			SDL_SetWindowSize(window, width, height);
@@ -282,129 +274,70 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
 	}
 	switch (code)
 	{
-		case SDL_SCANCODE_F11: // F11 and F12 are
-			return KEY_F11;    // separated from the
-		case SDL_SCANCODE_F12: // rest of the function
-			return KEY_F12;    // keys
-
-		case SDL_SCANCODE_KP_0:
-			return KEY_KEYPAD0;
-		case SDL_SCANCODE_KP_1:
-			return KEY_KEYPAD1;
-		case SDL_SCANCODE_KP_2:
-			return KEY_KEYPAD2;
-		case SDL_SCANCODE_KP_3:
-			return KEY_KEYPAD3;
-		case SDL_SCANCODE_KP_4:
-			return KEY_KEYPAD4;
-		case SDL_SCANCODE_KP_5:
-			return KEY_KEYPAD5;
-		case SDL_SCANCODE_KP_6:
-			return KEY_KEYPAD6;
-		case SDL_SCANCODE_KP_7:
-			return KEY_KEYPAD7;
-		case SDL_SCANCODE_KP_8:
-			return KEY_KEYPAD8;
-		case SDL_SCANCODE_KP_9:
-			return KEY_KEYPAD9;
-
-		case SDL_SCANCODE_RETURN:
-			return KEY_ENTER;
-		case SDL_SCANCODE_ESCAPE:
-			return KEY_ESCAPE;
-		case SDL_SCANCODE_BACKSPACE:
-			return KEY_BACKSPACE;
-		case SDL_SCANCODE_TAB:
-			return KEY_TAB;
-		case SDL_SCANCODE_SPACE:
-			return KEY_SPACE;
-		case SDL_SCANCODE_MINUS:
-			return KEY_MINUS;
-		case SDL_SCANCODE_EQUALS:
-			return KEY_EQUALS;
-		case SDL_SCANCODE_LEFTBRACKET:
-			return '[';
-		case SDL_SCANCODE_RIGHTBRACKET:
-			return ']';
-		case SDL_SCANCODE_BACKSLASH:
-			return '\\';
-		case SDL_SCANCODE_NONUSHASH:
-			return '#';
-		case SDL_SCANCODE_SEMICOLON:
-			return ';';
-		case SDL_SCANCODE_APOSTROPHE:
-			return '\'';
-		case SDL_SCANCODE_GRAVE:
-			return '`';
-		case SDL_SCANCODE_COMMA:
-			return ',';
-		case SDL_SCANCODE_PERIOD:
-			return '.';
-		case SDL_SCANCODE_SLASH:
-			return '/';
-		case SDL_SCANCODE_CAPSLOCK:
-			return KEY_CAPSLOCK;
-		case SDL_SCANCODE_PRINTSCREEN:
-			return 0; // undefined?
-		case SDL_SCANCODE_SCROLLLOCK:
-			return KEY_SCROLLLOCK;
-		case SDL_SCANCODE_PAUSE:
-			return KEY_PAUSE;
-		case SDL_SCANCODE_INSERT:
-			return KEY_INS;
-		case SDL_SCANCODE_HOME:
-			return KEY_HOME;
-		case SDL_SCANCODE_PAGEUP:
-			return KEY_PGUP;
-		case SDL_SCANCODE_DELETE:
-			return KEY_DEL;
-		case SDL_SCANCODE_END:
-			return KEY_END;
-		case SDL_SCANCODE_PAGEDOWN:
-			return KEY_PGDN;
-		case SDL_SCANCODE_RIGHT:
-			return KEY_RIGHTARROW;
-		case SDL_SCANCODE_LEFT:
-			return KEY_LEFTARROW;
-		case SDL_SCANCODE_DOWN:
-			return KEY_DOWNARROW;
-		case SDL_SCANCODE_UP:
-			return KEY_UPARROW;
-		case SDL_SCANCODE_NUMLOCKCLEAR:
-			return KEY_NUMLOCK;
-		case SDL_SCANCODE_KP_DIVIDE:
-			return KEY_KPADSLASH;
-		case SDL_SCANCODE_KP_MULTIPLY:
-			return '*'; // undefined?
-		case SDL_SCANCODE_KP_MINUS:
-			return KEY_MINUSPAD;
-		case SDL_SCANCODE_KP_PLUS:
-			return KEY_PLUSPAD;
-		case SDL_SCANCODE_KP_ENTER:
-			return KEY_ENTER;
-		case SDL_SCANCODE_KP_PERIOD:
-			return KEY_KPADDEL;
-		case SDL_SCANCODE_NONUSBACKSLASH:
-			return '\\';
-
-		case SDL_SCANCODE_LSHIFT:
-			return KEY_LSHIFT;
-		case SDL_SCANCODE_RSHIFT:
-			return KEY_RSHIFT;
-		case SDL_SCANCODE_LCTRL:
-			return KEY_LCTRL;
-		case SDL_SCANCODE_RCTRL:
-			return KEY_RCTRL;
-		case SDL_SCANCODE_LALT:
-			return KEY_LALT;
-		case SDL_SCANCODE_RALT:
-			return KEY_RALT;
-		case SDL_SCANCODE_LGUI:
-			return KEY_LEFTWIN;
-		case SDL_SCANCODE_RGUI:
-			return KEY_RIGHTWIN;
-		default:
-			break;
+		// F11 and F12 are separated from the rest of the function keys
+		case SDL_SCANCODE_F11: return KEY_F11;
+		case SDL_SCANCODE_F12: return KEY_F12;
+
+		case SDL_SCANCODE_KP_0: return KEY_KEYPAD0;
+		case SDL_SCANCODE_KP_1: return KEY_KEYPAD1;
+		case SDL_SCANCODE_KP_2: return KEY_KEYPAD2;
+		case SDL_SCANCODE_KP_3: return KEY_KEYPAD3;
+		case SDL_SCANCODE_KP_4: return KEY_KEYPAD4;
+		case SDL_SCANCODE_KP_5: return KEY_KEYPAD5;
+		case SDL_SCANCODE_KP_6: return KEY_KEYPAD6;
+		case SDL_SCANCODE_KP_7: return KEY_KEYPAD7;
+		case SDL_SCANCODE_KP_8: return KEY_KEYPAD8;
+		case SDL_SCANCODE_KP_9: return KEY_KEYPAD9;
+
+		case SDL_SCANCODE_RETURN:         return KEY_ENTER;
+		case SDL_SCANCODE_ESCAPE:         return KEY_ESCAPE;
+		case SDL_SCANCODE_BACKSPACE:      return KEY_BACKSPACE;
+		case SDL_SCANCODE_TAB:            return KEY_TAB;
+		case SDL_SCANCODE_SPACE:          return KEY_SPACE;
+		case SDL_SCANCODE_MINUS:          return KEY_MINUS;
+		case SDL_SCANCODE_EQUALS:         return KEY_EQUALS;
+		case SDL_SCANCODE_LEFTBRACKET:    return '[';
+		case SDL_SCANCODE_RIGHTBRACKET:   return ']';
+		case SDL_SCANCODE_BACKSLASH:      return '\\';
+		case SDL_SCANCODE_NONUSHASH:      return '#';
+		case SDL_SCANCODE_SEMICOLON:      return ';';
+		case SDL_SCANCODE_APOSTROPHE:     return '\'';
+		case SDL_SCANCODE_GRAVE:          return '`';
+		case SDL_SCANCODE_COMMA:          return ',';
+		case SDL_SCANCODE_PERIOD:         return '.';
+		case SDL_SCANCODE_SLASH:          return '/';
+		case SDL_SCANCODE_CAPSLOCK:       return KEY_CAPSLOCK;
+		case SDL_SCANCODE_PRINTSCREEN:    return 0; // undefined?
+		case SDL_SCANCODE_SCROLLLOCK:     return KEY_SCROLLLOCK;
+		case SDL_SCANCODE_PAUSE:          return KEY_PAUSE;
+		case SDL_SCANCODE_INSERT:         return KEY_INS;
+		case SDL_SCANCODE_HOME:           return KEY_HOME;
+		case SDL_SCANCODE_PAGEUP:         return KEY_PGUP;
+		case SDL_SCANCODE_DELETE:         return KEY_DEL;
+		case SDL_SCANCODE_END:            return KEY_END;
+		case SDL_SCANCODE_PAGEDOWN:       return KEY_PGDN;
+		case SDL_SCANCODE_RIGHT:          return KEY_RIGHTARROW;
+		case SDL_SCANCODE_LEFT:           return KEY_LEFTARROW;
+		case SDL_SCANCODE_DOWN:           return KEY_DOWNARROW;
+		case SDL_SCANCODE_UP:             return KEY_UPARROW;
+		case SDL_SCANCODE_NUMLOCKCLEAR:   return KEY_NUMLOCK;
+		case SDL_SCANCODE_KP_DIVIDE:      return KEY_KPADSLASH;
+		case SDL_SCANCODE_KP_MULTIPLY:    return '*'; // undefined?
+		case SDL_SCANCODE_KP_MINUS:       return KEY_MINUSPAD;
+		case SDL_SCANCODE_KP_PLUS:        return KEY_PLUSPAD;
+		case SDL_SCANCODE_KP_ENTER:       return KEY_ENTER;
+		case SDL_SCANCODE_KP_PERIOD:      return KEY_KPADDEL;
+		case SDL_SCANCODE_NONUSBACKSLASH: return '\\';
+
+		case SDL_SCANCODE_LSHIFT: return KEY_LSHIFT;
+		case SDL_SCANCODE_RSHIFT: return KEY_RSHIFT;
+		case SDL_SCANCODE_LCTRL:  return KEY_LCTRL;
+		case SDL_SCANCODE_RCTRL:  return KEY_RCTRL;
+		case SDL_SCANCODE_LALT:   return KEY_LALT;
+		case SDL_SCANCODE_RALT:   return KEY_RALT;
+		case SDL_SCANCODE_LGUI:   return KEY_LEFTWIN;
+		case SDL_SCANCODE_RGUI:   return KEY_RIGHTWIN;
+		default:                  break;
 	}
 #ifdef HWRENDER
 	DBG_Printf("Unknown incoming scancode: %d, represented %c\n",
@@ -432,15 +365,10 @@ static void VID_Command_NumModes_f (void)
 	CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), VID_NumModes());
 }
 
+// SDL2 doesn't have SDL_GetVideoSurface or a lot of the SDL_Surface flags that SDL 1.2 had
 static void SurfaceInfo(const SDL_Surface *infoSurface, const char *SurfaceText)
 {
-#if 1
-	(void)infoSurface;
-	(void)SurfaceText;
-	SDL2STUB();
-#else
 	INT32 vfBPP;
-	const SDL_Surface *VidSur = SDL_GetVideoSurface();
 
 	if (!infoSurface)
 		return;
@@ -453,49 +381,12 @@ static void SurfaceInfo(const SDL_Surface *infoSurface, const char *SurfaceText)
 	CONS_Printf("\x82" "%s\n", SurfaceText);
 	CONS_Printf(M_GetText(" %ix%i at %i bit color\n"), infoSurface->w, infoSurface->h, vfBPP);
 
-	if (infoSurface->flags&SDL_HWSURFACE)
-		CONS_Printf("%s", M_GetText(" Stored in video memory\n"));
-	else if (infoSurface->flags&SDL_OPENGL)
-		CONS_Printf("%s", M_GetText(" Stored in an OpenGL context\n"));
-	else if (infoSurface->flags&SDL_PREALLOC)
+	if (infoSurface->flags&SDL_PREALLOC)
 		CONS_Printf("%s", M_GetText(" Uses preallocated memory\n"));
 	else
 		CONS_Printf("%s", M_GetText(" Stored in system memory\n"));
-
-	if (infoSurface->flags&SDL_ASYNCBLIT)
-		CONS_Printf("%s", M_GetText(" Uses asynchronous blits if possible\n"));
-	else
-		CONS_Printf("%s", M_GetText(" Uses synchronous blits if possible\n"));
-
-	if (infoSurface->flags&SDL_ANYFORMAT)
-		CONS_Printf("%s", M_GetText(" Allows any pixel-format\n"));
-
-	if (infoSurface->flags&SDL_HWPALETTE)
-		CONS_Printf("%s", M_GetText(" Has exclusive palette access\n"));
-	else if (VidSur == infoSurface)
-		CONS_Printf("%s", M_GetText(" Has nonexclusive palette access\n"));
-
-	if (infoSurface->flags&SDL_DOUBLEBUF)
-		CONS_Printf("%s", M_GetText(" Double buffered\n"));
-	else if (VidSur == infoSurface)
-		CONS_Printf("%s", M_GetText(" No hardware flipping\n"));
-
-	if (infoSurface->flags&SDL_FULLSCREEN)
-		CONS_Printf("%s", M_GetText(" Full screen\n"));
-	else if (infoSurface->flags&SDL_RESIZABLE)
-		CONS_Printf("%s", M_GetText(" Resizable window\n"));
-	else if (VidSur == infoSurface)
-		CONS_Printf("%s", M_GetText(" Nonresizable window\n"));
-
-	if (infoSurface->flags&SDL_HWACCEL)
-		CONS_Printf("%s", M_GetText(" Uses hardware acceleration blit\n"));
-	if (infoSurface->flags&SDL_SRCCOLORKEY)
-		CONS_Printf("%s", M_GetText(" Use colorkey blitting\n"));
 	if (infoSurface->flags&SDL_RLEACCEL)
 		CONS_Printf("%s", M_GetText(" Colorkey RLE acceleration blit\n"));
-	if (infoSurface->flags&SDL_SRCALPHA)
-		CONS_Printf("%s", M_GetText(" Use alpha blending acceleration blit\n"));
-#endif
 }
 
 static void VID_Command_Info_f (void)
@@ -579,23 +470,6 @@ static void VID_Command_Mode_f (void)
 		setmodeneeded = modenum+1; // request vid mode change
 }
 
-#if 0
-#if defined(RPC_NO_WINDOWS_H)
-static VOID MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
-	UNREFERENCED_PARAMETER(hWnd);
-	UNREFERENCED_PARAMETER(message);
-	UNREFERENCED_PARAMETER(wParam);
-	switch (message)
-	{
-		case WM_SETTEXT:
-			COM_BufAddText((LPCSTR)lParam);
-			break;
-	}
-}
-#endif
-#endif
-
 static inline void SDLJoyRemap(event_t *event)
 {
 	(void)event;
@@ -954,218 +828,6 @@ void I_GetEvent(void)
 	// In order to make wheels act like buttons, we have to set their state to Up.
 	// This is because wheel messages don't have an up/down state.
 	gamekeydown[KEY_MOUSEWHEELDOWN] = gamekeydown[KEY_MOUSEWHEELUP] = 0;
-
-#if 0
-	SDL_Event inputEvent;
-	static SDL_bool sdlquit = SDL_FALSE; //Alam: once, just once
-	event_t event;
-
-	if (!graphics_started)
-		return;
-
-	memset(&inputEvent, 0x00, sizeof(inputEvent));
-	while (SDL_PollEvent(&inputEvent))
-	{
-		memset(&event,0x00,sizeof (event_t));
-		switch (inputEvent.type)
-		{
-			case SDL_ACTIVEEVENT:
-				if (inputEvent.active.state  & (SDL_APPACTIVE|SDL_APPINPUTFOCUS))
-				{
-					// pause music when alt-tab
-					if (inputEvent.active.gain /*&& !paused */)
-					{
-						static SDL_bool firsttimeonmouse = SDL_TRUE;
-						if (!firsttimeonmouse)
-						{
-							if (cv_usemouse.value) I_StartupMouse();
-						}
-						else firsttimeonmouse = SDL_FALSE;
-						//if (!netgame && !con_destlines) paused = false;
-						if (gamestate == GS_LEVEL)
-							if (!paused) I_ResumeSong(0); //resume it
-					}
-					else /*if (!paused)*/
-					{
-						if (!disable_mouse)
-							SDLforceUngrabMouse();
-						if (!netgame && gamestate == GS_LEVEL) paused = true;
-						memset(gamekeydown, 0, NUMKEYS);
-						//S_PauseSound();
-						if (gamestate == GS_LEVEL)
-							I_PauseSong(0); //pause it
-					}
-				}
-				if (MOUSE_MENU)
-				{
-					SDLdoUngrabMouse();
-					break;
-				}
-				if ((SDL_APPMOUSEFOCUS&inputEvent.active.state) && USE_MOUSEINPUT && inputEvent.active.gain)
-					HalfWarpMouse(realwidth, realheight);
-				break;
-			case SDL_KEYDOWN:
-			case SDL_KEYUP:
-				/// \todo inputEvent.key.which?
-				if (inputEvent.type == SDL_KEYUP)
-					event.type = ev_keyup;
-				else if (inputEvent.type == SDL_KEYDOWN)
-					event.type = ev_keydown;
-				else break;
-				event.data1 = SDLatekey(inputEvent.key.keysym.sym);
-				if (event.data1) D_PostEvent(&event);
-				break;
-			case SDL_MOUSEMOTION:
-				/// \todo inputEvent.motion.which
-				if (MOUSE_MENU)
-				{
-					SDLdoUngrabMouse();
-					break;
-				}
-				//if (USE_MOUSEINPUT) TODO SDL2 stub
-				{
-					// If the event is from warping the pointer back to middle
-					// of the screen then ignore it.
-					if ((inputEvent.motion.x == realwidth/2) &&
-					    (inputEvent.motion.y == realheight/2))
-					{
-						break;
-					}
-					else
-					{
-						event.data2 = +inputEvent.motion.xrel;
-						event.data3 = -inputEvent.motion.yrel;
-					}
-					event.type = ev_mouse;
-					D_PostEvent(&event);
-					// Warp the pointer back to the middle of the window
-					//  or we cannot move any further if it's at a border.
-					if ((inputEvent.motion.x < (realwidth/2 )-(realwidth/4 )) ||
-					    (inputEvent.motion.y < (realheight/2)-(realheight/4)) ||
-					    (inputEvent.motion.x > (realwidth/2 )+(realwidth/4 )) ||
-					    (inputEvent.motion.y > (realheight/2)+(realheight/4) ) )
-					{
-						//if (SDL_GRAB_ON == SDL_WM_GrabInput(SDL_GRAB_QUERY) || !mousegrabok)
-							HalfWarpMouse(realwidth, realheight);
-					}
-				}
-				break;
-			case SDL_MOUSEBUTTONDOWN:
-			case SDL_MOUSEBUTTONUP:
-				/// \todo inputEvent.button.which
-				if (USE_MOUSEINPUT)
-				{
-					if (inputEvent.type == SDL_MOUSEBUTTONUP)
-						event.type = ev_keyup;
-					else if (inputEvent.type == SDL_MOUSEBUTTONDOWN)
-						event.type = ev_keydown;
-					else break;
-					if (inputEvent.button.button==SDL_BUTTON_WHEELUP || inputEvent.button.button==SDL_BUTTON_WHEELDOWN)
-					{
-						if (inputEvent.type == SDL_MOUSEBUTTONUP)
-							event.data1 = 0; //Alam: dumb! this could be a real button with some mice
-						else
-							event.data1 = KEY_MOUSEWHEELUP + inputEvent.button.button - SDL_BUTTON_WHEELUP;
-					}
-					else if (inputEvent.button.button == SDL_BUTTON_MIDDLE)
-						event.data1 = KEY_MOUSE1+2;
-					else if (inputEvent.button.button == SDL_BUTTON_RIGHT)
-						event.data1 = KEY_MOUSE1+1;
-					else if (inputEvent.button.button <= MOUSEBUTTONS)
-						event.data1 = KEY_MOUSE1 + inputEvent.button.button - SDL_BUTTON_LEFT;
-					if (event.data1) D_PostEvent(&event);
-				}
-				break;
-			case SDL_JOYAXISMOTION:
-				inputEvent.jaxis.which++;
-				inputEvent.jaxis.axis++;
-				event.data1 = event.data2 = event.data3 = INT32_MAX;
-				if (cv_usejoystick.value == inputEvent.jaxis.which)
-				{
-					event.type = ev_joystick;
-				}
-				else if (cv_usejoystick.value == inputEvent.jaxis.which)
-				{
-					event.type = ev_joystick2;
-				}
-				else break;
-				//axis
-				if (inputEvent.jaxis.axis > JOYAXISSET*2)
-					break;
-				//vaule
-				if (inputEvent.jaxis.axis%2)
-				{
-					event.data1 = inputEvent.jaxis.axis / 2;
-					event.data2 = SDLJoyAxis(inputEvent.jaxis.value, event.type);
-				}
-				else
-				{
-					inputEvent.jaxis.axis--;
-					event.data1 = inputEvent.jaxis.axis / 2;
-					event.data3 = SDLJoyAxis(inputEvent.jaxis.value, event.type);
-				}
-				D_PostEvent(&event);
-				break;
-			case SDL_JOYBALLMOTION:
-			case SDL_JOYHATMOTION:
-				break; //NONE
-			case SDL_JOYBUTTONDOWN:
-			case SDL_JOYBUTTONUP:
-				inputEvent.jbutton.which++;
-				if (cv_usejoystick.value == inputEvent.jbutton.which)
-					event.data1 = KEY_JOY1;
-				else if (cv_usejoystick.value == inputEvent.jbutton.which)
-					event.data1 = KEY_2JOY1;
-				else break;
-				if (inputEvent.type == SDL_JOYBUTTONUP)
-					event.type = ev_keyup;
-				else if (inputEvent.type == SDL_JOYBUTTONDOWN)
-					event.type = ev_keydown;
-				else break;
-				if (inputEvent.jbutton.button < JOYBUTTONS)
-					event.data1 += inputEvent.jbutton.button;
-				else
-					break;
-				SDLJoyRemap(&event);
-				if (event.type != ev_console) D_PostEvent(&event);
-				break;
-			case SDL_QUIT:
-				if (!sdlquit)
-				{
-					sdlquit = SDL_TRUE;
-					M_QuitResponse('y');
-				}
-				break;
-#if defined(RPC_NO_WINDOWS_H)
-			case SDL_SYSWMEVENT:
-				MainWndproc(inputEvent.syswm.msg->hwnd,
-					inputEvent.syswm.msg->msg,
-					inputEvent.syswm.msg->wParam,
-					inputEvent.syswm.msg->lParam);
-				break;
-#endif
-			case SDL_VIDEORESIZE:
-				if (gamestate == GS_LEVEL || gamestate == GS_TITLESCREEN || gamestate == GS_EVALUATION)
-				    setmodeneeded = VID_GetModeForSize(inputEvent.resize.w,inputEvent.resize.h)+1;
-				if (render_soft == rendermode)
-				{
-					SDLSetMode(realwidth, realheight, vid.bpp*8, surfaceFlagsW);
-					if (vidSurface) SDL_SetColors(vidSurface, localPalette, 0, 256);
-				}
-				else
-					SDLSetMode(realwidth, realheight, vid.bpp*8, surfaceFlagsW);
-				if (!vidSurface)
-					I_Error("Could not reset vidmode: %s\n",SDL_GetError());
-				break;
-			case SDL_VIDEOEXPOSE:
-				exposevideo = SDL_TRUE;
-				break;
-			default:
-				break;
-		}
-	}
-	//reset wheel like in win32, I don't understand it but works
-#endif
 }
 
 void I_StartupMouse(void)
@@ -1494,11 +1156,6 @@ void VID_PrepareModeList(void)
 #endif
 }
 
-static inline void SDLESSet(void)
-{
-	SDL2STUB();
-}
-
 INT32 VID_SetMode(INT32 modeNum)
 {
 	SDLdoUngrabMouse();
@@ -1550,6 +1207,12 @@ INT32 VID_SetMode(INT32 modeNum)
 static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 {
 	int flags = 0;
+
+	if (rendermode == render_none) // dedicated
+	{
+		return SDL_TRUE; // Monster Iestyn -- not sure if it really matters what we return here tbh
+	}
+
 	if (window != NULL)
 	{
 		return SDL_FALSE;
@@ -1568,38 +1231,43 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen)
 #ifdef HWRENDER
 	if (rendermode == render_opengl)
 	{
-		window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
-				realwidth, realheight, flags | SDL_WINDOW_OPENGL);
-		if (window != NULL)
+		flags |= SDL_WINDOW_OPENGL;
+	}
+#endif
+
+	// Create a window
+	window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+			realwidth, realheight, flags);
+
+	if (window == NULL)
+	{
+		CONS_Printf(M_GetText("Couldn't create window: %s\n"), SDL_GetError());
+		return SDL_FALSE;
+	}
+
+	// Renderer-specific stuff
+#ifdef HWRENDER
+	if (rendermode == render_opengl)
+	{
+		sdlglcontext = SDL_GL_CreateContext(window);
+		if (sdlglcontext == NULL)
 		{
-			sdlglcontext = SDL_GL_CreateContext(window);
-			if (sdlglcontext == NULL)
-			{
-				SDL_DestroyWindow(window);
-				I_Error("Failed to create a GL context: %s\n", SDL_GetError());
-			}
-			else
-			{
-				SDL_GL_MakeCurrent(window, sdlglcontext);
-			}
+			SDL_DestroyWindow(window);
+			I_Error("Failed to create a GL context: %s\n", SDL_GetError());
 		}
-		else return SDL_FALSE;
+		SDL_GL_MakeCurrent(window, sdlglcontext);
 	}
+	else
 #endif
 	if (rendermode == render_soft)
 	{
-		window = SDL_CreateWindow("SRB2 "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
-				realwidth, realheight, flags);
-		if (window != NULL)
+		renderer = SDL_CreateRenderer(window, -1, (usesdl2soft ? SDL_RENDERER_SOFTWARE : 0) | (cv_vidwait.value && !usesdl2soft ? SDL_RENDERER_PRESENTVSYNC : 0));
+		if (renderer == NULL)
 		{
-			renderer = SDL_CreateRenderer(window, -1, (usesdl2soft ? SDL_RENDERER_SOFTWARE : 0) | (cv_vidwait.value && !usesdl2soft ? SDL_RENDERER_PRESENTVSYNC : 0));
-			if (renderer != NULL)
-			{
-				SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT);
-			}
-			else return SDL_FALSE;
+			CONS_Printf(M_GetText("Couldn't create rendering context: %s\n"), SDL_GetError());
+			return SDL_FALSE;
 		}
-		else return SDL_FALSE;
+		SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT);
 	}
 
 	return SDL_TRUE;
@@ -1620,7 +1288,7 @@ static void Impl_SetWindowIcon(void)
 	{
 		return;
 	}
-	SDL2STUB();
+	//SDL2STUB(); // Monster Iestyn: why is this stubbed?
 	SDL_SetWindowIcon(window, icoSurface);
 }
 
@@ -1718,7 +1386,6 @@ void I_StartupGraphics(void)
 	borderlesswindow = M_CheckParm("-borderless");
 
 	//SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2);
-	SDLESSet();
 	VID_Command_ModeList_f();
 #ifdef HWRENDER
 	if (M_CheckParm("-opengl") || rendermode == render_opengl)
diff --git a/src/sounds.c b/src/sounds.c
index 75ee1358c45775865d029bbe5697e4bc8ed180f0..b551b73b5c8ed7762ba9c26fa08b2bbb0b7a0bdd 100644
--- a/src/sounds.c
+++ b/src/sounds.c
@@ -165,8 +165,12 @@ sfxinfo_t S_sfx[NUMSFX] =
   {"rail1",  false,  64,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
   {"rail2",  false,  64,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
   {"rlaunc", false,  64,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
-  {"shield", false,  60,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
-  {"shldls", false,  64,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
+  {"shield", false,  60,  0, -1, NULL, 0,        -1,  -1, LUMPERROR}, // generic GET!
+  {"wirlsg", false,  60,  0, -1, NULL, 0,        -1,  -1, LUMPERROR}, // Whirlwind GET!
+  {"forcsg", false,  60,  0, -1, NULL, 0,        -1,  -1, LUMPERROR}, // Force GET!
+  {"elemsg", false,  60,  0, -1, NULL, 0,        -1,  -1, LUMPERROR}, // Elemental GET!
+  {"armasg", false,  60,  0, -1, NULL, 0,        -1,  -1, LUMPERROR}, // Armaggeddon GET!
+  {"shldls", false,  64,  0, -1, NULL, 0,        -1,  -1, LUMPERROR}, // You LOSE!
   {"spdpad", false, 127,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
   {"spkdth", false, 127,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
   {"spring", false, 112,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
@@ -183,6 +187,7 @@ sfxinfo_t S_sfx[NUMSFX] =
   {"wdjump", false,  60,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
   {"mswarp", false,  60, 16, -1, NULL, 0,        -1,  -1, LUMPERROR},
   {"mspogo", false,  60,  8, -1, NULL, 0,        -1,  -1, LUMPERROR},
+  {"boingf", false,  60,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
 
   // Menu, interface
   {"chchng", false, 120,  0, -1, NULL, 0,        -1,  -1, LUMPERROR},
diff --git a/src/sounds.h b/src/sounds.h
index 532c61da6ed590d1a23b68a081e93c5207b10e57..42fa4c3089d30274f0f4b19dd88dad1bd515618b 100644
--- a/src/sounds.h
+++ b/src/sounds.h
@@ -229,6 +229,10 @@ typedef enum
 	sfx_rail2,
 	sfx_rlaunc,
 	sfx_shield,
+	sfx_wirlsg,
+	sfx_forcsg,
+	sfx_elemsg,
+	sfx_armasg,
 	sfx_shldls,
 	sfx_spdpad,
 	sfx_spkdth,
@@ -246,6 +250,7 @@ typedef enum
 	sfx_wdjump,
 	sfx_mswarp,
 	sfx_mspogo,
+	sfx_boingf,
 
 	// Menu, interface
 	sfx_chchng,
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 9a7f649865f1a094cb07a5a6b2d415ae913a6182..658c2c6d602354e1951ae50511361ff63cd12bdc 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -99,6 +99,9 @@ static patch_t *ringshield;
 static patch_t *watershield;
 static patch_t *bombshield;
 static patch_t *pityshield;
+static patch_t *flameshield;
+static patch_t *bubbleshield;
+static patch_t *thundershield;
 static patch_t *invincibility;
 static patch_t *sneakers;
 static patch_t *gravboots;
@@ -294,6 +297,9 @@ void ST_LoadGraphics(void)
 	watershield = W_CachePatchName("TVELC0", PU_HUDGFX);
 	bombshield = W_CachePatchName("TVARC0", PU_HUDGFX);
 	pityshield = W_CachePatchName("TVPIC0", PU_HUDGFX);
+	flameshield = W_CachePatchName("TVFLC0", PU_HUDGFX);
+	bubbleshield = W_CachePatchName("TVBBC0", PU_HUDGFX);
+	thundershield = W_CachePatchName("TVZPC0", PU_HUDGFX);
 	invincibility = W_CachePatchName("TVIVC0", PU_HUDGFX);
 	sneakers = W_CachePatchName("TVSSC0", PU_HUDGFX);
 	gravboots = W_CachePatchName("TVGVC0", PU_HUDGFX);
@@ -576,12 +582,13 @@ static void ST_drawDebugInfo(void)
 		V_DrawRightAlignedString(320, height - 80,  V_MONOSPACE, va("AIR: %4d, %3d", stplyr->powers[pw_underwater], stplyr->powers[pw_spacetime]));
 
 		// Flags
-		V_DrawRightAlignedString(304-74, height - 72, V_MONOSPACE, "PF:");
-		V_DrawString(304-72,             height - 72, (stplyr->jumping) ? V_GREENMAP : V_REDMAP, "JM");
-		V_DrawString(304-54,             height - 72, (stplyr->pflags & PF_JUMPED) ? V_GREENMAP : V_REDMAP, "JD");
-		V_DrawString(304-36,             height - 72, (stplyr->pflags & PF_SPINNING) ? V_GREENMAP : V_REDMAP, "SP");
-		V_DrawString(304-18,             height - 72, (stplyr->pflags & PF_STARTDASH) ? V_GREENMAP : V_REDMAP, "ST");
-		V_DrawString(304,                height - 72, (stplyr->pflags & PF_THOKKED) ? V_GREENMAP : V_REDMAP, "TH");
+		V_DrawRightAlignedString(304-92, height - 72, V_MONOSPACE, "PF:");
+		V_DrawString(304-90,             height - 72, (stplyr->jumping) ? V_GREENMAP : V_REDMAP, "JM");
+		V_DrawString(304-72,             height - 72, (stplyr->pflags & PF_JUMPED) ? V_GREENMAP : V_REDMAP, "JD");
+		V_DrawString(304-54,             height - 72, (stplyr->pflags & PF_SPINNING) ? V_GREENMAP : V_REDMAP, "SP");
+		V_DrawString(304-36,             height - 72, (stplyr->pflags & PF_STARTDASH) ? V_GREENMAP : V_REDMAP, "ST");
+		V_DrawString(304-18,                height - 72, (stplyr->pflags & PF_THOKKED) ? V_GREENMAP : V_REDMAP, "TH");
+		V_DrawString(304,                height - 72, (stplyr->pflags & PF_SHIELDABILITY) ? V_GREENMAP : V_REDMAP, "SH");
 
 		V_DrawRightAlignedString(320, height - 64, V_MONOSPACE, va("CEILZ: %6d", stplyr->mo->ceilingz>>FRACBITS));
 		V_DrawRightAlignedString(320, height - 56, V_MONOSPACE, va("FLOORZ: %6d", stplyr->mo->floorz>>FRACBITS));
@@ -806,18 +813,21 @@ static void ST_drawFirstPersonHUD(void)
 		return;
 
 	// Graue 06-18-2004: no V_NOSCALESTART, no SCX, no SCY, snap to right
-	if (player->powers[pw_shield] & SH_FORCE)
+	if ((player->powers[pw_shield] & SH_NOSTACK & ~SH_FORCEHP) == SH_FORCE)
 	{
-		if ((player->powers[pw_shield] & 0xFF) > 0 || leveltime & 1)
+		if ((player->powers[pw_shield] & SH_FORCEHP) > 0 || leveltime & 1)
 			p = forceshield;
 	}
 	else switch (player->powers[pw_shield] & SH_NOSTACK)
 	{
-	case SH_JUMP:      p = jumpshield;  break;
-	case SH_ELEMENTAL: p = watershield; break;
-	case SH_BOMB:      p = bombshield;  break;
-	case SH_ATTRACT:   p = ringshield;  break;
-	case SH_PITY:      p = pityshield;  break;
+	case SH_WHIRLWIND:   p = jumpshield;    break;
+	case SH_ELEMENTAL:   p = watershield;   break;
+	case SH_ARMAGEDDON:  p = bombshield;    break;
+	case SH_ATTRACT:     p = ringshield;    break;
+	case SH_PITY:        p = pityshield;    break;
+	case SH_FLAMEAURA:   p = flameshield;   break;
+	case SH_BUBBLEWRAP:  p = bubbleshield;  break;
+	case SH_THUNDERCOIN: p = thundershield; break;
 	default: break;
 	}
 
diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg
index f309f7db11d158fb878eaa8a4615bed1b9dbf6b3..99b8bc9b2ca4b6949944429546b3e379808e804a 100644
--- a/src/win32/Makefile.cfg
+++ b/src/win32/Makefile.cfg
@@ -85,13 +85,21 @@ endif
 	OBJS=$(OBJDIR)/dx_error.o $(OBJDIR)/fabdxlib.o $(OBJDIR)/win_vid.o $(OBJDIR)/win_dll.o
 endif
 
+
+ZLIB_CFLAGS?=-I../libs/zlib
+ifdef MINGW64
+ZLIB_LDFLAGS?=-L../libs/zlib/win32 -lz64
+else
+ZLIB_LDFLAGS?=-L../libs/zlib/win32 -lz32
+endif
+
 ifndef NOPNG
 ifndef PNG_CONFIG
-	PNG_CFLAGS?=-I../libs/libpng-src -I../libs/zlib
+	PNG_CFLAGS?=-I../libs/libpng-src
 ifdef MINGW64
-	PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng64 -L../libs/zlib/win32 -lz64
+	PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng64
 else
-	PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng32 -L../libs/zlib/win32 -lz32
+	PNG_LDFLAGS?=-L../libs/libpng-src/projects -lpng32
 endif #MINGW64
 endif #PNG_CONFIG
 endif #NOPNG
diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj
index 064f75d7d06cdee1aa62d70dda03e9e28d53e6f2..95f9c85f94aeb1e6b62b2ac9447402a01c811840 100644
--- a/src/win32/Srb2win-vc10.vcxproj
+++ b/src/win32/Srb2win-vc10.vcxproj
@@ -131,6 +131,7 @@
     </ClCompile>
     <ClCompile Include="..\i_tcp.c" />
     <ClCompile Include="..\lua_baselib.c" />
+    <ClCompile Include="..\lua_blockmaplib.c" />
     <ClCompile Include="..\lua_consolelib.c" />
     <ClCompile Include="..\lua_hooklib.c" />
     <ClCompile Include="..\lua_hudlib.c" />
diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters
index b2647ea1c21518389b7061276f6464d05998721b..cfd46f1f81d260f7f9645759f7601626c6a64dad 100644
--- a/src/win32/Srb2win-vc10.vcxproj.filters
+++ b/src/win32/Srb2win-vc10.vcxproj.filters
@@ -225,6 +225,9 @@
     <ClCompile Include="..\lua_baselib.c">
       <Filter>LUA</Filter>
     </ClCompile>
+    <ClCompile Include="..\lua_blockmaplib.c">
+      <Filter>LUA</Filter>
+    </ClCompile>
     <ClCompile Include="..\lua_consolelib.c">
       <Filter>LUA</Filter>
     </ClCompile>
diff --git a/src/win32/win_dbg.c b/src/win32/win_dbg.c
index 23416af1b26672c71232c57cc057467d481f51a2..fe6ebb04ae6545bce5d2c89abf8c8f0a4f882f71 100644
--- a/src/win32/win_dbg.c
+++ b/src/win32/win_dbg.c
@@ -20,7 +20,9 @@
 
 
 #include <tchar.h>
+#ifndef HAVE_SDL
 #include "win_main.h"
+#endif
 #include "../doomdef.h" //just for VERSION
 #include "win_dbg.h"
 #include "../m_argv.h" //print the parameter in the log