diff --git a/.gitattributes b/.gitattributes
index 777bf189aefad727b647f5024a447734739e8358..ef775b91288dbb8043d94d61f54796491938489e 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -29,4 +29,6 @@
 /libs/zlib/nintendods/README -whitespace
 /libs/zlib/watcom/watcom_f.mak -crlf -whitespace
 /libs/zlib/watcom/watcom_l.mak -crlf -whitespace
+#Appveyor
+/appveyor.yml -crlf -whitespace
 # Other
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 346fd8db034e245b6db2cd55738ef5bb79383803..b8fe0ab5731f219e3661c9f8316c873986ec98d5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,6 +3,10 @@ project(SRB2
 	VERSION 2.1.14
 	LANGUAGES C)
 
+if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})
+	message(FATAL_ERROR "In-source builds will bring you a world of pain. Please make a separate directory to invoke CMake from.")
+endif()
+
 # Set up CMAKE path
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
 
@@ -44,7 +48,7 @@ macro(copy_files_to_build_dir target dlllist_var)
 			add_custom_command(TARGET ${target} POST_BUILD
 				COMMAND ${CMAKE_COMMAND} -E copy_if_different
 				${dlllist_item}
-				${CMAKE_CURRENT_BINARY_DIR}/\$\(Configuration\)/${dllname}
+				$<TARGET_FILE_DIR:${target}>/${dllname}
 			)
 		endforeach()
 	endif()
@@ -99,7 +103,8 @@ set(GIT_EXECUTABLE "git" CACHE FILEPATH "Path to git binary")
 include(GitUtilities)
 git_describe(SRB2_GIT_DESCRIBE "${CMAKE_SOURCE_DIR}")
 git_current_branch(SRB2_GIT_BRANCH "${CMAKE_SOURCE_DIR}")
-set(SRB2_COMP_REVISION "${SRB2_GIT_DESCRIBE}-<${SRB2_GIT_BRANCH}>")
+set(SRB2_COMP_BRANCH "${SRB2_GIT_BRANCH}")
+set(SRB2_COMP_REVISION "${SRB2_GIT_DESCRIBE}")
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/src/config.h)
 
 ##### PACKAGE CONFIGURATION #####
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4edcd7a7f422f45b84159f2a07dc8248e552b12a
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,71 @@
+version: 2.1.14.{branch}-{build}
+os: MinGW
+
+environment:
+ CC: i686-w64-mingw32-gcc
+ WINDRES: windres
+ MINGW_SDK: c:\msys64\mingw32
+ SDL2_URL: http://libsdl.org/release/SDL2-devel-2.0.4-mingw.tar.gz
+ SDL2_ARCHIVE: SDL2-devel-2.0.4-mingw.tar
+ SDL2_MOVE: SDL2-2.0.4\i686-w64-mingw32
+ SDL2_MIXER_URL: https://www.libsdl.org/projects/SDL_mixer/release/SDL2_mixer-devel-2.0.1-mingw.tar.gz
+ SDL2_MIXER_ARCHIVE: SDL2_mixer-devel-2.0.1-mingw.tar
+ SDL2_MIXER_MOVE: SDL2_mixer-2.0.1\i686-w64-mingw32
+
+cache:
+- SDL2-devel-2.0.4-mingw.tar.gz
+- SDL2_mixer-devel-2.0.1-mingw.tar.gz
+
+install:
+#Download SDL2
+- if not exist "%SDL2_ARCHIVE%.gz" appveyor DownloadFile "%SDL2_URL%" -FileName "%SDL2_ARCHIVE%.gz"
+- 7z x -y "%SDL2_ARCHIVE%.gz" -o%TMP% >null
+- 7z x -y "%TMP%\%SDL2_ARCHIVE%" -o%TMP% >null
+- robocopy /S /xx /ns /nc /nfl /ndl /np /njh /njs %TMP%\%SDL2_MOVE% %MINGW_SDK% || exit 0
+- ps: (Get-Content ([System.Environment]::ExpandEnvironmentVariables("%TMP%\%SDL2_MOVE%\bin\sdl2-config")))                  | ForEach-Object { $_ -replace "/usr/local/cross-tools/i686-w64-mingw32", ([System.Environment]::ExpandEnvironmentVariables("%MINGW_SDK%")) } | Set-Content ([System.Environment]::ExpandEnvironmentVariables("%MINGW_SDK%\bin\sdl2-config"))
+- ps: (Get-Content ([System.Environment]::ExpandEnvironmentVariables("%TMP%\%SDL2_MOVE%\lib\cmake\SDL2\sdl2-config.cmake"))) | ForEach-Object { $_ -replace "/usr/local/cross-tools/i686-w64-mingw32", ([System.Environment]::ExpandEnvironmentVariables("%MINGW_SDK%")) } | Set-Content ([System.Environment]::ExpandEnvironmentVariables("%MINGW_SDK%\lib\cmake\SDL2\sdl2-config.cmake"))
+- ps: (Get-Content ([System.Environment]::ExpandEnvironmentVariables("%TMP%\%SDL2_MOVE%\lib\pkgconfig\sdl2.pc")))            | ForEach-Object { $_ -replace "/usr/local/cross-tools/i686-w64-mingw32", ([System.Environment]::ExpandEnvironmentVariables("%MINGW_SDK%")) } | Set-Content ([System.Environment]::ExpandEnvironmentVariables("%MINGW_SDK%\lib\pkgconfig\sdl2.pc"))
+#Download SDL2_Mixer
+- if not exist "%SDL2_MIXER_ARCHIVE%.gz" appveyor DownloadFile "%SDL2_MIXER_URL%" -FileName "%SDL2_MIXER_ARCHIVE%.gz"
+- 7z x -y "%SDL2_MIXER_ARCHIVE%.gz" -o%TMP% >null
+- 7z x -y "%TMP%\%SDL2_MIXER_ARCHIVE%" -o%TMP% >null
+- robocopy /S /xx /ns /nc /nfl /ndl /np /njh /njs %TMP%\%SDL2_MIXER_MOVE% %MINGW_SDK% || exit 0
+- ps: (Get-Content ([System.Environment]::ExpandEnvironmentVariables("%TMP%\%SDL2_MIXER_MOVE%\lib\pkgconfig\SDL2_mixer.pc")))| ForEach-Object { $_ -replace "/usr/local/cross-tools/i686-w64-mingw32", ([System.Environment]::ExpandEnvironmentVariables("%MINGW_SDK%")) } | Set-Content ([System.Environment]::ExpandEnvironmentVariables("%MINGW_SDK%\lib\pkgconfig\SDL2_mixer.pc"))
+
+before_build:
+- set SDL_PKGCONFIG=%MINGW_SDK%\lib\pkgconfig\sdl2.pc
+- set Path=%MINGW_SDK%\bin;%Path%
+- i686-w64-mingw32-gcc --version
+- mingw32-make --version
+- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 NOASM=1 NOUPX=1 GCC53=1
+
+build_script:
+- cmd: mingw32-make.exe %SRB2_MFLAGS% SDL=1 clean
+- cmd: mingw32-make.exe %SRB2_MFLAGS% SDL=1 ERRORMODE=1
+
+after_build:
+- cmd: git rev-parse --short %APPVEYOR_REPO_COMMIT%>%TMP%/gitshort.txt
+- cmd: set /P GITSHORT=<%TMP%/gitshort.txt
+- set BUILD_ARCHIVE=%APPVEYOR_REPO_BRANCH%-%GITSHORT%.7z
+- cmd: 7z a %BUILD_ARCHIVE% bin\Mingw\Release -xr!.gitignore
+- appveyor PushArtifact %BUILD_ARCHIVE%
+
+test: off
+
+deploy:
+  - provider: FTP
+    protocol: ftps
+    host: 
+      secure: NsLJEPIBvmwCOj8Tg8RoRQ==
+    username:
+      secure: ejxi5mvk7oLYu7QtbYojajEPigMy0mokaKhuEVuDZcA=
+    password:
+      secure: Hbn6Uy3lT0YZ88yFJ3aW4w==
+    folder: appveyor
+    application:
+    active_mode: false
+
+
+on_finish:
+#- cmd: echo xfreerdp /u:appveyor /cert-ignore +clipboard /v:<ip>:<port>
+#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt
index 3ce133c6a67fde3d3ea55170bc7b8b24938fa8a6..292e184c72d20a3d2e2b5295de8dc818d6826a58 100644
--- a/assets/CMakeLists.txt
+++ b/assets/CMakeLists.txt
@@ -26,7 +26,7 @@ endforeach()
 # Installation
 
 if(CLANG)
-	get_target_property(outname ${SRB2_SDL2_EXE_NAME} OUTPUT_NAME)
+	get_target_property(outname SRB2SDL2 OUTPUT_NAME)
 	install(FILES ${SRB2_ASSET_ALL}
 		DESTINATION "${outname}.app/Contents/Resources"
 	)
diff --git a/comptime.bat b/comptime.bat
index 23ee7ea558e8242e5995adc37125cf7915ec53d7..9e127f001a984ebf3e6febffb8307adb21d08aaf 100644
--- a/comptime.bat
+++ b/comptime.bat
@@ -1,10 +1,32 @@
 @ECHO OFF
-set REV=Unknown
+set BRA=Unknown
+set REV=illegal
+
 copy nul: /b +%1\comptime.c tmp.$$$ > nul
 move tmp.$$$ %1\comptime.c > nul
-SET REV=illegal
-FOR /F "usebackq" %%s IN (`svnversion %1`) DO @SET REV=%%s
+
+if exist .git goto gitrev
+if exist ..\.git goto gitrev
+if exist .svn goto svnrev
+goto filwri
+
+:gitrev
+set GIT=%2
+if "%GIT%"=="" set GIT=git
+FOR /F "usebackq" %%s IN (`%GIT% rev-parse --abbrev-ref HEAD`) DO @SET BRA=%%s
+FOR /F "usebackq" %%s IN (`%GIT% rev-parse HEAD`) DO @SET REV=%%s
+set REV=%REV:~0,8%
+goto filwri
+
+:svnrev
+set BRA=Subversion
+FOR /F "usebackq" %%s IN (`svnversion .`) DO @SET REV=%%s
+set REV=r%REV%
+goto filwri
+
+:filwri
 ECHO // Do not edit!  This file was autogenerated > %1\comptime.h
 ECHO // by the %0 batch file >> %1\comptime.h
 ECHO // >> %1\comptime.h
-ECHO const char* comprevision = "r%REV%"; >> %1\comptime.h
+ECHO const char* compbranch = "%BRA%"; >> %1\comptime.h
+ECHO const char* comprevision = "%REV%"; >> %1\comptime.h
diff --git a/comptime.sh b/comptime.sh
index 703bb2d3549cbd890ab7e166722869bd60c7bbee..71c5f08aaa9e79dbb6878d47a3d41b979d5c37e1 100755
--- a/comptime.sh
+++ b/comptime.sh
@@ -5,13 +5,15 @@ if [ x"$1" != x ]; then
 fi
 
 versiongit() {
-	gitversion=`git describe`
+	gitbranch=`git rev-parse --abbrev-ref HEAD`
+	gitversion=`git rev-parse HEAD`
 	cat <<EOF > $path/comptime.h
 
 // Do not edit!  This file was autogenerated
-// by the $0 script with git svn
+// by the $0 script with git
 //
-const char* comprevision = "$gitversion";
+const char* compbranch = "$gitbranch";
+const char* comprevision = "${gitversion:0:8}";
 EOF
 exit 0
 }
@@ -23,6 +25,7 @@ versionsvn() {
 // Do not edit!  This file was autogenerated
 // by the $0 script with subversion
 //
+const char* compbranch = "Subversion";
 const char* comprevision = "r$svnrevision";
 EOF
 exit 0
@@ -34,6 +37,7 @@ versionfake() {
 // Do not edit!  This file was autogenerated
 // by the $0 script with an unknown or nonexist SCM
 //
+const char* compbranch = "Unknown";
 const char* comprevision = "illegal";
 EOF
 }
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ae3e4b751b080325e955a956fa725b7aa70aa834..716cf6cf848f4f2c8c2e70bbef30a18a66996141 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -35,32 +35,6 @@ set(SRB2_CORE_SOURCES
 	m_random.c
 	md5.c
 	mserv.c
-	p_ceilng.c
-	p_enemy.c
-	p_fab.c
-	p_floor.c
-	p_inter.c
-	p_lights.c
-	p_map.c
-	p_maputl.c
-	p_mobj.c
-	p_polyobj.c
-	p_saveg.c
-	p_setup.c
-	p_sight.c
-	p_spec.c
-	p_telept.c
-	p_tick.c
-	p_user.c
-	r_bsp.c
-	r_data.c
-	r_draw.c
-	r_main.c
-	r_plane.c
-	r_segs.c
-	r_sky.c
-	r_splats.c
-	r_things.c
 	s_sound.c
 	screen.c
 	sounds.c
@@ -126,15 +100,30 @@ set(SRB2_CORE_HEADERS
 	md5.h
 	mserv.h
 	p5prof.h
-	p_local.h
-	p_maputl.h
-	p_mobj.h
-	p_polyobj.h
-	p_pspr.h
-	p_saveg.h
-	p_setup.h
-	p_spec.h
-	p_tick.h
+	s_sound.h
+	screen.h
+	sounds.h
+	st_stuff.h
+	tables.h
+	v_video.h
+	w_wad.h
+	y_inter.h
+	z_zone.h
+
+	config.h.in
+)
+
+set(SRB2_CORE_RENDER_SOURCES
+	r_bsp.c
+	r_data.c
+	r_draw.c
+	r_main.c
+	r_plane.c
+	r_segs.c
+	r_sky.c
+	r_splats.c
+	r_things.c
+
 	r_bsp.h
 	r_data.h
 	r_defs.h
@@ -147,82 +136,78 @@ set(SRB2_CORE_HEADERS
 	r_splats.h
 	r_state.h
 	r_things.h
-	s_sound.h
-	screen.h
-	sounds.h
-	st_stuff.h
-	tables.h
-	v_video.h
-	w_wad.h
-	y_inter.h
-	z_zone.h
 )
 
-prepend_sources(SRB2_CORE_SOURCES)
-prepend_sources(SRB2_CORE_HEADERS)
-
-set(SRB2_CORE_HEADERS ${SRB2_CORE_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/config.h)
-
-set(SRB2_HWRENDER_SOURCES
-	hardware/hw_bsp.c
-	hardware/hw_cache.c
-	hardware/hw_draw.c
-	hardware/hw_light.c
-	hardware/hw_main.c
-	hardware/hw_md2.c
-	hardware/hw_trick.c
-)
+set(SRB2_CORE_GAME_SOURCES
+	p_ceilng.c
+	p_enemy.c
+	p_fab.c
+	p_floor.c
+	p_inter.c
+	p_lights.c
+	p_map.c
+	p_maputl.c
+	p_mobj.c
+	p_polyobj.c
+	p_saveg.c
+	p_setup.c
+	p_sight.c
+	p_slopes.c
+	p_spec.c
+	p_telept.c
+	p_tick.c
+	p_user.c
 
-set (SRB2_HWRENDER_HEADERS
-	hardware/hw_data.h
-	hardware/hw_defs.h
-	hardware/hw_dll.h
-	hardware/hw_drv.h
-	hardware/hw_glide.h
-	hardware/hw_glob.h
-	hardware/hw_light.h
-	hardware/hw_main.h
-	hardware/hw_md2.h
+	p_local.h
+	p_maputl.h
+	p_mobj.h
+	p_polyobj.h
+	p_pspr.h
+	p_saveg.h
+	p_setup.h
+	p_slopes.h
+	p_spec.h
+	p_tick.h
 )
 
-prepend_sources(SRB2_HWRENDER_SOURCES)
-prepend_sources(SRB2_HWRENDER_HEADERS)
+if(NOT CLANG)
+	set(SRB2_CORE_SOURCES ${SRB2_CORE_SOURCES} string.c)
+endif()
 
-set(SRB2_R_OPENGL_SOURCES
-	hardware/r_opengl/r_opengl.c
-)
+prepend_sources(SRB2_CORE_SOURCES)
+prepend_sources(SRB2_CORE_HEADERS)
+prepend_sources(SRB2_CORE_RENDER_SOURCES)
+prepend_sources(SRB2_CORE_GAME_SOURCES)
 
-set(SRB2_R_OPENGL_HEADERS
-	hardware/r_opengl/r_opengl.h
-)
+set(SRB2_CORE_HEADERS ${SRB2_CORE_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+source_group("Main" FILES ${SRB2_CORE_SOURCES} ${SRB2_CORE_HEADERS})
+source_group("Renderer" FILES ${SRB2_CORE_RENDER_SOURCES})
+source_group("Game" FILES ${SRB2_CORE_GAME_SOURCES})
 
-prepend_sources(SRB2_R_OPENGL_SOURCES)
-prepend_sources(SRB2_R_OPENGL_HEADERS)
 
 set(SRB2_ASM_SOURCES
-	vid_copy.s
+	${CMAKE_CURRENT_SOURCE_DIR}/vid_copy.s
 )
 
 set(SRB2_NASM_SOURCES
-	tmap_mmx.nas
-	tmap.nas
+	${CMAKE_CURRENT_SOURCE_DIR}/tmap_mmx.nas
+	${CMAKE_CURRENT_SOURCE_DIR}/tmap.nas
 )
 
 if(MSVC)
-	list(APPEND SRB2_NASM_SOURCES tmap_vc.nas)
+	list(APPEND SRB2_NASM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/tmap_vc.nas)
 endif()
 
 set(SRB2_NASM_OBJECTS
-	tmap_mmx.obj
-	tmap.obj
+	${CMAKE_CURRENT_BINARY_DIR}/tmap_mmx.obj
+	${CMAKE_CURRENT_BINARY_DIR}/tmap.obj
 )
 
 if(MSVC)
-	list(APPEND SRB2_NASM_OBJECTS tmap_vc.obj)
+	list(APPEND SRB2_NASM_OBJECTS ${CMAKE_CURRENT_BINARY_DIR}/tmap_vc.obj)
 endif()
 
-prepend_sources(SRB2_ASM_SOURCES)
-prepend_sources(SRB2_NASM_SOURCES)
+source_group("Assembly" FILES ${SRB2_ASM_SOURCES} ${SRB2_NASM_SOURCES})
 
 
 ### Configuration
@@ -231,11 +216,11 @@ set(SRB2_CONFIG_HAVE_BLUA ON CACHE BOOL
 set(SRB2_CONFIG_HAVE_PNG ON CACHE BOOL
 	"Enable PNG support. Depends on zlib, so will be disabled if you don't enable that too.")
 set(SRB2_CONFIG_HAVE_ZLIB ON CACHE BOOL
-	"Enable zlib support")
+	"Enable zlib support.")
 set(SRB2_CONFIG_HAVE_GME ON CACHE BOOL
-	"Enable GME support")
+	"Enable GME support.")
 set(SRB2_CONFIG_HWRENDER ON CACHE BOOL
-	"Enable hardware rendering through OpenGL")
+	"Enable hardware rendering through OpenGL.")
 set(SRB2_CONFIG_USEASM OFF CACHE BOOL
 	"Enable NASM tmap implementation for software mode speedup.")
 set(SRB2_CONFIG_YASM OFF CACHE BOOL
@@ -269,6 +254,8 @@ if(${SRB2_CONFIG_HAVE_BLUA})
 	prepend_sources(SRB2_LUA_SOURCES)
 	prepend_sources(SRB2_LUA_HEADERS)
 
+	source_group("LUA" FILES ${SRB2_LUA_SOURCES} ${SRB2_LUA_HEADERS})
+
 	set(SRB2_BLUA_SOURCES
 		blua/lapi.c
 		blua/lauxlib.c
@@ -320,8 +307,11 @@ if(${SRB2_CONFIG_HAVE_BLUA})
 		blua/lvm.h
 		blua/lzio.h
 	)
+
 	prepend_sources(SRB2_BLUA_SOURCES)
 	prepend_sources(SRB2_BLUA_HEADERS)
+
+	source_group("LUA\\Interpreter" FILES ${SRB2_BLUA_SOURCES} ${SRB2_BLUA_HEADERS})
 endif()
 
 if(${SRB2_CONFIG_HAVE_GME})
@@ -357,6 +347,36 @@ endif()
 
 if(${SRB2_CONFIG_HWRENDER})
 	add_definitions(-DHWRENDER)
+	set(SRB2_HWRENDER_SOURCES
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_bsp.c
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_cache.c
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_draw.c
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.c
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.c
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.c
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_trick.c
+	)
+
+	set (SRB2_HWRENDER_HEADERS
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_data.h
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_defs.h
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_dll.h
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_drv.h
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_glide.h
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_glob.h
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_light.h
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_main.h
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/hw_md2.h
+	)
+
+	set(SRB2_R_OPENGL_SOURCES
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/r_opengl/r_opengl.c
+	)
+
+	set(SRB2_R_OPENGL_HEADERS
+		${CMAKE_CURRENT_SOURCE_DIR}/hardware/r_opengl/r_opengl.h
+	)
+
 endif()
 
 if(${SRB2_CONFIG_HWRENDER} AND ${SRB2_CONFIG_STATIC_OPENGL})
@@ -386,10 +406,6 @@ endif()
 
 # Targets
 
-if(${CMAKE_SYSTEM} MATCHES Windows)
-	add_subdirectory(win32)
-endif()
-
 # Compatibility flag with later versions of GCC
 # We should really fix our code to not need this
 if(NOT CLANG AND NOT MSVC)
@@ -398,4 +414,23 @@ endif()
 
 add_definitions(-DCMAKECONFIG)
 
+#add_library(SRB2Core STATIC
+#	${SRB2_CORE_SOURCES}
+#	${SRB2_CORE_HEADERS}
+#	${SRB2_CORE_RENDER_SOURCES}
+#	${SRB2_CORE_GAME_SOURCES}
+#	${SRB2_LUA_SOURCES}
+#	${SRB2_LUA_HEADERS}
+#	${SRB2_BLUA_SOURCES}
+#	${SRB2_BLUA_HEADERS}
+#)
+
 add_subdirectory(sdl)
+
+if(${CMAKE_SYSTEM} MATCHES Windows)
+	add_subdirectory(win32)
+endif()
+
+if(NOT ${SRB2_SDL2_AVAILABLE} AND NOT ${SRB2_WIN32_AVAILABLE})
+	message(FATAL_ERROR "There are no targets available to build an SRB2 executable. :(")
+endif()
diff --git a/src/Makefile b/src/Makefile
index d4cc64a4b6ff79da6672ee10df9ef30f574aca40..bee60804720da1dcbee09065c29f616e145848f0 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -454,6 +454,7 @@ OBJS:=$(i_main_o) \
 		$(OBJDIR)/p_telept.o \
 		$(OBJDIR)/p_tick.o   \
 		$(OBJDIR)/p_user.o   \
+		$(OBJDIR)/p_slopes.o \
 		$(OBJDIR)/tables.o   \
 		$(OBJDIR)/r_bsp.o    \
 		$(OBJDIR)/r_data.o   \
diff --git a/src/Makefile.cfg b/src/Makefile.cfg
index 1ea96df925c1d8594bd026698e1e8d253f209000..fa8896a7c200f03acea8fa722568dd0da11d0075 100644
--- a/src/Makefile.cfg
+++ b/src/Makefile.cfg
@@ -7,6 +7,22 @@
 # and other things
 #
 
+ifdef GCC53
+GCC52=1
+endif
+
+ifdef GCC52
+GCC51=1
+endif
+
+ifdef GCC51
+GCC49=1
+endif
+
+ifdef GCC49
+GCC48=1
+endif
+
 ifdef GCC48
 GCC47=1
 endif
@@ -139,6 +155,10 @@ WFLAGS+=-Wformat-security
 ifndef GCC29
 #WFLAGS+=-Winit-self
 endif
+ifdef GCC46
+WFLAGS+=-Wno-suggest-attribute=noreturn
+endif
+
 ifndef MINGW
 ifdef GCC45
 WFLAGS+=-Wunsuffixed-float-constants
@@ -155,6 +175,7 @@ ifdef GCC43
 endif
 WFLAGS+=$(OLDWFLAGS)
 
+
 #indicate platform and what interface use with
 ifndef WINCE
 ifndef XBOX
diff --git a/src/blua/luaconf.h b/src/blua/luaconf.h
index 4fb9407996c3cd884f23fa87c9f5a415436d1177..9e2948f414bf771202b2d1b25e4d7378b086bda3 100644
--- a/src/blua/luaconf.h
+++ b/src/blua/luaconf.h
@@ -11,6 +11,13 @@
 #include <limits.h>
 #include <stddef.h>
 
+#ifdef _MSC_VER
+#define INT32 __int32
+#else
+#include <stdint.h>
+#define INT32 int32_t
+#endif
+
 
 /*
 ** ==================================================================
@@ -140,7 +147,7 @@
 ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most
 ** machines, ptrdiff_t gives a good choice between int or long.)
 */
-#define LUA_INTEGER	ptrdiff_t
+#define LUA_INTEGER	INT32
 
 
 /*
@@ -502,13 +509,13 @@
 */
 
 //#define LUA_NUMBER_DOUBLE
-#define LUA_NUMBER	ptrdiff_t
+#define LUA_NUMBER	INT32
 
 /*
 @@ LUAI_UACNUMBER is the result of an 'usual argument conversion'
 @* over a number.
 */
-#define LUAI_UACNUMBER	ptrdiff_t
+#define LUAI_UACNUMBER	INT32
 
 
 /*
@@ -519,14 +526,14 @@
 @@ lua_str2number converts a string to a number.
 */
 #ifdef LUA_WIN
-	#define LUA_NUMBER_SCAN		"%Ii"
-	#define LUA_NUMBER_FMT		"%Ii"
+	#define LUA_NUMBER_SCAN		"%d"
+	#define LUA_NUMBER_FMT		"%d"
 #else
-	#define LUA_NUMBER_SCAN		"%ti"
-	#define LUA_NUMBER_FMT		"%ti"
+	#define LUA_NUMBER_SCAN		"%d"
+	#define LUA_NUMBER_FMT		"%d"
 #endif
 #define lua_number2str(s,n)	sprintf((s), LUA_NUMBER_FMT, (n))
-#define LUAI_MAXNUMBER2STR	32 /* 16 digits, sign, point, and \0 */
+#define LUAI_MAXNUMBER2STR	12 /* 10 digits, sign, and \0 */
 #define lua_str2number(s,p)	strtol((s), (p), 10)
 
 
diff --git a/src/comptime.c b/src/comptime.c
index a4dc5b0f9637e60d761819792ee1f5dd4058656e..398eda0743706cecb4a22d1996f8949564f1fe07 100644
--- a/src/comptime.c
+++ b/src/comptime.c
@@ -9,12 +9,14 @@
 
 #if (defined(CMAKECONFIG))
 #include "config.h"
+const char *compbranch = SRB2_COMP_BRANCH;
 const char *comprevision = SRB2_COMP_REVISION;
 
 #elif (defined(COMPVERSION))
 #include "comptime.h"
 
 #else
+const char *compbranch = "Unknown";
 const char *comprevision = "illegal";
 
 #endif
diff --git a/src/config.h.in b/src/config.h.in
index 53747266c70bc9c4679c23b2a09a61e695c0cedd..5cd75fa5a50962f34a638b3dda519cfe2483fa47 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -3,6 +3,12 @@
 #ifndef __CONFIG_H__
 #define __CONFIG_H__
 
+/* DO NOT MODIFY config.h DIRECTLY! It will be overwritten by cmake.
+ * If you want to change a configuration option here, modify it in
+ * your CMakeCache.txt. config.h.in is used as a template for CMake
+ * variables, so you can insert them here too.
+ */
+
 #ifdef CMAKECONFIG
 
 #define ASSET_HASH_SRB2_SRB   "${SRB2_ASSET_srb2.srb_HASH}"
@@ -12,6 +18,7 @@
 #define ASSET_HASH_PATCH_DTA  "${SRB2_ASSET_patch.dta_HASH}"
 
 #define SRB2_COMP_REVISION    "${SRB2_COMP_REVISION}"
+#define SRB2_COMP_BRANCH      "${SRB2_COMP_BRANCH}"
 #define SRB2_GIT_DESCRIBE     "${SRB2_GIT_DESCRIBE}"
 #define SRB2_GIT_BRANCH       "${SRB2_GIT_BRANCH}"
 
diff --git a/src/console.c b/src/console.c
index e77c400b3fa98552f0c405b8c3acc96ed65c92cc..a6919c0f025dad20e4625a94dd9c0d40306d2910 100644
--- a/src/console.c
+++ b/src/console.c
@@ -202,7 +202,7 @@ static void CONS_Bind_f(void)
 	}
 
 	key = G_KeyStringtoNum(COM_Argv(1));
-	if (!key)
+	if (key <= 0 || key >= NUMINPUTS)
 	{
 		CONS_Alert(CONS_NOTICE, M_GetText("Invalid key name\n"));
 		return;
@@ -248,11 +248,11 @@ void CON_ReSetupBackColormap(UINT16 num)
 	{
 		j = pal[i] + pal[i+1] + pal[i+2];
 		cwhitemap[k] = (UINT8)(15 - (j>>6));
-		corangemap[k] = (UINT8)(95 - (j>>6));
-		cbluemap[k] = (UINT8)(239 - (j>>6));
-		cgreenmap[k] = (UINT8)(175 - (j>>6));
+		corangemap[k] = (UINT8)(63 - (j>>6));
+		cbluemap[k] = (UINT8)(159 - (j>>6));
+		cgreenmap[k] = (UINT8)(111 - (j>>6));
 		cgraymap[k] = (UINT8)(31 - (j>>6));
-		credmap[k] = (UINT8)(143 - (j>>6));
+		credmap[k] = (UINT8)(47 - (j>>6));
 	}
 }
 
@@ -283,11 +283,11 @@ static void CON_SetupBackColormap(void)
 	{
 		j = pal[i] + pal[i+1] + pal[i+2];
 		cwhitemap[k] = (UINT8)(15 - (j>>6));
-		corangemap[k] = (UINT8)(95 - (j>>6));
-		cbluemap[k] = (UINT8)(239 - (j>>6));
-		cgreenmap[k] = (UINT8)(175 - (j>>6));
+		corangemap[k] = (UINT8)(63 - (j>>6));
+		cbluemap[k] = (UINT8)(159 - (j>>6));
+		cgreenmap[k] = (UINT8)(111 - (j>>6));
 		cgraymap[k] = (UINT8)(31 - (j>>6));
-		credmap[k] = (UINT8)(143 - (j>>6));
+		credmap[k] = (UINT8)(47 - (j>>6));
 	}
 
 	// setup the other colormaps, for console text
@@ -306,20 +306,20 @@ static void CON_SetupBackColormap(void)
 		orangemap[i] = (UINT8)i;
 	}
 
-	yellowmap[3] = (UINT8)103;
-	yellowmap[9] = (UINT8)115;
-	purplemap[3] = (UINT8)195;
-	purplemap[9] = (UINT8)198;
-	lgreenmap[3] = (UINT8)162;
-	lgreenmap[9] = (UINT8)170;
-	bluemap[3]   = (UINT8)228;
-	bluemap[9]   = (UINT8)238;
+	yellowmap[3] = (UINT8)73;
+	yellowmap[9] = (UINT8)66;
+	purplemap[3] = (UINT8)184;
+	purplemap[9] = (UINT8)186;
+	lgreenmap[3] = (UINT8)102;
+	lgreenmap[9] = (UINT8)106;
+	bluemap[3]   = (UINT8)147;
+	bluemap[9]   = (UINT8)158;
 	graymap[3]   = (UINT8)10;
 	graymap[9]   = (UINT8)15;
-	redmap[3]    = (UINT8)124;
-	redmap[9]    = (UINT8)127;
-	orangemap[3] = (UINT8)85;
-	orangemap[9] = (UINT8)90;
+	redmap[3]    = (UINT8)210;
+	redmap[9]    = (UINT8)32;
+	orangemap[3] = (UINT8)52;
+	orangemap[9] = (UINT8)57;
 }
 
 // Setup the console text buffer
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index df75590203c45f1e5739bb57aadecf7375a2688f..8f0399637e3ce4c501d6a56c653c32fa077f31c7 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -525,7 +525,7 @@ static inline void CL_DrawConnectionStatus(void)
 	if (cl_mode != cl_downloadfiles)
 	{
 		INT32 i, animtime = ((ccstime / 4) & 15) + 16;
-		UINT8 palstart = (cl_mode == cl_searching) ? 128 : 160;
+		UINT8 palstart = (cl_mode == cl_searching) ? 32 : 96;
 		// 15 pal entries total.
 		const char *cltext;
 
@@ -563,8 +563,8 @@ static inline void CL_DrawConnectionStatus(void)
 		dldlength = (INT32)((fileneeded[lastfilenum].currentsize/(double)fileneeded[lastfilenum].totalsize) * 256);
 		if (dldlength > 256)
 			dldlength = 256;
-		V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 175);
-		V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, dldlength, 8, 160);
+		V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, 256, 8, 111);
+		V_DrawFill(BASEVIDWIDTH/2-128, BASEVIDHEIGHT-24, dldlength, 8, 96);
 
 		memset(tempname, 0, sizeof(tempname));
 		nameonly(strncpy(tempname, fileneeded[lastfilenum].filename, 31));
diff --git a/src/d_main.c b/src/d_main.c
index 61255e2722574bc6e28a6acd2fa461913c4fd67b..c5f0d0b396029bb4c18b8e46a2488906abc51c21 100644
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -96,6 +96,10 @@ int	snprintf(char *str, size_t n, const char *fmt, ...);
 #include "hardware/hw3sound.h"
 #endif
 
+#ifdef HAVE_BLUA
+#include "lua_script.h"
+#endif
+
 // platform independant focus loss
 UINT8 window_notinfocus = false;
 
@@ -634,6 +638,10 @@ void D_SRB2Loop(void)
 #ifdef HW3SOUND
 		HW3S_EndFrameUpdate();
 #endif
+
+#ifdef HAVE_BLUA
+		LUA_Step();
+#endif
 	}
 }
 
@@ -1121,10 +1129,10 @@ void D_SRB2Main(void)
 #ifndef DEVELOP // md5s last updated 12/14/14
 
 	// Check MD5s of autoloaded files
-	W_VerifyFileMD5(0, ASSET_HASH_SRB2_SRB); // srb2.srb/srb2.wad
-	W_VerifyFileMD5(1, ASSET_HASH_ZONES_DTA); // zones.dta
-	W_VerifyFileMD5(2, ASSET_HASH_PLAYER_DTA); // player.dta
-	W_VerifyFileMD5(3, ASSET_HASH_RINGS_DTA); // rings.dta
+	//W_VerifyFileMD5(0, ASSET_HASH_SRB2_SRB); // srb2.srb/srb2.wad
+	//W_VerifyFileMD5(1, ASSET_HASH_ZONES_DTA); // zones.dta
+	//W_VerifyFileMD5(2, ASSET_HASH_PLAYER_DTA); // player.dta
+	//W_VerifyFileMD5(3, ASSET_HASH_RINGS_DTA); // rings.dta
 	//W_VerifyFileMD5(4, "0c66790502e648bfce90fdc5bb15722e"); // patch.dta
 	// don't check music.dta because people like to modify it, and it doesn't matter if they do
 	// ...except it does if they slip maps in there, and that's what W_VerifyNMUSlumps is for.
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 557715064b0e8914c6d5f8b7f7fc531042611a6c..6d9fb6b511fd8e6af65be9616d3f372d96e93c44 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -3179,7 +3179,11 @@ static void Command_ListWADS_f(void)
   */
 static void Command_Version_f(void)
 {
+#ifdef DEVELOP
+	CONS_Printf("Sonic Robo Blast 2 %s-%s (%s %s)\n", compbranch, comprevision, compdate, comptime);
+#else
 	CONS_Printf("Sonic Robo Blast 2 %s (%s %s %s)\n", VERSIONSTRING, compdate, comptime, comprevision);
+#endif
 }
 
 #ifdef UPDATE_ALERT
diff --git a/src/d_player.h b/src/d_player.h
index b9fcdef75f34af7e533f263d8d5126cfd501683f..2425ea1bdd78048caa5e5ba3df8f6836733df0fb 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -161,11 +161,15 @@ typedef enum
 	// Are animation frames playing?
 	PA_ETC=0,
 	PA_IDLE,
+	PA_EDGE,
 	PA_WALK,
 	PA_RUN,
+	PA_PAIN,
 	PA_ROLL,
+	PA_SPRING,
 	PA_FALL,
-	PA_ABILITY
+	PA_ABILITY,
+	PA_RIDE
 } panim_t;
 
 typedef enum
diff --git a/src/dehacked.c b/src/dehacked.c
index a8eccf49d25dd7f484c1b6be752e4e6f9b1766e1..241a523f89ea60f5bd0758dd71978ce75cc86a7f 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -998,7 +998,7 @@ static const struct {
 static void readlevelheader(MYFILE *f, INT32 num)
 {
 	char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
-	char *word = s;
+	char *word;
 	char *word2;
 	//char *word3; // Non-uppercase version of word2
 	char *tmp;
@@ -1027,6 +1027,9 @@ static void readlevelheader(MYFILE *f, INT32 num)
 			if (s == tmp)
 				continue; // Skip comment lines, but don't break.
 
+			// Set / reset word, because some things (Lua.) move it
+			word = s;
+
 			// Get the part before the " = "
 			tmp = strchr(s, '=');
 			*(tmp-1) = '\0';
@@ -1129,6 +1132,10 @@ static void readlevelheader(MYFILE *f, INT32 num)
 			}
 			else if (fastcmp(word, "NEXTLEVEL"))
 			{
+				if      (fastcmp(word2, "TITLE"))      i = 1100;
+				else if (fastcmp(word2, "EVALUATION")) i = 1101;
+				else if (fastcmp(word2, "CREDITS"))    i = 1102;
+				else
 				// Support using the actual map name,
 				// i.e., Nextlevel = AB, Nextlevel = FZ, etc.
 
@@ -3747,9 +3754,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_PLAY_RUN",
 	"S_PLAY_PAIN",
 	"S_PLAY_DEAD",
+	"S_PLAY_DRWN",
 	"S_PLAY_SPIN",
+	"S_PLAY_DASH",
 	"S_PLAY_GASP",
 	"S_PLAY_JUMP",
+	"S_PLAY_SPRING",
 	"S_PLAY_FALL",
 	"S_PLAY_EDGE",
 	"S_PLAY_RIDE",
@@ -3767,8 +3777,18 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_PLAY_SUPER_STND",
 	"S_PLAY_SUPER_WALK",
 	"S_PLAY_SUPER_RUN",
-	"S_PLAY_SUPER_EDGE",
 	"S_PLAY_SUPER_PAIN",
+	"S_PLAY_SUPER_STUN",
+	"S_PLAY_SUPER_DEAD",
+	"S_PLAY_SUPER_DRWN",
+	"S_PLAY_SUPER_SPIN",
+	"S_PLAY_SUPER_GASP",
+	"S_PLAY_SUPER_JUMP",
+	"S_PLAY_SUPER_SPRING",
+	"S_PLAY_SUPER_FALL",
+	"S_PLAY_SUPER_EDGE",
+	"S_PLAY_SUPER_RIDE",
+	"S_PLAY_SUPER_FLOAT",
 
 	// SF_SUPER
 	"S_PLAY_SUPERTRANS1",
@@ -7189,6 +7209,7 @@ static const char *const MOBJEFLAG_LIST[] = {
 	"GOOWATER", // Goo water
 	"PUSHED", // Mobj was already pushed this tic
 	"SPRUNG", // Mobj was already sprung this tic
+	"APPLYPMOMZ", // Platform movement
 	NULL
 };
 
@@ -7298,27 +7319,31 @@ static const char *COLOR_ENUMS[] = {
 	"SILVER",   	// SKINCOLOR_SILVER
 	"GREY",	    	// SKINCOLOR_GREY
 	"BLACK",    	// SKINCOLOR_BLACK
-	"CYAN",     	// SKINCOLOR_CYAN
-	"TEAL",     	// SKINCOLOR_TEAL
-	"STEELBLUE",	// SKINCOLOR_STEELBLUE
-	"BLUE",     	// SKINCOLOR_BLUE
-	"PEACH",    	// SKINCOLOR_PEACH
-	"TAN",      	// SKINCOLOR_TAN
-	"PINK",     	// SKINCOLOR_PINK
-	"LAVENDER", 	// SKINCOLOR_LAVENDER
-	"PURPLE",   	// SKINCOLOR_PURPLE
-	"ORANGE",   	// SKINCOLOR_ORANGE
-	"ROSEWOOD", 	// SKINCOLOR_ROSEWOOD
 	"BEIGE",    	// SKINCOLOR_BEIGE
+	"PEACH",    	// SKINCOLOR_PEACH
 	"BROWN",    	// SKINCOLOR_BROWN
 	"RED",      	// SKINCOLOR_RED
-	"DARKRED",  	// SKINCOLOR_DARKRED
-	"NEONGREEN",	// SKINCOLOR_NEONGREEN
-	"GREEN",    	// SKINCOLOR_GREEN
-	"ZIM",      	// SKINCOLOR_ZIM
-	"OLIVE",    	// SKINCOLOR_OLIVE
+	"CRIMSON",     	// SKINCOLOR_CRIMSON
+	"ORANGE",   	// SKINCOLOR_ORANGE
+	"RUST",     	// SKINCOLOR_RUST
+	"GOLD",      	// SKINCOLOR_GOLD
 	"YELLOW",   	// SKINCOLOR_YELLOW
-	"GOLD",     	// SKINCOLOR_GOLD
+	"TAN",      	// SKINCOLOR_TAN
+	"MOSS",      	// SKINCOLOR_MOSS
+	"PERIDOT",    	// SKINCOLOR_PERIDOT
+	"GREEN",    	// SKINCOLOR_GREEN
+	"EMERALD",  	// SKINCOLOR_EMERALD
+	"AQUA",     	// SKINCOLOR_AQUA
+	"TEAL",     	// SKINCOLOR_TEAL
+	"CYAN",     	// SKINCOLOR_CYAN
+	"BLUE",     	// SKINCOLOR_BLUE
+	"AZURE",    	// SKINCOLOR_AZURE
+	"PASTEL",		// SKINCOLOR_PASTEL
+	"PURPLE",   	// SKINCOLOR_PURPLE
+	"LAVENDER", 	// SKINCOLOR_LAVENDER
+	"MAGENTA",   	// SKINCOLOR_MAGENTA
+	"PINK",     	// SKINCOLOR_PINK
+	"ROSY",     	// SKINCOLOR_ROSY
 	// Super special awesome Super flashing colors!
 	"SUPER1",   	// SKINCOLOR_SUPER1
 	"SUPER2",   	// SKINCOLOR_SUPER2,
@@ -7655,11 +7680,15 @@ struct {
 	// Player animation (panim_t)
 	{"PA_ETC",PA_ETC},
 	{"PA_IDLE",PA_IDLE},
+	{"PA_EDGE",PA_EDGE},
 	{"PA_WALK",PA_WALK},
 	{"PA_RUN",PA_RUN},
+	{"PA_PAIN",PA_PAIN},
 	{"PA_ROLL",PA_ROLL},
+	{"PA_SPRING",PA_SPRING},
 	{"PA_FALL",PA_FALL},
 	{"PA_ABILITY",PA_ABILITY},
+	{"PA_RIDE",PA_RIDE},
 
 	// Current weapon
 	{"WEP_AUTO",WEP_AUTO},
@@ -7738,36 +7767,36 @@ struct {
 	{"FF_GOOWATER",FF_GOOWATER},               ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop.
 
 	// Angles
-	{"ANG1",ANG1},
-	{"ANG2",ANG2},
-	{"ANG10",ANG10},
-	{"ANG15",ANG15},
-	{"ANG20",ANG20},
-	{"ANG30",ANG30},
-	{"ANG60",ANG60},
-	{"ANG64h",ANG64h},
-	{"ANG105",ANG105},
-	{"ANG210",ANG210},
-	{"ANG255",ANG255},
-	{"ANG340",ANG340},
-	{"ANG350",ANG350},
-	{"ANGLE_11hh",ANGLE_11hh},
-	{"ANGLE_22h",ANGLE_22h},
-	{"ANGLE_45",ANGLE_45},
-	{"ANGLE_67h",ANGLE_67h},
-	{"ANGLE_90",ANGLE_90},
-	{"ANGLE_112h",ANGLE_112h},
-	{"ANGLE_135",ANGLE_135},
-	{"ANGLE_157h",ANGLE_157h},
-	{"ANGLE_180",ANGLE_180},
-	{"ANGLE_202h",ANGLE_202h},
-	{"ANGLE_225",ANGLE_225},
-	{"ANGLE_247h",ANGLE_247h},
-	{"ANGLE_270",ANGLE_270},
-	{"ANGLE_292h",ANGLE_292h},
-	{"ANGLE_315",ANGLE_315},
-	{"ANGLE_337h",ANGLE_337h},
-	{"ANGLE_MAX",ANGLE_MAX},
+	{"ANG1",ANG1>>16},
+	{"ANG2",ANG2>>16},
+	{"ANG10",ANG10>>16},
+	{"ANG15",ANG15>>16},
+	{"ANG20",ANG20>>16},
+	{"ANG30",ANG30>>16},
+	{"ANG60",ANG60>>16},
+	{"ANG64h",ANG64h>>16},
+	{"ANG105",ANG105>>16},
+	{"ANG210",ANG210>>16},
+	{"ANG255",ANG255>>16},
+	{"ANG340",ANG340>>16},
+	{"ANG350",ANG350>>16},
+	{"ANGLE_11hh",ANGLE_11hh>>16},
+	{"ANGLE_22h",ANGLE_22h>>16},
+	{"ANGLE_45",ANGLE_45>>16},
+	{"ANGLE_67h",ANGLE_67h>>16},
+	{"ANGLE_90",ANGLE_90>>16},
+	{"ANGLE_112h",ANGLE_112h>>16},
+	{"ANGLE_135",ANGLE_135>>16},
+	{"ANGLE_157h",ANGLE_157h>>16},
+	{"ANGLE_180",ANGLE_180>>16},
+	{"ANGLE_202h",ANGLE_202h>>16},
+	{"ANGLE_225",ANGLE_225>>16},
+	{"ANGLE_247h",ANGLE_247h>>16},
+	{"ANGLE_270",ANGLE_270>>16},
+	{"ANGLE_292h",ANGLE_292h>>16},
+	{"ANGLE_315",ANGLE_315>>16},
+	{"ANGLE_337h",ANGLE_337h>>16},
+	{"ANGLE_MAX",ANGLE_MAX>>16},
 
 	// P_Chase directions (dirtype_t)
 	{"DI_NODIR",DI_NODIR},
@@ -8726,7 +8755,7 @@ static inline int lib_getenum(lua_State *L)
 		lua_pushinteger(L, mapmusic);
 		return 1;
 	} else if (fastcmp(word,"server")) {
-		if (!playeringame[serverplayer])
+		if ((!multiplayer || !netgame) && !playeringame[serverplayer])
 			return 0;
 		LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
 		return 1;
diff --git a/src/doomdef.h b/src/doomdef.h
index 83702ad750064fe93f9c847f22ebb548253bcf28..7572778653c122ad5b4c57fc181f89007f801200 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -142,8 +142,10 @@ extern FILE *logstream;
 #ifdef DEVELOP
 #define VERSION    0 // Game version
 #define SUBVERSION 0 // more precise version number
-#define VERSIONSTRING "Trunk"
-#define VERSIONSTRINGW L"Trunk"
+#define VERSIONSTRING "Development EXE"
+#define VERSIONSTRINGW L"Development EXE"
+// most interface strings are ignored in development mode.
+// we use comprevision and compbranch instead.
 #else
 #define VERSION    202 // Game version
 #define SUBVERSION 0  // more precise version number
@@ -232,27 +234,31 @@ typedef enum
 	SKINCOLOR_SILVER,
 	SKINCOLOR_GREY,
 	SKINCOLOR_BLACK,
-	SKINCOLOR_CYAN,
-	SKINCOLOR_TEAL,
-	SKINCOLOR_STEELBLUE,
-	SKINCOLOR_BLUE,
-	SKINCOLOR_PEACH,
-	SKINCOLOR_TAN,
-	SKINCOLOR_PINK,
-	SKINCOLOR_LAVENDER,
-	SKINCOLOR_PURPLE,
-	SKINCOLOR_ORANGE,
-	SKINCOLOR_ROSEWOOD,
 	SKINCOLOR_BEIGE,
+	SKINCOLOR_PEACH,
 	SKINCOLOR_BROWN,
 	SKINCOLOR_RED,
-	SKINCOLOR_DARKRED,
-	SKINCOLOR_NEONGREEN,
-	SKINCOLOR_GREEN,
-	SKINCOLOR_ZIM,
-	SKINCOLOR_OLIVE,
-	SKINCOLOR_YELLOW,
+	SKINCOLOR_CRIMSON,
+	SKINCOLOR_ORANGE,
+	SKINCOLOR_RUST,
 	SKINCOLOR_GOLD,
+	SKINCOLOR_YELLOW,
+	SKINCOLOR_TAN,
+	SKINCOLOR_MOSS,
+	SKINCOLOR_PERIDOT,
+	SKINCOLOR_GREEN,
+	SKINCOLOR_EMERALD,
+	SKINCOLOR_AQUA,
+	SKINCOLOR_TEAL,
+	SKINCOLOR_CYAN,
+	SKINCOLOR_BLUE,
+	SKINCOLOR_AZURE,
+	SKINCOLOR_PASTEL,
+	SKINCOLOR_PURPLE,
+	SKINCOLOR_LAVENDER,
+	SKINCOLOR_MAGENTA,
+	SKINCOLOR_PINK,
+	SKINCOLOR_ROSY,
 
 	// Careful! MAXSKINCOLORS cannot be greater than 0x20!
 	MAXSKINCOLORS,
@@ -426,7 +432,7 @@ INT32 I_GetKey(void);
 #endif
 
 // Compile date and time and revision.
-extern const char *compdate, *comptime, *comprevision;
+extern const char *compdate, *comptime, *comprevision, *compbranch;
 
 // Disabled code and code under testing
 // None of these that are disabled in the normal build are guaranteed to work perfectly
@@ -439,6 +445,9 @@ extern const char *compdate, *comptime, *comprevision;
 ///	Fun experimental slope stuff!
 //#define SLOPENESS
 
+/// Kalaron/Eternity Engine slope code (SRB2CB ported)
+#define ESLOPE
+
 ///	Delete file while the game is running.
 ///	\note	EXTREMELY buggy, tends to crash game.
 //#define DELFILE
diff --git a/src/doomtype.h b/src/doomtype.h
index ff4199775f03c104ac86f51f23998f167c137ac7..8e7da6881df87beb351470bbc1d6bfb01fead98a 100644
--- a/src/doomtype.h
+++ b/src/doomtype.h
@@ -100,11 +100,13 @@ typedef long ssize_t;
 
 #if defined (_MSC_VER) || defined (__OS2__)
 	// Microsoft VisualC++
+#ifdef _MSC_VER
 #if (_MSC_VER <= 1800) // MSVC 2013 and back
 	#define snprintf                _snprintf
 #if (_MSC_VER <= 1200) // MSVC 2012 and back
 	#define vsnprintf               _vsnprintf
 #endif
+#endif
 #endif
 	#define strncasecmp             strnicmp
 	#define strcasecmp              stricmp
@@ -177,6 +179,8 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
 // not the number of bytes in the buffer.
 #define STRBUFCPY(dst,src) strlcpy(dst, src, sizeof dst)
 
+// \note __BYTEBOOL__ used to be set above if "macintosh" was defined,
+// if macintosh's version of boolean type isn't needed anymore, then isn't this macro pointless now?
 #ifndef __BYTEBOOL__
 	#define __BYTEBOOL__
 
@@ -193,7 +197,6 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
 	#else
 		typedef enum {false, true} boolean;
 	#endif
-	//#endif // __cplusplus
 #endif // __BYTEBOOL__
 
 /* 7.18.2.1  Limits of exact-width integer types */
diff --git a/src/f_finale.c b/src/f_finale.c
index f541995d49977d3e54cc229a657922006b0a3f81..a85fd11cb0438fb3950401339007f55cb8f71858 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -982,6 +982,7 @@ static const char *credits[] = {
 	"",
 	"\1Programming",
 	"\1Assistance",
+	"\"chi.miru\"", // Red's secret weapon, the REAL reason slopes exist (also helped port drawing code from ZDoom)
 	"Andrew \"orospakr\" Clunis",
 	"Gregor \"Oogaland\" Dick",
 	"Julio \"Chaos Zero 64\" Guir",
diff --git a/src/f_wipe.c b/src/f_wipe.c
index 8e7c622c43a393276c6c9dffd9b515a36b3114b6..6f14e577aa13133806b0919293a3a18121240392 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -231,34 +231,52 @@ static void F_DoWipe(fademask_t *fademask)
 		maskx = masky = 0;
 		do
 		{
-			// pointer to transtable that this mask would use
-			transtbl = transtables + ((9 - *mask)<<FF_TRANSSHIFT);
-			// (ignore that it goes out of bounds if *mask is 0 or 10 --
-			//  it wouldn't be used in those cases anyway)
-
 			draw_rowstart = scrxpos[maskx];
 			draw_rowend   = scrxpos[maskx + 1];
 			draw_linestart = scrypos[masky];
 			draw_lineend   = scrypos[masky + 1];
 
-			// DRAWING LOOP
 			relativepos = (draw_linestart * vid.width) + draw_rowstart;
 			draw_linestogo = draw_lineend - draw_linestart;
-			while (draw_linestogo--)
+
+			if (*mask == 0)
 			{
-				w = w_base + relativepos;
-				s = s_base + relativepos;
-				e = e_base + relativepos;
-				draw_rowstogo = draw_rowend - draw_rowstart;
-				while (draw_rowstogo--)
+				// shortcut - memcpy source to work
+				while (draw_linestogo--)
 				{
-					if (*s != *e)
-						*w = ((*mask == 0) ? *s : (*mask == 10) ? *e : transtbl[(*e<<8) + *s]);
-					++w, ++s, ++e;
+					M_Memcpy(w_base+relativepos, s_base+relativepos, draw_rowend-draw_rowstart);
+					relativepos += vid.width;
+				}
+			}
+			else if (*mask == 10)
+			{
+				// shortcut - memcpy target to work
+				while (draw_linestogo--)
+				{
+					M_Memcpy(w_base+relativepos, e_base+relativepos, draw_rowend-draw_rowstart);
+					relativepos += vid.width;
+				}
+			}
+			else
+			{
+				// pointer to transtable that this mask would use
+				transtbl = transtables + ((9 - *mask)<<FF_TRANSSHIFT);
+
+				// DRAWING LOOP
+				while (draw_linestogo--)
+				{
+					w = w_base + relativepos;
+					s = s_base + relativepos;
+					e = e_base + relativepos;
+					draw_rowstogo = draw_rowend - draw_rowstart;
+
+					while (draw_rowstogo--)
+						*w++ = transtbl[ ( *e++ << 8 ) + *s++ ];
+
+					relativepos += vid.width;
 				}
-				relativepos += vid.width;
+				// END DRAWING LOOP
 			}
-			// END DRAWING LOOP
 
 			if (++maskx >= fademask->width)
 				++masky, maskx = 0;
diff --git a/src/g_game.c b/src/g_game.c
index 643ec8c93684ee6946f1b80c7d2760703abfa480..e2ed1e792b841bab73f3795426808ab06eebe7af 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -123,7 +123,7 @@ boolean useNightsSS = false;
 UINT8 skincolor_redteam = SKINCOLOR_RED;
 UINT8 skincolor_blueteam = SKINCOLOR_BLUE;
 UINT8 skincolor_redring = SKINCOLOR_RED;
-UINT8 skincolor_bluering = SKINCOLOR_STEELBLUE;
+UINT8 skincolor_bluering = SKINCOLOR_AZURE;
 
 tic_t countdowntimer = 0;
 boolean countdowntimeup = false;
@@ -297,9 +297,6 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"},
 #if JOYAXISSET > 3
 {7, "Pitch"}, {8, "Roll"}, {-7, "Pitch-"}, {-8, "Roll-"},
 #endif
-#if JOYAXISSET > 3
-{7, "Pitch"}, {8, "Roll"}, {-7, "Pitch-"}, {-8, "Roll-"},
-#endif
 #if JOYAXISSET > 4
 {7, "Yaw"}, {8, "Dummy"}, {-7, "Yaw-"}, {-8, "Dummy-"},
 #endif
@@ -5586,7 +5583,7 @@ boolean G_CheckDemoStatus(void)
 		free(demobuffer);
 		demorecording = false;
 
-		if (!modeattacking == ATTACKING_RECORD)
+		if (modeattacking != ATTACKING_RECORD)
 		{
 			if (saved)
 				CONS_Printf(M_GetText("Demo %s recorded\n"), demoname);
diff --git a/src/g_input.c b/src/g_input.c
index f12ddb7114c4b935e79877de7195ee248c47f6c2..e9010b39d0580f14000bd802a61aabfe063efda7 100644
--- a/src/g_input.c
+++ b/src/g_input.c
@@ -16,7 +16,6 @@
 #include "g_input.h"
 #include "keys.h"
 #include "hu_stuff.h" // need HUFONT start & end
-#include "keys.h"
 #include "d_net.h"
 #include "console.h"
 
@@ -1042,13 +1041,13 @@ INT32 G_KeyStringtoNum(const char *keystr)
 	if (!keystr[1] && keystr[0] > ' ' && keystr[0] <= 'z')
 		return keystr[0];
 
+	if (!strncmp(keystr, "KEY", 3) && keystr[3] >= '0' && keystr[3] <= '9')
+		return atoi(&keystr[3]);
+
 	for (j = 0; j < NUMKEYNAMES; j++)
 		if (!stricmp(keynames[j].name, keystr))
 			return keynames[j].keynum;
 
-	if (strlen(keystr) > 3)
-		return atoi(&keystr[3]);
-
 	return 0;
 }
 
diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h
index 70d776d9e962c219d3449bdd3db262e6017962db..52110121b9bb47c34a7ed7e903ee94ead00d9a97 100644
--- a/src/hardware/hw_defs.h
+++ b/src/hardware/hw_defs.h
@@ -46,8 +46,8 @@ typedef unsigned char   FBOOLEAN;
 #define HWR_PATCHES_CHROMAKEY_COLORINDEX   0
 #define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 1
 #else
-#define HWR_PATCHES_CHROMAKEY_COLORINDEX   247
-#define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 220
+#define HWR_PATCHES_CHROMAKEY_COLORINDEX   255
+#define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 130
 #endif
 
 // the chroma key color shows on border sprites, set it to black
diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h
index 88786bc112ae459eb8826fc14ab551d8f479ce98..83dff02f877e17db254f5e0e35bb47095bc7c18e 100644
--- a/src/hardware/hw_glob.h
+++ b/src/hardware/hw_glob.h
@@ -79,6 +79,7 @@ typedef struct gr_vissprite_s
 	boolean vflip;
    //Hurdler: 25/04/2000: now support colormap in hardware mode
 	UINT8 *colormap;
+	INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
 } gr_vissprite_t;
 
 // --------
diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 820eb25fc6509a1087c1e083f7c35249367b84d8..d0b1e2e08a5dbc5f9e16bc7af669127e4dbde8ce 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -2856,7 +2856,6 @@ static void HWR_AddPolyObjectPlanes(void)
 //                  : Draw one or more line segments.
 // Notes            : Sets gr_cursectorlight to the light of the parent sector, to modulate wall textures
 // -----------------+
-static lumpnum_t doomwaterflat;  //set by R_InitFlats hack
 static void HWR_Subsector(size_t num)
 {
 	INT16 count;
@@ -2867,7 +2866,6 @@ static void HWR_Subsector(size_t num)
 	INT32 ceilinglightlevel;
 	INT32 locFloorHeight, locCeilingHeight;
 	INT32 light = 0;
-	fixed_t wh;
 	extracolormap_t *floorcolormap;
 	extracolormap_t *ceilingcolormap;
 
@@ -3193,26 +3191,6 @@ static void HWR_Subsector(size_t num)
 		}
 	}
 
-//20/08/99: Changed by Hurdler (taken from faB's code)
-#ifdef DOPLANES
-	// -------------------- WATER IN DEV. TEST ------------------------
-	//dck hack : use abs(tag) for waterheight
-	//ilag : Since we changed to UINT16 for sector tags, simulate INT16
-	if (gr_frontsector->tag > 32767)
-	{
-		wh = ((65535-gr_frontsector->tag) <<FRACBITS) + (FRACUNIT/2);
-		if (wh > gr_frontsector->floorheight &&
-			wh < gr_frontsector->ceilingheight)
-		{
-			HWR_GetFlat(doomwaterflat);
-			HWR_RenderPlane(gr_frontsector,
-				&extrasubsectors[num], wh, PF_Translucent,
-				gr_frontsector->lightlevel, doomwaterflat,
-				NULL, 255, false, gr_frontsector->lightlist[light].extra_colormap);
-		}
-	}
-	// -------------------- WATER IN DEV. TEST ------------------------
-#endif
 	sub->validcount = validcount;
 }
 
@@ -3998,6 +3976,7 @@ static void HWR_SortVisSprites(void)
 	gr_vissprite_t *best = NULL;
 	gr_vissprite_t unsorted;
 	float bestdist;
+	INT32 bestdispoffset;
 
 	if (!gr_visspritecount)
 		return;
@@ -4025,11 +4004,19 @@ static void HWR_SortVisSprites(void)
 	for (i = 0; i < gr_visspritecount; i++)
 	{
 		bestdist = ZCLIP_PLANE-1;
+		bestdispoffset = INT32_MAX;
 		for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
 		{
 			if (ds->tz > bestdist)
 			{
 				bestdist = ds->tz;
+				bestdispoffset = ds->dispoffset;
+				best = ds;
+			}
+			// order visprites of same scale by dispoffset, smallest first
+			else if (ds->tz == bestdist && ds->dispoffset < bestdispoffset)
+			{
+				bestdispoffset = ds->dispoffset;
 				best = ds;
 			}
 		}
@@ -4653,6 +4640,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
 #endif
 	vis->x2 = tx;
 	vis->tz = tz;
+	vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST
 	vis->patchlumpnum = sprframe->lumppat[rot];
 	vis->flip = flip;
 	vis->mobj = thing;
@@ -4769,6 +4757,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
 	vis->x1 = x1;
 	vis->x2 = tx;
 	vis->tz = tz;
+	vis->dispoffset = 0; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST
 	vis->patchlumpnum = sprframe->lumppat[rot];
 	vis->flip = flip;
 	vis->mobj = (mobj_t *)thing;
@@ -5488,11 +5477,6 @@ void HWR_Startup(void)
 		HWR_AddEngineCommands();
 		HWR_InitTextureCache();
 
-		// for test water translucent surface
-		doomwaterflat  = W_CheckNumForName("FWATER1");
-		if (doomwaterflat == LUMPERROR) // if FWATER1 not found (in doom shareware)
-			doomwaterflat = W_GetNumForName("WATER0");
-
 		HWR_InitMD2();
 
 #ifdef ALAM_LIGHTING
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index a1763c8c809901e6caa6af45f22895febc71e772..c1ed368d68d82f6eb092bbadb8132a6d32ee44b1 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -926,7 +926,7 @@ void HWR_InitMD2(void)
 			CONS_Printf("MD2 for sprite PLAY detected in md2.dat, use a player skin instead!\n");
 			continue;
 		}
-	
+
 		for (i = 0; i < NUMSPRITES; i++)
 		{
 			if (stricmp(name, sprnames[i]) == 0)
@@ -1085,7 +1085,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 	if (!cv_grmd2.value)
 		return;
 
-	if (!spr->precip)
+	if (spr->precip)
 		return;
 
 	// MD2 colormap fix
diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index d14324c300cc5b683c57c05f01e084e026aa0908..e23b3eebf2fd2d74e69240e782e4b99a659a9ec4 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -2371,7 +2371,7 @@ EXPORT void HWRAPI(MakeScreenTexture) (void)
 	Clamp2D(GL_TEXTURE_WRAP_S);
 	Clamp2D(GL_TEXTURE_WRAP_T);
 #ifndef KOS_GL_COMPATIBILITY
-	pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, texsize, texsize, 0);
+	pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
 #endif
 
 	tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now
@@ -2399,7 +2399,7 @@ EXPORT void HWRAPI(MakeScreenFinalTexture) (void)
 	Clamp2D(GL_TEXTURE_WRAP_S);
 	Clamp2D(GL_TEXTURE_WRAP_T);
 #ifndef KOS_GL_COMPATIBILITY
-	pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, texsize, texsize, 0);
+	pglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, texsize, texsize, 0);
 #endif
 
 	tex_downloaded = 0; // 0 so it knows it doesn't have any of the cached patches downloaded right now
diff --git a/src/info.c b/src/info.c
index 7759960920c0534077b1aa1386715760ae347c52..10ce319bf08cebcf0d5a6df2405af6b7e9b44baf 100644
--- a/src/info.c
+++ b/src/info.c
@@ -64,9 +64,12 @@ char spr2names[NUMPLAYERSPRITES][5] =
 	"RUN_",
 	"PAIN",
 	"DEAD",
+	"DRWN",
 	"SPIN",
+	"DASH",
 	"GASP",
 	"JUMP",
+	"SPNG",
 	"FALL",
 	"EDGE",
 	"RIDE",
@@ -85,8 +88,18 @@ char spr2names[NUMPLAYERSPRITES][5] =
 	"SSTD",
 	"SWLK",
 	"SRUN",
+	"SPAN",
+	"SMSL",
+	"SDTH",
+	"SDRN",
+	"SSPN",
+	"SGSP",
+	"SJMP",
+	"SSPG",
+	"SFAL",
 	"SEDG",
-	"SHIT"
+	"SRID",
+	"SFLT"
 };
 
 // Doesn't work with g++, needs actionf_p1 (don't modify this comment)
@@ -114,32 +127,49 @@ state_t states[NUMSTATES] =
 	{SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL}, // S_THOK
 
 	// Player
-	{SPR_PLAY, SPR2_STND, 105, {NULL},   0, 0, S_PLAY_WAIT}, // S_PLAY_STND
-	{SPR_PLAY, SPR2_WAIT,  16, {NULL},   0, 0, S_PLAY_WAIT}, // S_PLAY_WAIT
-	{SPR_PLAY, SPR2_WALK,   4, {NULL},   0, 0, S_PLAY_WALK}, // S_PLAY_WALK
-	{SPR_PLAY, SPR2_RUN ,   2, {NULL},   0, 0, S_PLAY_RUN},  // S_PLAY_RUN
-	{SPR_PLAY, SPR2_PAIN, 350, {NULL},   0, 0, S_PLAY_FALL}, // S_PLAY_PAIN
-	{SPR_PLAY, SPR2_DEAD,   4, {A_Fall}, 0, 0, S_PLAY_DEAD}, // S_PLAY_DEAD
-	{SPR_PLAY, SPR2_SPIN,   1, {NULL},   0, 0, S_PLAY_SPIN}, // S_PLAY_SPIN
-	{SPR_PLAY, SPR2_GASP,  14, {NULL},   0, 0, S_PLAY_WALK}, // S_PLAY_GASP
-	{SPR_PLAY, SPR2_JUMP,  -1, {NULL},   0, 0, S_PLAY_FALL}, // S_PLAY_JUMP
-	{SPR_PLAY, SPR2_FALL,   2, {NULL},   0, 0, S_PLAY_FALL}, // S_PLAY_FALL
-	{SPR_PLAY, SPR2_EDGE,  12, {NULL},   0, 0, S_PLAY_EDGE}, // S_PLAY_EDGE
-	{SPR_PLAY, SPR2_RIDE,   4, {NULL},   0, 0, S_PLAY_RIDE}, // S_PLAY_RIDE
-
-	{SPR_PLAY, SPR2_FLY ,   2, {NULL},   0, 0, S_PLAY_FLY},  // S_PLAY_FLY
-	{SPR_PLAY, SPR2_TIRE,  12, {NULL},   0, 0, S_PLAY_FLY_TIRED}, // S_PLAY_FLY_TIRED
-
-	{SPR_PLAY, SPR2_GLID,   2, {NULL},   0, 0, S_PLAY_GLIDE}, // S_PLAY_GLIDE
-	{SPR_PLAY, SPR2_CLNG,   6, {NULL},   0, 0, S_PLAY_CLING}, // S_PLAY_CLING
-	{SPR_PLAY, SPR2_CLMB,   5, {NULL},   0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB
-
-	{SPR_PLAY, SPR2_SSTD,   7, {NULL},   0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_STND
-	{SPR_PLAY, SPR2_SWLK,   7, {NULL},   0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_WALK
-	{SPR_PLAY, SPR2_SRUN,   7, {NULL},   0, 0, S_PLAY_SUPER_RUN},  // S_PLAY_SUPER_RUN
-	{SPR_PLAY, SPR2_SEDG,  12, {NULL},   0, 0, S_PLAY_SUPER_EDGE}, // S_PLAY_SUPER_EDGE
-	{SPR_PLAY, SPR2_SHIT,  -1, {NULL},   0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_PAIN
-
+	{SPR_PLAY, SPR2_STND, 105, {NULL}, 0, 0, S_PLAY_WAIT}, // S_PLAY_STND
+	{SPR_PLAY, SPR2_WAIT,  16, {NULL}, 0, 0, S_PLAY_WAIT}, // S_PLAY_WAIT
+	{SPR_PLAY, SPR2_WALK,   4, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_WALK
+	{SPR_PLAY, SPR2_RUN ,   2, {NULL}, 0, 0, S_PLAY_RUN},  // S_PLAY_RUN
+	{SPR_PLAY, SPR2_PAIN, 350, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_PAIN
+	{SPR_PLAY, SPR2_DEAD,   4, {NULL}, 0, 0, S_PLAY_DEAD}, // S_PLAY_DEAD
+	{SPR_PLAY, SPR2_DRWN,   4, {NULL}, 0, 0, S_PLAY_DRWN}, // S_PLAY_DRWN
+	{SPR_PLAY, SPR2_SPIN,   1, {NULL}, 0, 0, S_PLAY_SPIN}, // S_PLAY_SPIN
+	{SPR_PLAY, SPR2_DASH,   2, {NULL}, 0, 0, S_PLAY_DASH}, // S_PLAY_DASH
+	{SPR_PLAY, SPR2_GASP,  14, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_GASP
+	{SPR_PLAY, SPR2_JUMP,   1, {NULL}, 0, 0, S_PLAY_JUMP}, // S_PLAY_JUMP
+	{SPR_PLAY, SPR2_SPNG,   2, {NULL}, 0, 0, S_PLAY_SPRING}, // S_PLAY_SPRING
+	{SPR_PLAY, SPR2_FALL,   2, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_FALL
+	{SPR_PLAY, SPR2_EDGE,  12, {NULL}, 0, 0, S_PLAY_EDGE}, // S_PLAY_EDGE
+	{SPR_PLAY, SPR2_RIDE,   4, {NULL}, 0, 0, S_PLAY_RIDE}, // S_PLAY_RIDE
+
+	// Tails abilities
+	{SPR_PLAY, SPR2_FLY ,   2, {NULL}, 0, 0, S_PLAY_FLY},  // S_PLAY_FLY
+	{SPR_PLAY, SPR2_TIRE,  12, {NULL}, 0, 0, S_PLAY_FLY_TIRED}, // S_PLAY_FLY_TIRED
+
+	// Knuckles abilities
+	{SPR_PLAY, SPR2_GLID,   2, {NULL}, 0, 0, S_PLAY_GLIDE}, // S_PLAY_GLIDE
+	{SPR_PLAY, SPR2_CLNG,   6, {NULL}, 0, 0, S_PLAY_CLING}, // S_PLAY_CLING
+	{SPR_PLAY, SPR2_CLMB,   5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB
+
+	// Super Sonic
+	{SPR_PLAY, SPR2_SSTD,   7, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_STND
+	{SPR_PLAY, SPR2_SWLK,   7, {NULL}, 0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_WALK
+	{SPR_PLAY, SPR2_SRUN,   7, {NULL}, 0, 0, S_PLAY_SUPER_RUN},  // S_PLAY_SUPER_RUN
+	{SPR_PLAY, SPR2_SPAN,  -1, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_PAIN
+	{SPR_PLAY, SPR2_SMSL,  -1, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_STUN
+	{SPR_PLAY, SPR2_SDTH,   4, {NULL}, 0, 0, S_PLAY_SUPER_DEAD}, // S_PLAY_SUPER_DEAD
+	{SPR_PLAY, SPR2_SDRN,   4, {NULL}, 0, 0, S_PLAY_SUPER_DRWN}, // S_PLAY_SUPER_DRWN
+	{SPR_PLAY, SPR2_SSPN,   1, {NULL}, 0, 0, S_PLAY_SUPER_SPIN}, // S_PLAY_SUPER_SPIN
+	{SPR_PLAY, SPR2_SGSP,  14, {NULL}, 0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_GASP
+	{SPR_PLAY, SPR2_SJMP,   1, {NULL}, 0, 0, S_PLAY_SUPER_JUMP}, // S_PLAY_SUPER_JUMP
+	{SPR_PLAY, SPR2_SSPG,   2, {NULL}, 0, 0, S_PLAY_SUPER_SPRING}, // S_PLAY_SUPER_SPRING
+	{SPR_PLAY, SPR2_SFAL,   2, {NULL}, 0, 0, S_PLAY_SUPER_FALL}, // S_PLAY_SUPER_FALL
+	{SPR_PLAY, SPR2_SEDG,  12, {NULL}, 0, 0, S_PLAY_SUPER_EDGE}, // S_PLAY_SUPER_EDGE
+	{SPR_PLAY, SPR2_SRID,   4, {NULL}, 0, 0, S_PLAY_SUPER_RIDE}, // S_PLAY_SUPER_RIDE
+	{SPR_PLAY, SPR2_SFLT,   7, {NULL}, 0, 0, S_PLAY_SUPER_FLOAT}, // S_PLAY_SUPER_FLOAT
+
+	// Transforming into Super
 	{SPR_PLAY, SPR2_TRNS,                4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS2}, // S_PLAY_SUPER_TRANS
 	{SPR_PLAY, SPR2_TRNS,                4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS3}, // S_PLAY_SUPER_TRANS2
 	{SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT,  4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS4}, // S_PLAY_SUPER_TRANS3
@@ -3130,8 +3160,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_PLAY_SPIN,    // missilestate
-		S_PLAY_DEAD,     // deathstate
-		S_NULL,         // xdeathstate
+		S_PLAY_DEAD,    // deathstate
+		S_PLAY_DRWN,    // xdeathstate
 		sfx_None,       // deathsound
 		1,              // speed
 		16*FRACUNIT,    // radius
@@ -3400,7 +3430,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_NULL,         // deathstate
+		S_XPLD1,        // deathstate
 		S_DETON16,      // xdeathstate
 		sfx_pop,        // deathsound
 		1*FRACUNIT,     // speed
diff --git a/src/info.h b/src/info.h
index 44a3dd012bb83fcab932329d3a2eebb935f482ae..306b928e5ec1f93a2967974262f00f36846b80ee 100644
--- a/src/info.h
+++ b/src/info.h
@@ -583,9 +583,12 @@ enum playersprite
 	SPR2_RUN ,
 	SPR2_PAIN,
 	SPR2_DEAD,
+	SPR2_DRWN,
 	SPR2_SPIN,
+	SPR2_DASH,
 	SPR2_GASP,
 	SPR2_JUMP,
+	SPR2_SPNG, // spring
 	SPR2_FALL,
 	SPR2_EDGE,
 	SPR2_RIDE,
@@ -604,8 +607,18 @@ enum playersprite
 	SPR2_SSTD,
 	SPR2_SWLK,
 	SPR2_SRUN,
+	SPR2_SPAN,
+	SPR2_SMSL,
+	SPR2_SDTH,
+	SPR2_SDRN,
+	SPR2_SSPN,
+	SPR2_SGSP,
+	SPR2_SJMP,
+	SPR2_SSPG,
+	SPR2_SFAL,
 	SPR2_SEDG,
-	SPR2_SHIT,
+	SPR2_SRID,
+	SPR2_SFLT,
 
 	NUMPLAYERSPRITES
 };
@@ -634,9 +647,12 @@ typedef enum state
 	S_PLAY_RUN,
 	S_PLAY_PAIN,
 	S_PLAY_DEAD,
+	S_PLAY_DRWN,
 	S_PLAY_SPIN,
+	S_PLAY_DASH,
 	S_PLAY_GASP,
-	S_PLAY_JUMP,
+	S_PLAY_JUMP, // spin jump (todo: make jump separate from spring up for non-spin chars too?)
+	S_PLAY_SPRING,
 	S_PLAY_FALL,
 	S_PLAY_EDGE,
 	S_PLAY_RIDE,
@@ -654,8 +670,18 @@ typedef enum state
 	S_PLAY_SUPER_STND,
 	S_PLAY_SUPER_WALK,
 	S_PLAY_SUPER_RUN,
-	S_PLAY_SUPER_EDGE,
 	S_PLAY_SUPER_PAIN,
+	S_PLAY_SUPER_STUN,
+	S_PLAY_SUPER_DEAD,
+	S_PLAY_SUPER_DRWN,
+	S_PLAY_SUPER_SPIN,
+	S_PLAY_SUPER_GASP,
+	S_PLAY_SUPER_JUMP, // see note above
+	S_PLAY_SUPER_SPRING,
+	S_PLAY_SUPER_FALL,
+	S_PLAY_SUPER_EDGE,
+	S_PLAY_SUPER_RIDE,
+	S_PLAY_SUPER_FLOAT,
 
 	// SF_SUPER
 	S_PLAY_SUPER_TRANS,
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 9b0a34f17bb2c35a3a3e64245e2c4b3075a51379..4be1031065b86c54c851a562c4a1990fa8684d79 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -85,13 +85,6 @@ static int lib_print(lua_State *L)
 	return 0;
 }
 
-static int lib_evalMath(lua_State *L)
-{
-	const char *word = luaL_checkstring(L, 1);
-	lua_pushinteger(L, LUA_EvalMath(word));
-	return 1;
-}
-
 // M_RANDOM
 //////////////
 
@@ -138,25 +131,25 @@ static int lib_pRandomRange(lua_State *L)
 
 static int lib_pAproxDistance(lua_State *L)
 {
-	fixed_t dx = (fixed_t)luaL_checkinteger(L, 1);
-	fixed_t dy = (fixed_t)luaL_checkinteger(L, 2);
+	fixed_t dx = luaL_checkfixed(L, 1);
+	fixed_t dy = luaL_checkfixed(L, 2);
 	//HUDSAFE
-	lua_pushinteger(L, P_AproxDistance(dx, dy));
+	lua_pushfixed(L, P_AproxDistance(dx, dy));
 	return 1;
 }
 
 static int lib_pClosestPointOnLine(lua_State *L)
 {
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
+	fixed_t x = luaL_checkfixed(L, 1);
+	fixed_t y = luaL_checkfixed(L, 2);
 	line_t *line = *((line_t **)luaL_checkudata(L, 3, META_LINE));
 	vertex_t result;
 	//HUDSAFE
 	if (!line)
 		return LUA_ErrInvalid(L, "line_t");
 	P_ClosestPointOnLine(x, y, line, &result);
-	lua_pushinteger(L, result.x);
-	lua_pushinteger(L, result.y);
+	lua_pushfixed(L, result.x);
+	lua_pushfixed(L, result.y);
 	return 2;
 }
 
@@ -241,9 +234,9 @@ static int lib_pLookForPlayers(lua_State *L)
 
 static int lib_pSpawnMobj(lua_State *L)
 {
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
-	fixed_t z = (fixed_t)luaL_checkinteger(L, 3);
+	fixed_t x = luaL_checkfixed(L, 1);
+	fixed_t y = luaL_checkfixed(L, 2);
+	fixed_t z = luaL_checkfixed(L, 3);
 	mobjtype_t type = luaL_checkinteger(L, 4);
 	NOHUD
 	if (type > MT_LASTFREESLOT)
@@ -283,9 +276,9 @@ static int lib_pSpawnXYZMissile(lua_State *L)
 	mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
 	mobj_t *dest = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
 	mobjtype_t type = luaL_checkinteger(L, 3);
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 4);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 5);
-	fixed_t z = (fixed_t)luaL_checkinteger(L, 6);
+	fixed_t x = luaL_checkfixed(L, 4);
+	fixed_t y = luaL_checkfixed(L, 5);
+	fixed_t z = luaL_checkfixed(L, 6);
 	NOHUD
 	if (!source || !dest)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -298,13 +291,13 @@ static int lib_pSpawnXYZMissile(lua_State *L)
 static int lib_pSpawnPointMissile(lua_State *L)
 {
 	mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	fixed_t xa = (fixed_t)luaL_checkinteger(L, 2);
-	fixed_t ya = (fixed_t)luaL_checkinteger(L, 3);
-	fixed_t za = (fixed_t)luaL_checkinteger(L, 4);
+	fixed_t xa = luaL_checkfixed(L, 2);
+	fixed_t ya = luaL_checkfixed(L, 3);
+	fixed_t za = luaL_checkfixed(L, 4);
 	mobjtype_t type = luaL_checkinteger(L, 5);
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 6);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 7);
-	fixed_t z = (fixed_t)luaL_checkinteger(L, 8);
+	fixed_t x = luaL_checkfixed(L, 6);
+	fixed_t y = luaL_checkfixed(L, 7);
+	fixed_t z = luaL_checkfixed(L, 8);
 	NOHUD
 	if (!source)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -318,9 +311,9 @@ static int lib_pSpawnAlteredDirectionMissile(lua_State *L)
 {
 	mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
 	mobjtype_t type = luaL_checkinteger(L, 2);
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 3);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 4);
-	fixed_t z = (fixed_t)luaL_checkinteger(L, 5);
+	fixed_t x = luaL_checkfixed(L, 3);
+	fixed_t y = luaL_checkfixed(L, 4);
+	fixed_t z = luaL_checkfixed(L, 5);
 	INT32 shiftingAngle = (INT32)luaL_checkinteger(L, 5);
 	NOHUD
 	if (!source)
@@ -348,7 +341,7 @@ static int lib_pSPMAngle(lua_State *L)
 {
 	mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
 	mobjtype_t type = luaL_checkinteger(L, 2);
-	angle_t angle = (angle_t)luaL_checkinteger(L, 3);
+	angle_t angle = luaL_checkangle(L, 3);
 	UINT8 allowaim = (UINT8)luaL_optinteger(L, 4, 0);
 	UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0);
 	NOHUD
@@ -418,13 +411,13 @@ static int lib_pGetClosestAxis(lua_State *L)
 
 static int lib_pSpawnParaloop(lua_State *L)
 {
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
-	fixed_t z = (fixed_t)luaL_checkinteger(L, 3);
-	fixed_t radius = (fixed_t)luaL_checkinteger(L, 4);
+	fixed_t x = luaL_checkfixed(L, 1);
+	fixed_t y = luaL_checkfixed(L, 2);
+	fixed_t z = luaL_checkfixed(L, 3);
+	fixed_t radius = luaL_checkfixed(L, 4);
 	INT32 number = (INT32)luaL_checkinteger(L, 5);
 	mobjtype_t type = luaL_checkinteger(L, 6);
-	angle_t rotangle = (angle_t)luaL_checkinteger(L, 7);
+	angle_t rotangle = luaL_checkangle(L, 7);
 	statenum_t nstate = luaL_optinteger(L, 8, S_NULL);
 	boolean spawncenter = lua_optboolean(L, 9);
 	NOHUD
@@ -458,7 +451,7 @@ static int lib_pSupermanLook4Players(lua_State *L)
 static int lib_pSetScale(lua_State *L)
 {
 	mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	fixed_t newscale = (fixed_t)luaL_checkinteger(L, 2);
+	fixed_t newscale = luaL_checkfixed(L, 2);
 	NOHUD
 	if (!mobj)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -526,7 +519,7 @@ static int lib_pGetPlayerHeight(lua_State *L)
 	//HUDSAFE
 	if (!player)
 		return LUA_ErrInvalid(L, "player_t");
-	lua_pushinteger(L, P_GetPlayerHeight(player));
+	lua_pushfixed(L, P_GetPlayerHeight(player));
 	return 1;
 }
 
@@ -536,7 +529,7 @@ static int lib_pGetPlayerSpinHeight(lua_State *L)
 	//HUDSAFE
 	if (!player)
 		return LUA_ErrInvalid(L, "player_t");
-	lua_pushinteger(L, P_GetPlayerSpinHeight(player));
+	lua_pushfixed(L, P_GetPlayerSpinHeight(player));
 	return 1;
 }
 
@@ -639,7 +632,7 @@ static int lib_pInQuicksand(lua_State *L)
 static int lib_pSetObjectMomZ(lua_State *L)
 {
 	mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	fixed_t value = (fixed_t)luaL_checkinteger(L, 2);
+	fixed_t value = luaL_checkfixed(L, 2);
 	boolean relative = lua_optboolean(L, 3);
 	NOHUD
 	if (!mo)
@@ -753,8 +746,8 @@ static int lib_pDoPlayerExit(lua_State *L)
 static int lib_pInstaThrust(lua_State *L)
 {
 	mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	angle_t angle = (angle_t)luaL_checkinteger(L, 2);
-	fixed_t move = (fixed_t)luaL_checkinteger(L, 3);
+	angle_t angle = luaL_checkangle(L, 2);
+	fixed_t move = luaL_checkfixed(L, 3);
 	NOHUD
 	if (!mo)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -768,10 +761,10 @@ static int lib_pReturnThrustX(lua_State *L)
 	fixed_t move;
 	if (lua_isnil(L, 1) || lua_isuserdata(L, 1))
 		lua_remove(L, 1); // ignore mobj as arg1
-	angle = (angle_t)luaL_checkinteger(L, 1);
-	move = (fixed_t)luaL_checkinteger(L, 2);
+	angle = luaL_checkangle(L, 1);
+	move = luaL_checkfixed(L, 2);
 	//HUDSAFE
-	lua_pushinteger(L, P_ReturnThrustX(NULL, angle, move));
+	lua_pushfixed(L, P_ReturnThrustX(NULL, angle, move));
 	return 1;
 }
 
@@ -781,10 +774,10 @@ static int lib_pReturnThrustY(lua_State *L)
 	fixed_t move;
 	if (lua_isnil(L, 1) || lua_isuserdata(L, 1))
 		lua_remove(L, 1); // ignore mobj as arg1
-	angle = (angle_t)luaL_checkinteger(L, 1);
-	move = (fixed_t)luaL_checkinteger(L, 2);
+	angle = luaL_checkangle(L, 1);
+	move = luaL_checkfixed(L, 2);
 	//HUDSAFE
-	lua_pushinteger(L, P_ReturnThrustY(NULL, angle, move));
+	lua_pushfixed(L, P_ReturnThrustY(NULL, angle, move));
 	return 1;
 }
 
@@ -802,7 +795,7 @@ static int lib_pNukeEnemies(lua_State *L)
 {
 	mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
 	mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
-	fixed_t radius = (fixed_t)luaL_checkinteger(L, 3);
+	fixed_t radius = luaL_checkfixed(L, 3);
 	NOHUD
 	if (!inflictor || !source)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -868,8 +861,8 @@ static int lib_pSpawnSpinMobj(lua_State *L)
 static int lib_pTelekinesis(lua_State *L)
 {
 	player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
-	fixed_t thrust = (fixed_t)luaL_checkinteger(L, 2);
-	fixed_t range = (fixed_t)luaL_checkinteger(L, 3);
+	fixed_t thrust = luaL_checkfixed(L, 2);
+	fixed_t range = luaL_checkfixed(L, 3);
 	NOHUD
 	if (!player)
 		return LUA_ErrInvalid(L, "player_t");
@@ -884,8 +877,8 @@ static int lib_pCheckPosition(lua_State *L)
 {
 	mobj_t *ptmthing = tmthing;
 	mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 2);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 3);
+	fixed_t x = luaL_checkfixed(L, 2);
+	fixed_t y = luaL_checkfixed(L, 3);
 	NOHUD
 	if (!thing)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -899,8 +892,8 @@ static int lib_pTryMove(lua_State *L)
 {
 	mobj_t *ptmthing = tmthing;
 	mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 2);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 3);
+	fixed_t x = luaL_checkfixed(L, 2);
+	fixed_t y = luaL_checkfixed(L, 3);
 	boolean allowdropoff = lua_optboolean(L, 4);
 	NOHUD
 	if (!thing)
@@ -915,7 +908,7 @@ static int lib_pMove(lua_State *L)
 {
 	mobj_t *ptmthing = tmthing;
 	mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	fixed_t speed = (fixed_t)luaL_checkinteger(L, 2);
+	fixed_t speed = luaL_checkfixed(L, 2);
 	NOHUD
 	if (!actor)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -929,9 +922,9 @@ static int lib_pTeleportMove(lua_State *L)
 {
 	mobj_t *ptmthing = tmthing;
 	mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 2);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 3);
-	fixed_t z = (fixed_t)luaL_checkinteger(L, 4);
+	fixed_t x = luaL_checkfixed(L, 2);
+	fixed_t y = luaL_checkfixed(L, 3);
+	fixed_t z = luaL_checkfixed(L, 4);
 	NOHUD
 	if (!thing)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -975,10 +968,10 @@ static int lib_pCheckSight(lua_State *L)
 static int lib_pCheckHoopPosition(lua_State *L)
 {
 	mobj_t *hoopthing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 2);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 3);
-	fixed_t z = (fixed_t)luaL_checkinteger(L, 4);
-	fixed_t radius = (fixed_t)luaL_checkinteger(L, 5);
+	fixed_t x = luaL_checkfixed(L, 2);
+	fixed_t y = luaL_checkfixed(L, 3);
+	fixed_t z = luaL_checkfixed(L, 4);
+	fixed_t radius = luaL_checkfixed(L, 5);
 	NOHUD
 	if (!hoopthing)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -990,7 +983,7 @@ static int lib_pRadiusAttack(lua_State *L)
 {
 	mobj_t *spot = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
 	mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
-	fixed_t damagedist = (fixed_t)luaL_checkinteger(L, 3);
+	fixed_t damagedist = luaL_checkfixed(L, 3);
 	NOHUD
 	if (!spot || !source)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -1000,12 +993,12 @@ static int lib_pRadiusAttack(lua_State *L)
 
 static int lib_pFloorzAtPos(lua_State *L)
 {
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
-	fixed_t z = (fixed_t)luaL_checkinteger(L, 3);
-	fixed_t height = (fixed_t)luaL_checkinteger(L, 4);
+	fixed_t x = luaL_checkfixed(L, 1);
+	fixed_t y = luaL_checkfixed(L, 2);
+	fixed_t z = luaL_checkfixed(L, 3);
+	fixed_t height = luaL_checkfixed(L, 4);
 	//HUDSAFE
-	lua_pushinteger(L, P_FloorzAtPos(x, y, z, height));
+	lua_pushfixed(L, P_FloorzAtPos(x, y, z, height));
 	return 1;
 }
 
@@ -1016,8 +1009,8 @@ static int lib_pDoSpring(lua_State *L)
 	NOHUD
 	if (!spring || !object)
 		return LUA_ErrInvalid(L, "mobj_t");
-	P_DoSpring(spring, object);
-	return 0;
+	lua_pushboolean(L, P_DoSpring(spring, object));
+	return 1;
 }
 
 // P_INTER
@@ -1213,8 +1206,8 @@ static int lib_pDoNightsScore(lua_State *L)
 static int lib_pThrust(lua_State *L)
 {
 	mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
-	angle_t angle = (angle_t)luaL_checkinteger(L, 2);
-	fixed_t move = (fixed_t)luaL_checkinteger(L, 3);
+	angle_t angle = luaL_checkangle(L, 2);
+	fixed_t move = luaL_checkfixed(L, 3);
 	NOHUD
 	if (!mo)
 		return LUA_ErrInvalid(L, "mobj_t");
@@ -1489,48 +1482,48 @@ static int lib_evCrumbleChain(lua_State *L)
 
 static int lib_rPointToAngle(lua_State *L)
 {
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
+	fixed_t x = luaL_checkfixed(L, 1);
+	fixed_t y = luaL_checkfixed(L, 2);
 	//HUDSAFE
-	lua_pushinteger(L, R_PointToAngle(x, y));
+	lua_pushangle(L, R_PointToAngle(x, y));
 	return 1;
 }
 
 static int lib_rPointToAngle2(lua_State *L)
 {
-	fixed_t px2 = (fixed_t)luaL_checkinteger(L, 1);
-	fixed_t py2 = (fixed_t)luaL_checkinteger(L, 2);
-	fixed_t px1 = (fixed_t)luaL_checkinteger(L, 3);
-	fixed_t py1 = (fixed_t)luaL_checkinteger(L, 4);
+	fixed_t px2 = luaL_checkfixed(L, 1);
+	fixed_t py2 = luaL_checkfixed(L, 2);
+	fixed_t px1 = luaL_checkfixed(L, 3);
+	fixed_t py1 = luaL_checkfixed(L, 4);
 	//HUDSAFE
-	lua_pushinteger(L, R_PointToAngle2(px2, py2, px1, py1));
+	lua_pushangle(L, R_PointToAngle2(px2, py2, px1, py1));
 	return 1;
 }
 
 static int lib_rPointToDist(lua_State *L)
 {
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
+	fixed_t x = luaL_checkfixed(L, 1);
+	fixed_t y = luaL_checkfixed(L, 2);
 	//HUDSAFE
-	lua_pushinteger(L, R_PointToDist(x, y));
+	lua_pushfixed(L, R_PointToDist(x, y));
 	return 1;
 }
 
 static int lib_rPointToDist2(lua_State *L)
 {
-	fixed_t px2 = (fixed_t)luaL_checkinteger(L, 1);
-	fixed_t py2 = (fixed_t)luaL_checkinteger(L, 2);
-	fixed_t px1 = (fixed_t)luaL_checkinteger(L, 3);
-	fixed_t py1 = (fixed_t)luaL_checkinteger(L, 4);
+	fixed_t px2 = luaL_checkfixed(L, 1);
+	fixed_t py2 = luaL_checkfixed(L, 2);
+	fixed_t px1 = luaL_checkfixed(L, 3);
+	fixed_t py1 = luaL_checkfixed(L, 4);
 	//HUDSAFE
-	lua_pushinteger(L, R_PointToDist2(px2, py2, px1, py1));
+	lua_pushfixed(L, R_PointToDist2(px2, py2, px1, py1));
 	return 1;
 }
 
 static int lib_rPointInSubsector(lua_State *L)
 {
-	fixed_t x = (fixed_t)luaL_checkinteger(L, 1);
-	fixed_t y = (fixed_t)luaL_checkinteger(L, 2);
+	fixed_t x = luaL_checkfixed(L, 1);
+	fixed_t y = luaL_checkfixed(L, 2);
 	//HUDSAFE
 	LUA_PushUserdata(L, R_PointInSubsector(x, y), META_SUBSECTOR);
 	return 1;
@@ -1664,7 +1657,7 @@ static int lib_sChangeMusic(lua_State *L)
 
 static int lib_sSpeedMusic(lua_State *L)
 {
-	fixed_t fixedspeed = (fixed_t)luaL_checkinteger(L, 1);
+	fixed_t fixedspeed = luaL_checkfixed(L, 1);
 	float speed = FIXED_TO_FLOAT(fixedspeed);
 	player_t *player = NULL;
 	NOHUD
@@ -1865,7 +1858,6 @@ static int lib_gTicsToMilliseconds(lua_State *L)
 
 static luaL_Reg lib[] = {
 	{"print", lib_print},
-	{"EvalMath", lib_evalMath},
 
 	// m_random
 	{"P_Random",lib_pRandom},
diff --git a/src/lua_hook.h b/src/lua_hook.h
index fae3bb7e6d1672a50f72d7d5e58c524bb65317c1..da2dcdc380461cefd958b9f42bfbe738a98d724b 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -41,7 +41,7 @@ enum hook {
 	hook_BotAI,
 	hook_LinedefExecute,
 	hook_PlayerMsg,
-	hook_DeathMsg,
+	hook_HurtMsg,
 
 	hook_MAX // last hook
 };
@@ -54,8 +54,9 @@ void LUAh_ThinkFrame(void); // Hook for frame (after mobj and player thinkers)
 boolean LUAh_MobjHook(mobj_t *mo, enum hook which);
 boolean LUAh_PlayerHook(player_t *plr, enum hook which);
 #define LUAh_MobjSpawn(mo) LUAh_MobjHook(mo, hook_MobjSpawn) // Hook for P_SpawnMobj by mobj type
-UINT8 LUAh_MobjCollide(mobj_t *thing1, mobj_t *thing2); // Hook for PIT_CheckThing by (thing) mobj type
-UINT8 LUAh_MobjMoveCollide(mobj_t *thing1, mobj_t *thing2); // Hook for PIT_CheckThing by (tmthing) mobj type
+UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which);
+#define LUAh_MobjCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjCollide) // Hook for PIT_CheckThing by (thing) mobj type
+#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
@@ -73,6 +74,6 @@ boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd
 boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name
 boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors
 boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages
-boolean LUAh_DeathMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages
+boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages
 
 #endif
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 532726ac223afa4d686029cc0917731e405c0cfc..0415d23e61acfe98705ec8855846b06297fcdf02 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -56,23 +56,40 @@ const char *const hookNames[hook_MAX+1] = {
 	NULL
 };
 
+// Hook metadata
+struct hook_s
+{
+	struct hook_s *next;
+	enum hook type;
+	UINT16 id;
+	union {
+		mobjtype_t mt;
+		char *skinname;
+		char *funcname;
+	} s;
+	boolean error;
+};
+typedef struct hook_s* hook_p;
+
+#define FMT_HOOKID "hook_%d"
+
+hook_p roothook;
+
 // Takes hook, function, and additional arguments (mobj type to act on, etc.)
 static int lib_addHook(lua_State *L)
 {
-	UINT16 hook;
-	boolean notable = false;
-	boolean subtable = false;
-	UINT32 subindex = 0;
-	char *subfield = NULL;
-	const char *lsubfield = NULL;
+	static struct hook_s hook = {NULL, 0, 0, {0}, false};
+	hook_p hookp, *lastp;
+
+	hook.type = luaL_checkoption(L, 1, NULL, hookNames);
+	lua_remove(L, 1);
 
-	hook = (UINT16)luaL_checkoption(L, 1, NULL, hookNames);
-	luaL_checktype(L, 2, LUA_TFUNCTION);
+	luaL_checktype(L, 1, LUA_TFUNCTION);
 
 	if (hud_running)
 		return luaL_error(L, "HUD rendering code should not call this function!");
 
-	switch(hook)
+	switch(hook.type)
 	{
 	// Take a mobjtype enum which this hook is specifically for.
 	case hook_MobjSpawn:
@@ -87,918 +104,668 @@ static int lib_addHook(lua_State *L)
 	case hook_MobjDeath:
 	case hook_BossDeath:
 	case hook_MobjRemoved:
-		subtable = true;
-		if (lua_isnumber(L, 3))
-			subindex = (UINT32)luaL_checkinteger(L, 3);
-		else
-			lsubfield = "a";
-		lua_settop(L, 2);
+	case hook_HurtMsg:
+		hook.s.mt = MT_NULL;
+		if (lua_isnumber(L, 2))
+			hook.s.mt = lua_tonumber(L, 2);
 		break;
-	case hook_BotAI: // Only one AI function per skin, please!
-		notable = true;
-		subtable = true;
-		subfield = ZZ_Alloc(strlen(luaL_checkstring(L, 3))+1);
+	case hook_BotAI:
+		hook.s.skinname = NULL;
+		if (lua_isstring(L, 2))
 		{ // lowercase copy
-			char *p = subfield;
-			const char *s = luaL_checkstring(L, 3);
+			const char *s = lua_tostring(L, 2);
+			char *p = hook.s.skinname = ZZ_Alloc(strlen(s)+1);
 			do {
 				*p = tolower(*s);
 				++p;
 			} while(*(++s));
 			*p = 0;
 		}
-		lua_settop(L, 3);
 		break;
-	case hook_LinedefExecute: // Get one linedef executor function by name
-		notable = true;
-		subtable = true;
-		subfield = ZZ_Alloc(strlen(luaL_checkstring(L, 3))+1);
+	case hook_LinedefExecute: // Linedef executor functions
 		{ // uppercase copy
-			char *p = subfield;
-			const char *s = luaL_checkstring(L, 3);
+			const char *s = luaL_checkstring(L, 2);
+			char *p = hook.s.funcname = ZZ_Alloc(strlen(s)+1);
 			do {
 				*p = toupper(*s);
 				++p;
 			} while(*(++s));
 			*p = 0;
 		}
-		lua_settop(L, 3);
 		break;
 	default:
-		lua_settop(L, 2);
 		break;
 	}
+	lua_settop(L, 1); // lua stack contains only the function now.
 
-	lua_getfield(L, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(L, -1));
+	hooksAvailable[hook.type/8] |= 1<<(hook.type%8);
 
-	// This hook type only allows one entry, not an array of hooks.
-	// New hooks will overwrite the previous ones, and the stack is one table shorter.
-	if (notable)
+	// 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)
 	{
-		if (subtable)
-		{
-			lua_rawgeti(L, -1, hook);
-			lua_remove(L, -2); // pop "hook"
-			I_Assert(lua_istable(L, -1));
-			lua_pushvalue(L, 2);
-			if (subfield)
-				lua_setfield(L, -2, subfield);
-			else if (lsubfield)
-				lua_setfield(L, -2, lsubfield);
-			else
-				lua_rawseti(L, -2, subindex);
-		} else {
-			lua_pushvalue(L, 2);
-			lua_rawseti(L, -2, hook);
-		}
-		hooksAvailable[hook/8] |= 1<<(hook%8);
-		return 0;
+		if (hookp->id >= hook.id)
+			hook.id = hookp->id+1;
+		lastp = &hookp->next;
 	}
 
-	// Fetch the hook's table from the registry.
-	// It should always exist, since LUA_HookLib creates a table for every hook.
-	lua_rawgeti(L, -1, hook);
-	lua_remove(L, -2); // pop "hook"
-	I_Assert(lua_istable(L, -1));
-	if (subtable)
-	{
-		// Fetch a subtable based on index
-		if (subfield)
-			lua_getfield(L, -1, subfield);
-		else if (lsubfield)
-			lua_getfield(L, -1, lsubfield);
-		else
-			lua_rawgeti(L, -1, subindex);
-
-		// Subtable doesn't exist, make one now.
-		if (lua_isnil(L, -1))
-		{
-			lua_pop(L, 1);
-			lua_newtable(L);
-
-			// Store a link to the subtable for later.
-			lua_pushvalue(L, -1);
-			if (subfield)
-				lua_setfield(L, -3, subfield);
-			else if (lsubfield)
-				lua_setfield(L, -3, lsubfield);
-			else
-				lua_rawseti(L, -3, subindex);
-	}	}
-
-	// Add function to the table.
-	lua_pushvalue(L, 2);
-	lua_rawseti(L, -2, (int)(lua_objlen(L, -2) + 1));
-
-	if (subfield)
-		Z_Free(subfield);
-
-	hooksAvailable[hook/8] |= 1<<(hook%8);
+	// allocate a permanent memory struct to stuff hook.
+	hookp = ZZ_Alloc(sizeof(struct hook_s));
+	memcpy(hookp, &hook, sizeof(struct hook_s));
+	// tack it onto the end of the linked list.
+	*lastp = hookp;
+
+	// set the hook function in the registry.
+	lua_pushfstring(L, FMT_HOOKID, hook.id);
+	lua_pushvalue(L, 1);
+	lua_settable(L, LUA_REGISTRYINDEX);
 	return 0;
 }
 
 int LUA_HookLib(lua_State *L)
 {
-	// Create all registry tables
-	enum hook i;
 	memset(hooksAvailable,0,sizeof(UINT8[(hook_MAX/8)+1]));
-
-	lua_newtable(L);
-	for (i = 0; i < hook_MAX; i++)
-	{
-		lua_newtable(L);
-		switch(i)
-		{
-		default:
-			break;
-		case hook_MobjSpawn:
-		case hook_MobjCollide:
-		case hook_MobjMoveCollide:
-		case hook_TouchSpecial:
-		case hook_MobjFuse:
-		case hook_MobjThinker:
-		case hook_BossThinker:
-		case hook_ShouldDamage:
-		case hook_MobjDamage:
-		case hook_MobjDeath:
-		case hook_BossDeath:
-		case hook_MobjRemoved:
-			lua_pushstring(L, "a");
-			lua_newtable(L);
-			lua_rawset(L, -3);
-			break;
-		}
-		lua_rawseti(L, -2, i);
-	}
-	lua_setfield(L, LUA_REGISTRYINDEX, "hook");
+	roothook = NULL;
 	lua_register(L, "addHook", lib_addHook);
 	return 0;
 }
 
 boolean LUAh_MobjHook(mobj_t *mo, enum hook which)
 {
+	hook_p hookp;
 	boolean hooked = false;
 	if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
 		return false;
 
-	// clear the stack (just in case)
-	lua_pop(gL, -1);
-
-	// hook table
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, which);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
-
-	// generic subtable
-	lua_pushstring(gL, "a");
-	lua_rawget(gL, -2);
-	I_Assert(lua_istable(gL, -1));
-
-	LUA_PushUserdata(gL, mo, META_MOBJ);
-	lua_pushnil(gL);
-	while (lua_next(gL, -3)) {
-		CONS_Debug(DBG_LUA, "MobjHook: Calling hook_%s for generic mobj types\n", hookNames[which]);
-		lua_pushvalue(gL, -3); // mo
-		// stack is: hook_Mobj table, subtable "a", mobj, i, function, mobj
-		if (lua_pcall(gL, 1, 1, 0)) {
-			// A run-time error occurred.
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
-			lua_pop(gL, 1);
-			// Remove this function from the hook table to prevent further errors.
-			lua_pushvalue(gL, -1); // key
-			lua_pushnil(gL); // value
-			lua_rawset(gL, -5); // table
-			CONS_Printf("Hook removed.\n");
-		}
-		else
-		{
-			if (lua_toboolean(gL, -1))
-				hooked = true;
-			lua_pop(gL, 1);
-		}
-	}
-	// stack is: hook_Mobj table, subtable "a", mobj
-	lua_remove(gL, -2); // pop subtable, leave mobj
-
-	// mobjtype subtable
-	// stack is: hook_Mobj table, mobj
-	lua_rawgeti(gL, -2, mo->type);
-	if (lua_isnil(gL, -1)) {
-		lua_pop(gL, 3); // pop hook_Mobj table, mobj, and nil
-		// the stack should now be empty.
-		return false;
-	}
-	lua_remove(gL, -3); // remove hook table
-	// stack is: mobj, mobjtype subtable
-	lua_insert(gL, lua_gettop(gL)-1); // swap subtable with mobj
-	// stack is: mobjtype subtable, mobj
-
-	lua_pushnil(gL);
-	while (lua_next(gL, -3)) {
-		CONS_Debug(DBG_LUA, "MobjHook: Calling hook_%s for mobj type %d\n", hookNames[which], mo->type);
-		lua_pushvalue(gL, -3); // mo
-		// stack is: mobjtype subtable, mobj, i, function, mobj
-		if (lua_pcall(gL, 1, 1, 0)) {
-			// A run-time error occurred.
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
-			lua_pop(gL, 1);
-			// Remove this function from the hook table to prevent further errors.
-			lua_pushvalue(gL, -1); // key
-			lua_pushnil(gL); // value
-			lua_rawset(gL, -5); // table
-			CONS_Printf("Hook removed.\n");
-		}
-		else
+	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))
 		{
+			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_pop(gL, 2); // pop mobj and subtable
-	// the stack should now be empty.
-
-	lua_gc(gL, LUA_GCSTEP, 3);
+	lua_settop(gL, 0);
 	return hooked;
 }
 
 boolean LUAh_PlayerHook(player_t *plr, enum hook which)
 {
+	hook_p hookp;
 	boolean hooked = false;
 	if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
 		return false;
 
-	// clear the stack (just in case)
-	lua_pop(gL, -1);
-
-	// hook table
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, which);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
+	lua_settop(gL, 0);
 
-	LUA_PushUserdata(gL, plr, META_PLAYER);
-
-	lua_pushnil(gL);
-	while (lua_next(gL, -3) != 0) {
-		lua_pushvalue(gL, -3); // player
-		if (lua_pcall(gL, 1, 1, 0)) { // pops hook function, player, pushes 1 return result
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == which)
+		{
+			if (lua_gettop(gL) == 0)
+				LUA_PushUserdata(gL, plr, META_PLAYER);
+			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);
-			continue;
 		}
-		if (lua_toboolean(gL, -1)) // if return true,
-			hooked = true; // override vanilla behavior
-		lua_pop(gL, 1); // pop return value
-	}
 
-	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCSTEP, 1);
+	lua_settop(gL, 0);
 	return hooked;
 }
 
 // Hook for map change (before load)
 void LUAh_MapChange(void)
 {
+	hook_p hookp;
 	if (!gL || !(hooksAvailable[hook_MapChange/8] & (1<<(hook_MapChange%8))))
 		return;
 
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_MapChange);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
-
+	lua_settop(gL, 0);
 	lua_pushinteger(gL, gamemap);
-	lua_pushnil(gL);
-	while (lua_next(gL, -3) != 0) {
-		lua_pushvalue(gL, -3); // gamemap
-		LUA_Call(gL, 1);
-	}
-	lua_pop(gL, 1);
-	lua_gc(gL, LUA_GCSTEP, 1);
+
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_MapChange)
+		{
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -2);
+			LUA_Call(gL, 1);
+		}
+
+	lua_settop(gL, 0);
 }
 
 // Hook for map load
 void LUAh_MapLoad(void)
 {
+	hook_p hookp;
 	if (!gL || !(hooksAvailable[hook_MapLoad/8] & (1<<(hook_MapLoad%8))))
 		return;
 
-	lua_pop(gL, -1);
+	lua_settop(gL, 0);
+	lua_pushinteger(gL, gamemap);
 
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_MapLoad);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_MapLoad)
+		{
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -2);
+			LUA_Call(gL, 1);
+		}
 
-	lua_pushinteger(gL, gamemap);
-	lua_pushnil(gL);
-	while (lua_next(gL, -3) != 0) {
-		lua_pushvalue(gL, -3); // gamemap
-		LUA_Call(gL, 1);
-	}
-	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCCOLLECT, 0);
+	lua_settop(gL, 0);
 }
 
 // Hook for Got_AddPlayer
 void LUAh_PlayerJoin(int playernum)
 {
+	hook_p hookp;
 	if (!gL || !(hooksAvailable[hook_PlayerJoin/8] & (1<<(hook_PlayerJoin%8))))
 		return;
 
-	lua_pop(gL, -1);
+	lua_settop(gL, 0);
+	lua_pushinteger(gL, playernum);
 
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_PlayerJoin);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_PlayerJoin)
+		{
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -2);
+			LUA_Call(gL, 1);
+		}
 
-	lua_pushinteger(gL, playernum);
-	lua_pushnil(gL);
-	while (lua_next(gL, -3) != 0) {
-		lua_pushvalue(gL, -3); // playernum
-		LUA_Call(gL, 1);
-	}
-	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCCOLLECT, 0);
+	lua_settop(gL, 0);
 }
 
 // Hook for frame (after mobj and player thinkers)
 void LUAh_ThinkFrame(void)
 {
+	hook_p hookp;
 	if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8))))
 		return;
 
-	lua_pop(gL, -1);
-
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_ThinkFrame);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
-
-	lua_pushnil(gL);
-	while (lua_next(gL, -2) != 0)
-	{
-		//LUA_Call(gL, 0);
-		if (lua_pcall(gL, 0, 0, 0))
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_ThinkFrame)
 		{
-			// A run-time error occurred.
-			CONS_Alert(CONS_WARNING,"%s\n", lua_tostring(gL, -1));
-			lua_pop(gL, 1);
-			// Remove this function from the hook table to prevent further errors.
-			lua_pushvalue(gL, -1); // key
-			lua_pushnil(gL); // value
-			lua_rawset(gL, -4); // table
-			CONS_Printf("Hook removed.\n");
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			if (lua_pcall(gL, 0, 0, 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;
+			}
 		}
-	}
-	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCCOLLECT, 0);
 }
 
-// Hook for PIT_CheckThing by (thing) mobj type (thing1 = thing, thing2 = tmthing)
-UINT8 LUAh_MobjCollide(mobj_t *thing1, mobj_t *thing2)
+// Hook for mobj collisions
+UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which)
 {
+	hook_p hookp;
 	UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no.
-	if (!gL || !(hooksAvailable[hook_MobjCollide/8] & (1<<(hook_MobjCollide%8))))
-		return 0;
-
-	// clear the stack
-	lua_pop(gL, -1);
-
-	// hook table
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_MobjCollide);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
-
-	// mobjtype subtable
-	lua_rawgeti(gL, -1, thing1->type);
-	if (lua_isnil(gL, -1)) {
-		lua_pop(gL, 2);
-		return 0;
-	}
-	lua_remove(gL, -2); // remove hook table
-
-	LUA_PushUserdata(gL, thing1, META_MOBJ);
-	LUA_PushUserdata(gL, thing2, META_MOBJ);
-	lua_pushnil(gL);
-	while (lua_next(gL, -4)) {
-		lua_pushvalue(gL, -4); // thing1
-		lua_pushvalue(gL, -4); // thing2
-		if (lua_pcall(gL, 2, 1, 0)) {
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
-			lua_pop(gL, 1);
-			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); // pop return value
-	}
-	lua_pop(gL, 3); // pop arguments and mobjtype table
-
-	lua_gc(gL, LUA_GCSTEP, 1);
-	return shouldCollide;
-}
-
-// Hook for PIT_CheckThing by (tmthing) mobj type (thing1 = tmthing, thing2 = thing)
-UINT8 LUAh_MobjMoveCollide(mobj_t *thing1, mobj_t *thing2)
-{
-	UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no.
-	if (!gL || !(hooksAvailable[hook_MobjMoveCollide/8] & (1<<(hook_MobjMoveCollide%8))))
+	if (!gL || !(hooksAvailable[which/8] & (1<<(which%8))))
 		return 0;
 
-	// clear the stack
-	lua_pop(gL, -1);
-
-	// hook table
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_MobjMoveCollide);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
+	lua_settop(gL, 0);
 
-	// mobjtype subtable
-	lua_rawgeti(gL, -1, thing1->type);
-	if (lua_isnil(gL, -1)) {
-		lua_pop(gL, 2);
-		return 0;
-	}
-	lua_remove(gL, -2); // remove hook table
-
-	LUA_PushUserdata(gL, thing1, META_MOBJ);
-	LUA_PushUserdata(gL, thing2, META_MOBJ);
-	lua_pushnil(gL);
-	while (lua_next(gL, -4)) {
-		lua_pushvalue(gL, -4); // thing1
-		lua_pushvalue(gL, -4); // thing2
-		if (lua_pcall(gL, 2, 1, 0)) {
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == which
+		&& (hookp->s.mt == MT_NULL || hookp->s.mt == thing1->type))
+		{
+			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);
-			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); // pop return value
-	}
-	lua_pop(gL, 3); // pop arguments and mobjtype table
 
-	lua_gc(gL, LUA_GCSTEP, 1);
+	lua_settop(gL, 0);
 	return shouldCollide;
 }
 
 // Hook for P_TouchSpecialThing by mobj type
 boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher)
 {
+	hook_p hookp;
 	boolean hooked = false;
 	if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8))))
-		return false;
-
-	// clear the stack
-	lua_pop(gL, -1);
-
-	// get hook table
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_TouchSpecial);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
-
-	// get mobjtype subtable
-	lua_pushinteger(gL, special->type);
-	lua_rawget(gL, 1);
-	if (lua_isnil(gL, -1)) {
-		lua_pop(gL, 2);
-		return false;
-	}
-	lua_remove(gL, 1); // pop hook table off the stack
+		return 0;
 
-	LUA_PushUserdata(gL, special, META_MOBJ);
-	LUA_PushUserdata(gL, toucher, META_MOBJ);
+	lua_settop(gL, 0);
 
-	lua_pushnil(gL);
-	while (lua_next(gL, 1) != 0) {
-		lua_pushvalue(gL, 2); // special
-		lua_pushvalue(gL, 3); // toucher
-		if (lua_pcall(gL, 2, 1, 0)) { // pops hook function, special, toucher, pushes 1 return result
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_TouchSpecial
+		&& (hookp->s.mt == MT_NULL || hookp->s.mt == special->type))
+		{
+			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);
-			continue;
 		}
-		if (lua_toboolean(gL, -1)) // if return true,
-			hooked = true; // override vanilla behavior
-		lua_pop(gL, 1); // pop return value
-	}
 
-	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCSTEP, 1);
+	lua_settop(gL, 0);
 	return hooked;
 }
 
 // Hook for P_DamageMobj by mobj type (Should mobj take damage?)
 UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage)
 {
+	hook_p hookp;
 	UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no.
 	if (!gL || !(hooksAvailable[hook_ShouldDamage/8] & (1<<(hook_ShouldDamage%8))))
 		return 0;
 
-	// clear the stack
-	lua_pop(gL, -1);
-
-	// hook table
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_ShouldDamage);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
+	lua_settop(gL, 0);
 
-	// mobjtype subtable
-	lua_rawgeti(gL, -1, target->type);
-	if (lua_isnil(gL, -1)) {
-		lua_pop(gL, 2);
-		return 0;
-	}
-	lua_remove(gL, -2); // remove hook table
-
-	LUA_PushUserdata(gL, target, META_MOBJ);
-	LUA_PushUserdata(gL, inflictor, META_MOBJ);
-	LUA_PushUserdata(gL, source, META_MOBJ);
-	lua_pushinteger(gL, damage);
-	lua_pushnil(gL);
-	while (lua_next(gL, -6)) {
-		lua_pushvalue(gL, -6); // target
-		lua_pushvalue(gL, -6); // inflictor
-		lua_pushvalue(gL, -6); // source
-		lua_pushvalue(gL, -6); // damage
-		if (lua_pcall(gL, 4, 1, 0)) {
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_ShouldDamage
+		&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
+		{
+			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);
-			continue;
 		}
-		if (!lua_isnil(gL, -1))
-		{ // if nil, leave shouldDamage = 0.
-			if (lua_toboolean(gL, -1))
-				shouldDamage = 1; // Force yes
-			else
-				shouldDamage = 2; // Force no
-		}
-		lua_pop(gL, 1); // pop return value
-	}
-	lua_pop(gL, 5); // pop arguments and mobjtype table
 
-	lua_gc(gL, LUA_GCSTEP, 1);
+	lua_settop(gL, 0);
 	return shouldDamage;
 }
 
 // Hook for P_DamageMobj by mobj type (Mobj actually takes damage!)
 boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage)
 {
-	boolean handled = false;
+	hook_p hookp;
+	boolean hooked = false;
 	if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8))))
-		return false;
-
-	// clear the stack
-	lua_pop(gL, -1);
+		return 0;
 
-	// hook table
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_MobjDamage);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
+	lua_settop(gL, 0);
 
-	// mobjtype subtable
-	lua_rawgeti(gL, -1, target->type);
-	if (lua_isnil(gL, -1)) {
-		lua_pop(gL, 2);
-		return false;
-	}
-	lua_remove(gL, -2); // remove hook table
-
-	LUA_PushUserdata(gL, target, META_MOBJ);
-	LUA_PushUserdata(gL, inflictor, META_MOBJ);
-	LUA_PushUserdata(gL, source, META_MOBJ);
-	lua_pushinteger(gL, damage);
-	lua_pushnil(gL);
-	while (lua_next(gL, -6)) {
-		lua_pushvalue(gL, -6); // target
-		lua_pushvalue(gL, -6); // inflictor
-		lua_pushvalue(gL, -6); // source
-		lua_pushvalue(gL, -6); // damage
-		if (lua_pcall(gL, 4, 1, 0)) {
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_MobjDamage
+		&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
+		{
+			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);
-			continue;
 		}
-		if (lua_toboolean(gL, -1))
-			handled = true;
-		lua_pop(gL, 1); // pop return value
-	}
-	lua_pop(gL, 5); // pop arguments and mobjtype table
 
-	lua_gc(gL, LUA_GCSTEP, 1);
-	return handled;
+	lua_settop(gL, 0);
+	return hooked;
 }
 
 // Hook for P_KillMobj by mobj type
 boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source)
 {
-	boolean handled = false;
+	hook_p hookp;
+	boolean hooked = false;
 	if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8))))
-		return false;
-
-	// clear the stack
-	lua_pop(gL, -1);
+		return 0;
 
-	// hook table
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_MobjDeath);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
+	lua_settop(gL, 0);
 
-	// mobjtype subtable
-	lua_rawgeti(gL, -1, target->type);
-	if (lua_isnil(gL, -1)) {
-		lua_pop(gL, 2);
-		return false;
-	}
-	lua_remove(gL, -2); // remove hook table
-
-	LUA_PushUserdata(gL, target, META_MOBJ);
-	LUA_PushUserdata(gL, inflictor, META_MOBJ);
-	LUA_PushUserdata(gL, source, META_MOBJ);
-	lua_pushnil(gL);
-	while (lua_next(gL, -5)) {
-		lua_pushvalue(gL, -5); // target
-		lua_pushvalue(gL, -5); // inflictor
-		lua_pushvalue(gL, -5); // source
-		if (lua_pcall(gL, 3, 1, 0)) {
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_MobjDeath
+		&& (hookp->s.mt == MT_NULL || hookp->s.mt == target->type))
+		{
+			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);
-			continue;
 		}
-		if (lua_toboolean(gL, -1))
-			handled = true;
-		lua_pop(gL, 1); // pop return value
-	}
-	lua_pop(gL, 4); // pop arguments and mobjtype table
 
-	lua_gc(gL, LUA_GCSTEP, 1);
-	return handled;
+	lua_settop(gL, 0);
+	return hooked;
 }
 
 // Hook for B_BuildTiccmd
 boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd)
 {
+	hook_p hookp;
 	boolean hooked = false;
 	if (!gL || !(hooksAvailable[hook_BotTiccmd/8] & (1<<(hook_BotTiccmd%8))))
 		return false;
 
-	// clear the stack
-	lua_pop(gL, -1);
-
-	// hook table
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_BotTiccmd);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
-
-	LUA_PushUserdata(gL, bot, META_PLAYER);
-	LUA_PushUserdata(gL, cmd, META_TICCMD);
-
-	lua_pushnil(gL);
-	while (lua_next(gL, 1)) {
-		lua_pushvalue(gL, 2); // bot
-		lua_pushvalue(gL, 3); // cmd
-		if (lua_pcall(gL, 2, 1, 0)) {
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
+	lua_settop(gL, 0);
+
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_BotTiccmd)
+		{
+			if (lua_gettop(gL) == 0)
+			{
+				LUA_PushUserdata(gL, bot, META_PLAYER);
+				LUA_PushUserdata(gL, cmd, META_TICCMD);
+			}
+			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);
-			continue;
 		}
-		if (lua_toboolean(gL, -1))
-			hooked = true;
-		lua_pop(gL, 1); // pop return value
-	}
 
-	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCSTEP, 1);
+	lua_settop(gL, 0);
 	return hooked;
 }
 
 // Hook for B_BuildTailsTiccmd by skin name
 boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
 {
-	if (!gL || !tails->skin || !(hooksAvailable[hook_BotAI/8] & (1<<(hook_BotAI%8))))
-		return false;
-
-	// clear the stack
-	lua_pop(gL, -1);
-
-	// hook table
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_BotAI);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
-
-	// bot skin ai function
-	lua_getfield(gL, 1, ((skin_t *)tails->skin)->name);
-	if (lua_isnil(gL, -1)) {
-		lua_pop(gL, 2);
-		return false;
-	}
-	lua_remove(gL, 1); // pop the hook table
-
-	// Takes sonic, tails
-	// Returns forward, backward, left, right, jump, spin
-	LUA_PushUserdata(gL, sonic, META_MOBJ);
-	LUA_PushUserdata(gL, tails, META_MOBJ);
-	if (lua_pcall(gL, 2, 8, 0)) {
-		CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
-		lua_pop(gL,-1);
+	hook_p hookp;
+	boolean hooked = false;
+	if (!gL || !(hooksAvailable[hook_BotAI/8] & (1<<(hook_BotAI%8))))
 		return false;
-	}
 
-	// This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails.
-	if (lua_istable(gL, 1)) {
-		boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false;
+	lua_settop(gL, 0);
 
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_BotAI
+		&& (hookp->s.skinname == NULL || !strcmp(hookp->s.skinname, ((skin_t*)tails->skin)->name)))
+		{
+			if (lua_gettop(gL) == 0)
+			{
+				LUA_PushUserdata(gL, sonic, META_MOBJ);
+				LUA_PushUserdata(gL, tails, META_MOBJ);
+			}
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -3);
+			lua_pushvalue(gL, -3);
+			if (lua_pcall(gL, 2, 8, 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;
+			}
+
+			// This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails.
+			if (lua_istable(gL, 2+1)) {
+				boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false;
 #define CHECKFIELD(field) \
-		lua_getfield(gL, 1, #field);\
-		if (lua_toboolean(gL, -1))\
-			field = true;\
-		lua_pop(gL, 1);
-
-		CHECKFIELD(forward)
-		CHECKFIELD(backward)
-		CHECKFIELD(left)
-		CHECKFIELD(right)
-		CHECKFIELD(strafeleft)
-		CHECKFIELD(straferight)
-		CHECKFIELD(jump)
-		CHECKFIELD(spin)
-
+				lua_getfield(gL, 2+1, #field);\
+				if (lua_toboolean(gL, -1))\
+					field = true;\
+				lua_pop(gL, 1);
+
+				CHECKFIELD(forward)
+				CHECKFIELD(backward)
+				CHECKFIELD(left)
+				CHECKFIELD(right)
+				CHECKFIELD(strafeleft)
+				CHECKFIELD(straferight)
+				CHECKFIELD(jump)
+				CHECKFIELD(spin)
 #undef CHECKFIELD
+				B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin);
+			} else
+				B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, 2+1), lua_toboolean(gL, 2+2), lua_toboolean(gL, 2+3), lua_toboolean(gL, 2+4), lua_toboolean(gL, 2+5), lua_toboolean(gL, 2+6), lua_toboolean(gL, 2+7), lua_toboolean(gL, 2+8));
 
-		B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin);
-	} else
-		B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, 1), lua_toboolean(gL, 2), lua_toboolean(gL, 3), lua_toboolean(gL, 4), lua_toboolean(gL, 5), lua_toboolean(gL, 6), lua_toboolean(gL, 7), lua_toboolean(gL, 8));
+			lua_pop(gL, 8);
+			hooked = true;
+		}
 
-	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCSTEP, 1);
-	return true;
+	lua_settop(gL, 0);
+	return hooked;
 }
 
 // Hook for linedef executors
 boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
 {
+	hook_p hookp;
+	boolean hooked = false;
 	if (!gL || !(hooksAvailable[hook_LinedefExecute/8] & (1<<(hook_LinedefExecute%8))))
-		return false;
-
-	// clear the stack
-	lua_pop(gL, -1);
-
-	// get hook table
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_LinedefExecute);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
+		return 0;
 
-	// get function by line text
-	lua_getfield(gL, 1, line->text);
-	if (lua_isnil(gL, -1)) {
-		lua_pop(gL, 2);
-		return false;
-	}
-	lua_remove(gL, 1); // pop hook table off the stack
+	lua_settop(gL, 0);
 
-	LUA_PushUserdata(gL, line, META_LINE);
-	LUA_PushUserdata(gL, mo, META_MOBJ);
-	LUA_PushUserdata(gL, sector, META_SECTOR);
-	LUA_Call(gL, 3); // pops hook function, line, mo, sector
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_LinedefExecute
+		&& !strcmp(hookp->s.funcname, line->text))
+		{
+			if (lua_gettop(gL) == 0)
+			{
+				LUA_PushUserdata(gL, line, META_LINE);
+				LUA_PushUserdata(gL, mo, META_MOBJ);
+				LUA_PushUserdata(gL, sector, META_SECTOR);
+			}
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -4);
+			lua_pushvalue(gL, -4);
+			lua_pushvalue(gL, -4);
+			LUA_Call(gL, 3);
+			hooked = true;
+		}
 
-	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCSTEP, 1);
-	return true;
+	lua_settop(gL, 0);
+	return hooked;
 }
 
-// Hook for PlayerMsg -Red
+// Hook for player chat
 boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg)
 {
-	boolean handled = false;
-
+	hook_p hookp;
+	boolean hooked = false;
 	if (!gL || !(hooksAvailable[hook_PlayerMsg/8] & (1<<(hook_PlayerMsg%8))))
 		return false;
 
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_PlayerMsg);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
-
-	LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player
-
-	if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c
-		lua_pushinteger(gL, 3); // type
-		lua_pushnil(gL); // target
-	} else if (target == -1) { // sayteam
-		lua_pushinteger(gL, 1); // type
-		lua_pushnil(gL); // target
-	} else if (target == 0) { // say
-		lua_pushinteger(gL, 0); // type
-		lua_pushnil(gL); // target
-	} else { // sayto
-		lua_pushinteger(gL, 2); // type
-		LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target
-	}
-
-	lua_pushstring(gL, msg); // msg
+	lua_settop(gL, 0);
 
-	lua_pushnil(gL);
-
-	while (lua_next(gL, -6)) {
-		lua_pushvalue(gL, -6); // source
-		lua_pushvalue(gL, -6); // type
-		lua_pushvalue(gL, -6); // target
-		lua_pushvalue(gL, -6); // msg
-		if (lua_pcall(gL, 4, 1, 0)) {
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_PlayerMsg)
+		{
+			if (lua_gettop(gL) == 0)
+			{
+				LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player
+				if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c
+					lua_pushinteger(gL, 3); // type
+					lua_pushnil(gL); // target
+				} else if (target == -1) { // sayteam
+					lua_pushinteger(gL, 1); // type
+					lua_pushnil(gL); // target
+				} else if (target == 0) { // say
+					lua_pushinteger(gL, 0); // type
+					lua_pushnil(gL); // target
+				} else { // sayto
+					lua_pushinteger(gL, 2); // type
+					LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target
+				}
+				lua_pushstring(gL, msg); // msg
+			}
+			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);
-			continue;
 		}
-		if (lua_toboolean(gL, -1))
-			handled = true;
-		lua_pop(gL, 1); // pop return value
-	}
-	lua_pop(gL, 4); // pop arguments and mobjtype table
 
-	lua_gc(gL, LUA_GCSTEP, 1);
-	return handled;
+	lua_settop(gL, 0);
+	return hooked;
 }
 
-// Hook for hurt messages -Red
-// The internal name is DeathMsg, but the API name is "HurtMsg". Keep that in mind. (Should this be fixed at some point?)
-// @TODO This hook should be fixed to take mobj type at the addHook parameter to compare to inflictor. (I couldn't get this to work without crashing)
-boolean LUAh_DeathMsg(player_t *player, mobj_t *inflictor, mobj_t *source)
+// Hook for hurt messages
+boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source)
 {
-	boolean handled = false;
-
-	if (!gL || !(hooksAvailable[hook_DeathMsg/8] & (1<<(hook_DeathMsg%8))))
+	hook_p hookp;
+	boolean hooked = false;
+	if (!gL || !(hooksAvailable[hook_HurtMsg/8] & (1<<(hook_HurtMsg%8))))
 		return false;
 
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_DeathMsg);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
-
-	LUA_PushUserdata(gL, player, META_PLAYER); // Player
-	LUA_PushUserdata(gL, inflictor, META_MOBJ); // Inflictor
-	LUA_PushUserdata(gL, source, META_MOBJ); // Source
-
-	lua_pushnil(gL);
+	lua_settop(gL, 0);
 
-	while (lua_next(gL, -5)) {
-		lua_pushvalue(gL, -5); // player
-		lua_pushvalue(gL, -5); // inflictor
-		lua_pushvalue(gL, -5); // source
-		if (lua_pcall(gL, 3, 1, 0)) {
-			CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_HurtMsg
+		&& (hookp->s.mt == MT_NULL || (inflictor && hookp->s.mt == inflictor->type)))
+		{
+			if (lua_gettop(gL) == 0)
+			{
+				LUA_PushUserdata(gL, player, META_PLAYER);
+				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);
-			continue;
 		}
-		if (lua_toboolean(gL, -1))
-			handled = true;
-		lua_pop(gL, 1); // pop return value
-	}
-	lua_pop(gL, 3); // pop arguments and mobjtype table
 
-	lua_gc(gL, LUA_GCSTEP, 1);
-	return handled;
+	lua_settop(gL, 0);
+	return hooked;
 }
 
 #endif
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 86ff11337a6fcd02e763da75ee612eb5ee789d1d..5a83d95b56a6a3a39cf7d0364c39a2866964dd26 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -674,8 +674,6 @@ void LUAh_GameHUD(player_t *stplayr)
 		LUA_Call(gL, 3);
 	}
 	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCCOLLECT, 0);
-
 	hud_running = false;
 }
 
@@ -701,8 +699,6 @@ void LUAh_ScoresHUD(void)
 		LUA_Call(gL, 1);
 	}
 	lua_pop(gL, -1);
-	lua_gc(gL, LUA_GCCOLLECT, 0);
-
 	hud_running = false;
 }
 
diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index 61c64a8f69f195c6247406bcd8491b135691945d..a983bb00295a348e16dbabb77377c889e223bf17 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -175,8 +175,6 @@ static void A_Lua(mobj_t *actor)
 		--superstack;
 		superactions[superstack] = NULL;
 	}
-
-	lua_gc(gL, LUA_GCSTEP, 1);
 }
 
 // Arbitrary states[] table index -> state_t *
@@ -548,11 +546,11 @@ static int lib_setMobjInfo(lua_State *L)
 		else if (i == 15 || (str && fastcmp(str,"deathsound")))
 			info->deathsound = luaL_checkinteger(L, 3);
 		else if (i == 16 || (str && fastcmp(str,"speed")))
-			info->speed = (fixed_t)luaL_checkinteger(L, 3);
+			info->speed = luaL_checkfixed(L, 3);
 		else if (i == 17 || (str && fastcmp(str,"radius")))
-			info->radius = (fixed_t)luaL_checkinteger(L, 3);
+			info->radius = luaL_checkfixed(L, 3);
 		else if (i == 18 || (str && fastcmp(str,"height")))
-			info->height = (fixed_t)luaL_checkinteger(L, 3);
+			info->height = luaL_checkfixed(L, 3);
 		else if (i == 19 || (str && fastcmp(str,"dispoffset")))
 			info->dispoffset = (INT32)luaL_checkinteger(L, 3);
 		else if (i == 20 || (str && fastcmp(str,"mass")))
@@ -618,11 +616,11 @@ static int mobjinfo_get(lua_State *L)
 	else if (fastcmp(field,"deathsound"))
 		lua_pushinteger(L, info->deathsound);
 	else if (fastcmp(field,"speed"))
-		lua_pushinteger(L, info->speed);
+		lua_pushinteger(L, info->speed); // sometimes it's fixed_t, sometimes it's not...
 	else if (fastcmp(field,"radius"))
-		lua_pushinteger(L, info->radius);
+		lua_pushfixed(L, info->radius);
 	else if (fastcmp(field,"height"))
-		lua_pushinteger(L, info->height);
+		lua_pushfixed(L, info->height);
 	else if (fastcmp(field,"dispoffset"))
 		lua_pushinteger(L, info->dispoffset);
 	else if (fastcmp(field,"mass"))
@@ -694,11 +692,11 @@ static int mobjinfo_set(lua_State *L)
 	else if (fastcmp(field,"deathsound"))
 		info->deathsound = luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"speed"))
-		info->speed = (fixed_t)luaL_checkinteger(L, 3);
+		info->speed = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"radius"))
-		info->radius = (fixed_t)luaL_checkinteger(L, 3);
+		info->radius = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"height"))
-		info->height = (fixed_t)luaL_checkinteger(L, 3);
+		info->height = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"dispoffset"))
 		info->dispoffset = (INT32)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"mass"))
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index e5cc30c12571a3ce8f047f257add6fb0bf062841..38920c22328cefec06fcfb9d231dc13da0425d4c 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -280,10 +280,10 @@ static int sector_get(lua_State *L)
 		lua_pushboolean(L, 1);
 		return 1;
 	case sector_floorheight:
-		lua_pushinteger(L, sector->floorheight);
+		lua_pushfixed(L, sector->floorheight);
 		return 1;
 	case sector_ceilingheight:
-		lua_pushinteger(L, sector->ceilingheight);
+		lua_pushfixed(L, sector->ceilingheight);
 		return 1;
 	case sector_floorpic: { // floorpic
 		levelflat_t *levelflat;
@@ -396,26 +396,30 @@ static int sector_set(lua_State *L)
 		return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]);
 	case sector_floorheight: { // floorheight
 		boolean flag;
+		mobj_t *ptmthing = tmthing;
 		fixed_t lastpos = sector->floorheight;
-		sector->floorheight = (fixed_t)luaL_checkinteger(L, 3);
+		sector->floorheight = luaL_checkfixed(L, 3);
 		flag = P_CheckSector(sector, true);
 		if (flag && sector->numattached)
 		{
 			sector->floorheight = lastpos;
 			P_CheckSector(sector, true);
 		}
+		P_SetTarget(&tmthing, ptmthing);
 		break;
 	}
 	case sector_ceilingheight: { // ceilingheight
 		boolean flag;
+		mobj_t *ptmthing = tmthing;
 		fixed_t lastpos = sector->ceilingheight;
-		sector->ceilingheight = (fixed_t)luaL_checkinteger(L, 3);
+		sector->ceilingheight = luaL_checkfixed(L, 3);
 		flag = P_CheckSector(sector, true);
 		if (flag && sector->numattached)
 		{
 			sector->ceilingheight = lastpos;
 			P_CheckSector(sector, true);
 		}
+		P_SetTarget(&tmthing, ptmthing);
 		break;
 	}
 	case sector_floorpic:
@@ -509,10 +513,10 @@ static int line_get(lua_State *L)
 		LUA_PushUserdata(L, line->v2, META_VERTEX);
 		return 1;
 	case line_dx:
-		lua_pushinteger(L, line->dx);
+		lua_pushfixed(L, line->dx);
 		return 1;
 	case line_dy:
-		lua_pushinteger(L, line->dy);
+		lua_pushfixed(L, line->dy);
 		return 1;
 	case line_flags:
 		lua_pushinteger(L, line->flags);
@@ -628,10 +632,10 @@ static int side_get(lua_State *L)
 		lua_pushboolean(L, 1);
 		return 1;
 	case side_textureoffset:
-		lua_pushinteger(L, side->textureoffset);
+		lua_pushfixed(L, side->textureoffset);
 		return 1;
 	case side_rowoffset:
-		lua_pushinteger(L, side->rowoffset);
+		lua_pushfixed(L, side->rowoffset);
 		return 1;
 	case side_toptexture:
 		lua_pushinteger(L, side->toptexture);
@@ -658,6 +662,50 @@ static int side_get(lua_State *L)
 	return 0;
 }
 
+static int side_set(lua_State *L)
+{
+	side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
+	enum side_e field = luaL_checkoption(L, 2, side_opt[0], side_opt);
+
+	if (!side)
+	{
+		if (field == side_valid) {
+			lua_pushboolean(L, 0);
+			return 1;
+		}
+		return luaL_error(L, "accessed side_t doesn't exist anymore.");
+	}
+
+	switch(field)
+	{
+	case side_valid: // valid
+	case side_sector:
+	case side_special:
+	case side_text:
+	default:
+		return luaL_error(L, "side_t field " LUA_QS " cannot be set.", side_opt[field]);
+	case side_textureoffset:
+		side->textureoffset = luaL_checkfixed(L, 3);
+		break;
+	case side_rowoffset:
+		side->rowoffset = luaL_checkfixed(L, 3);
+		break;
+	case side_toptexture:
+        side->toptexture = luaL_checkinteger(L, 3);
+		break;
+	case side_bottomtexture:
+        side->bottomtexture = luaL_checkinteger(L, 3);
+		break;
+	case side_midtexture:
+        side->midtexture = luaL_checkinteger(L, 3);
+		break;
+	case side_repeatcnt:
+        side->repeatcnt = luaL_checkinteger(L, 3);
+		break;
+	}
+	return 0;
+}
+
 static int side_num(lua_State *L)
 {
 	side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
@@ -685,13 +733,13 @@ static int vertex_get(lua_State *L)
 		lua_pushboolean(L, 1);
 		return 1;
 	case vertex_x:
-		lua_pushinteger(L, vertex->x);
+		lua_pushfixed(L, vertex->x);
 		return 1;
 	case vertex_y:
-		lua_pushinteger(L, vertex->y);
+		lua_pushfixed(L, vertex->y);
 		return 1;
 	case vertex_z:
-		lua_pushinteger(L, vertex->z);
+		lua_pushfixed(L, vertex->z);
 		return 1;
 	}
 	return 0;
@@ -954,7 +1002,7 @@ static int ffloor_get(lua_State *L)
 		lua_pushboolean(L, 1);
 		return 1;
 	case ffloor_topheight:
-		lua_pushinteger(L, *ffloor->topheight);
+		lua_pushfixed(L, *ffloor->topheight);
 		return 1;
 	case ffloor_toppic: { // toppic
 		levelflat_t *levelflat;
@@ -968,7 +1016,7 @@ static int ffloor_get(lua_State *L)
 		lua_pushinteger(L, *ffloor->toplightlevel);
 		return 1;
 	case ffloor_bottomheight:
-		lua_pushinteger(L, *ffloor->bottomheight);
+		lua_pushfixed(L, *ffloor->bottomheight);
 		return 1;
 	case ffloor_bottompic: { // bottompic
 		levelflat_t *levelflat;
@@ -1027,14 +1075,16 @@ static int ffloor_set(lua_State *L)
 	case ffloor_topheight: { // topheight
 		boolean flag;
 		fixed_t lastpos = *ffloor->topheight;
+		mobj_t *ptmthing = tmthing;
 		sector_t *sector = &sectors[ffloor->secnum];
-		sector->ceilingheight = (fixed_t)luaL_checkinteger(L, 3);
+		sector->ceilingheight = luaL_checkfixed(L, 3);
 		flag = P_CheckSector(sector, true);
 		if (flag && sector->numattached)
 		{
 			*ffloor->topheight = lastpos;
 			P_CheckSector(sector, true);
 		}
+		P_SetTarget(&tmthing, ptmthing);
 		break;
 	}
 	case ffloor_toppic:
@@ -1046,14 +1096,16 @@ static int ffloor_set(lua_State *L)
 	case ffloor_bottomheight: { // bottomheight
 		boolean flag;
 		fixed_t lastpos = *ffloor->bottomheight;
+		mobj_t *ptmthing = tmthing;
 		sector_t *sector = &sectors[ffloor->secnum];
-		sector->floorheight = (fixed_t)luaL_checkinteger(L, 3);
+		sector->floorheight = luaL_checkfixed(L, 3);
 		flag = P_CheckSector(sector, true);
 		if (flag && sector->numattached)
 		{
 			*ffloor->bottomheight = lastpos;
 			P_CheckSector(sector, true);
 		}
+		P_SetTarget(&tmthing, ptmthing);
 		break;
 	}
 	case ffloor_bottompic:
@@ -1105,14 +1157,11 @@ static int mapheaderinfo_get(lua_State *L)
 {
 	mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER));
 	const char *field = luaL_checkstring(L, 2);
-	//INT16 i;
-	if (fastcmp(field,"lvlttl")) {
-		//for (i = 0; i < 21; i++)
-		//	if (!header->lvlttl[i])
-		//		break;
-		lua_pushlstring(L, header->lvlttl, 21);
-	} else if (fastcmp(field,"subttl"))
-		lua_pushlstring(L, header->subttl, 32);
+	INT16 i;
+	if (fastcmp(field,"lvlttl"))
+		lua_pushstring(L, header->lvlttl);
+	else if (fastcmp(field,"subttl"))
+		lua_pushstring(L, header->subttl);
 	else if (fastcmp(field,"actnum"))
 		lua_pushinteger(L, header->actnum);
 	else if (fastcmp(field,"typeoflevel"))
@@ -1124,7 +1173,7 @@ static int mapheaderinfo_get(lua_State *L)
 	else if (fastcmp(field,"musicslottrack"))
 		lua_pushinteger(L, header->musicslottrack);
 	else if (fastcmp(field,"forcecharacter"))
-		lua_pushlstring(L, header->forcecharacter, 16);
+		lua_pushstring(L, header->forcecharacter);
 	else if (fastcmp(field,"weather"))
 		lua_pushinteger(L, header->weather);
 	else if (fastcmp(field,"skynum"))
@@ -1135,12 +1184,15 @@ static int mapheaderinfo_get(lua_State *L)
 		lua_pushinteger(L, header->skybox_scaley);
 	else if (fastcmp(field,"skybox_scalez"))
 		lua_pushinteger(L, header->skybox_scalez);
-	else if (fastcmp(field,"interscreen"))
-		lua_pushlstring(L, header->interscreen, 8);
-	else if (fastcmp(field,"runsoc"))
-		lua_pushlstring(L, header->runsoc, 32);
+	else if (fastcmp(field,"interscreen")) {
+		for (i = 0; i < 8; i++)
+			if (!header->interscreen[i])
+				break;
+		lua_pushlstring(L, header->interscreen, i);
+	} else if (fastcmp(field,"runsoc"))
+		lua_pushstring(L, header->runsoc);
 	else if (fastcmp(field,"scriptname"))
-		lua_pushlstring(L, header->scriptname, 32);
+		lua_pushstring(L, header->scriptname);
 	else if (fastcmp(field,"precutscenenum"))
 		lua_pushinteger(L, header->precutscenenum);
 	else if (fastcmp(field,"cutscenenum"))
@@ -1165,11 +1217,11 @@ static int mapheaderinfo_get(lua_State *L)
 	else {
 		// Read custom vars now
 		// (note: don't include the "LUA." in your lua scripts!)
-		UINT8 i = 0;
-		for (;i < header->numCustomOptions && !fastcmp(field, header->customopts[i].option); ++i);
+		UINT8 j = 0;
+		for (;j < header->numCustomOptions && !fastcmp(field, header->customopts[j].option); ++j);
 
-		if(i < header->numCustomOptions)
-			lua_pushlstring(L, header->customopts[i].value, 255);
+		if(j < header->numCustomOptions)
+			lua_pushstring(L, header->customopts[j].value);
 		else
 			lua_pushnil(L);
 	}
@@ -1214,6 +1266,9 @@ int LUA_MapLib(lua_State *L)
 		lua_pushcfunction(L, side_get);
 		lua_setfield(L, -2, "__index");
 
+		lua_pushcfunction(L, side_set);
+		lua_setfield(L, -2, "__newindex");
+
 		lua_pushcfunction(L, side_num);
 		lua_setfield(L, -2, "__len");
 	lua_pop(L, 1);
diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c
index f8b33ffd2ad08bfc10de72dc7e2195e91a2bd9c6..fd00180d5b6bb5106de861999ae4db37ed1caf8a 100644
--- a/src/lua_mathlib.c
+++ b/src/lua_mathlib.c
@@ -47,37 +47,39 @@ static int lib_max(lua_State *L)
 
 static int lib_fixedangle(lua_State *L)
 {
-	lua_pushinteger(L, FixedAngle((fixed_t)luaL_checkinteger(L, 1)));
+	lua_pushangle(L, FixedAngle(luaL_checkfixed(L, 1)));
 	return 1;
 }
 
 static int lib_anglefixed(lua_State *L)
 {
-	lua_pushinteger(L, AngleFixed((angle_t)luaL_checkinteger(L, 1)));
+	lua_pushfixed(L, AngleFixed(luaL_checkangle(L, 1)));
 	return 1;
 }
 
 static int lib_invangle(lua_State *L)
 {
-	lua_pushinteger(L, InvAngle((angle_t)luaL_checkinteger(L, 1)));
+	lua_pushangle(L, InvAngle(luaL_checkangle(L, 1)));
 	return 1;
 }
 
 static int lib_finesine(lua_State *L)
 {
-	lua_pushinteger(L, FINESINE((luaL_checkinteger(L, 1)>>ANGLETOFINESHIFT) & FINEMASK));
+	lua_pushfixed(L, FINESINE((luaL_checkangle(L, 1)>>ANGLETOFINESHIFT) & FINEMASK));
 	return 1;
 }
 
 static int lib_finecosine(lua_State *L)
 {
-	lua_pushinteger(L, FINECOSINE((luaL_checkinteger(L, 1)>>ANGLETOFINESHIFT) & FINEMASK));
+	lua_pushfixed(L, FINECOSINE((luaL_checkangle(L, 1)>>ANGLETOFINESHIFT) & FINEMASK));
 	return 1;
 }
 
 static int lib_finetangent(lua_State *L)
 {
-	lua_pushinteger(L, FINETANGENT((luaL_checkinteger(L, 1)>>ANGLETOFINESHIFT) & FINEMASK));
+	// HACK: add ANGLE_90 to make tan() in Lua start at 0 like it should
+	// use & 4095 instead of & FINEMASK (8191), so it doesn't go out of the array's bounds
+	lua_pushfixed(L, FINETANGENT(((luaL_checkangle(L, 1)+ANGLE_90)>>ANGLETOFINESHIFT) & 4095));
 	return 1;
 }
 
@@ -86,61 +88,61 @@ static int lib_finetangent(lua_State *L)
 
 static int lib_fixedmul(lua_State *L)
 {
-	lua_pushinteger(L, FixedMul((fixed_t)luaL_checkinteger(L, 1), (fixed_t)luaL_checkinteger(L, 2)));
+	lua_pushfixed(L, FixedMul(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
 	return 1;
 }
 
 static int lib_fixedint(lua_State *L)
 {
-	lua_pushinteger(L, FixedInt((fixed_t)luaL_checkinteger(L, 1)));
+	lua_pushinteger(L, FixedInt(luaL_checkfixed(L, 1)));
 	return 1;
 }
 
 static int lib_fixeddiv(lua_State *L)
 {
-	lua_pushinteger(L, FixedDiv((fixed_t)luaL_checkinteger(L, 1), (fixed_t)luaL_checkinteger(L, 2)));
+	lua_pushfixed(L, FixedDiv(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
 	return 1;
 }
 
 static int lib_fixedrem(lua_State *L)
 {
-	lua_pushinteger(L, FixedRem((fixed_t)luaL_checkinteger(L, 1), (fixed_t)luaL_checkinteger(L, 2)));
+	lua_pushfixed(L, FixedRem(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
 	return 1;
 }
 
 static int lib_fixedsqrt(lua_State *L)
 {
-	lua_pushinteger(L, FixedSqrt((fixed_t)luaL_checkinteger(L, 1)));
+	lua_pushfixed(L, FixedSqrt(luaL_checkfixed(L, 1)));
 	return 1;
 }
 
 static int lib_fixedhypot(lua_State *L)
 {
-	lua_pushinteger(L, FixedHypot((fixed_t)luaL_checkinteger(L, 1), (fixed_t)luaL_checkinteger(L, 2)));
+	lua_pushfixed(L, FixedHypot(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2)));
 	return 1;
 }
 
 static int lib_fixedfloor(lua_State *L)
 {
-	lua_pushinteger(L, FixedFloor((fixed_t)luaL_checkinteger(L, 1)));
+	lua_pushfixed(L, FixedFloor(luaL_checkfixed(L, 1)));
 	return 1;
 }
 
 static int lib_fixedtrunc(lua_State *L)
 {
-	lua_pushinteger(L, FixedTrunc((fixed_t)luaL_checkinteger(L, 1)));
+	lua_pushfixed(L, FixedTrunc(luaL_checkfixed(L, 1)));
 	return 1;
 }
 
 static int lib_fixedceil(lua_State *L)
 {
-	lua_pushinteger(L, FixedCeil((fixed_t)luaL_checkinteger(L, 1)));
+	lua_pushfixed(L, FixedCeil(luaL_checkfixed(L, 1)));
 	return 1;
 }
 
 static int lib_fixedround(lua_State *L)
 {
-	lua_pushinteger(L, FixedRound((fixed_t)luaL_checkinteger(L, 1)));
+	lua_pushfixed(L, FixedRound(luaL_checkfixed(L, 1)));
 	return 1;
 }
 
@@ -156,7 +158,7 @@ static int lib_getsecspecial(lua_State *L)
 
 static int lib_all7emeralds(lua_State *L)
 {
-	lua_pushinteger(L, ALL7EMERALDS(luaL_checkinteger(L, 1)));
+	lua_pushboolean(L, ALL7EMERALDS(luaL_checkinteger(L, 1)));
 	return 1;
 }
 
@@ -164,7 +166,7 @@ static int lib_all7emeralds(lua_State *L)
 // Returns both color and frame numbers!
 static int lib_coloropposite(lua_State *L)
 {
-	int colornum = ((int)luaL_checkinteger(L, 1)) & MAXSKINCOLORS;
+	int colornum = ((int)luaL_checkinteger(L, 1)) % MAXSKINCOLORS;
 	lua_pushinteger(L, Color_Opposite[colornum*2]); // push color
 	lua_pushinteger(L, Color_Opposite[colornum*2+1]); // push frame
 	return 2;
diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c
index cf4db8f398aee2e765f51560a47001eabcd31202..83e7039e4bbacb68079f78d62020bdb388a1f3ac 100644
--- a/src/lua_mobjlib.c
+++ b/src/lua_mobjlib.c
@@ -162,13 +162,13 @@ static int mobj_get(lua_State *L)
 		lua_pushboolean(L, 1);
 		break;
 	case mobj_x:
-		lua_pushinteger(L, mo->x);
+		lua_pushfixed(L, mo->x);
 		break;
 	case mobj_y:
-		lua_pushinteger(L, mo->y);
+		lua_pushfixed(L, mo->y);
 		break;
 	case mobj_z:
-		lua_pushinteger(L, mo->z);
+		lua_pushfixed(L, mo->z);
 		break;
 	case mobj_snext:
 		LUA_PushUserdata(L, mo->snext, META_MOBJ);
@@ -179,7 +179,7 @@ static int mobj_get(lua_State *L)
 		// i.e. it will always ultimately point to THIS mobj -- so that's actually not useful to Lua and won't be included.
 		return UNIMPLEMENTED;
 	case mobj_angle:
-		lua_pushinteger(L, mo->angle);
+		lua_pushangle(L, mo->angle);
 		break;
 	case mobj_sprite:
 		lua_pushinteger(L, mo->sprite);
@@ -193,28 +193,28 @@ static int mobj_get(lua_State *L)
 		LUA_PushUserdata(L, mo->subsector, META_SUBSECTOR);
 		break;
 	case mobj_floorz:
-		lua_pushinteger(L, mo->floorz);
+		lua_pushfixed(L, mo->floorz);
 		break;
 	case mobj_ceilingz:
-		lua_pushinteger(L, mo->ceilingz);
+		lua_pushfixed(L, mo->ceilingz);
 		break;
 	case mobj_radius:
-		lua_pushinteger(L, mo->radius);
+		lua_pushfixed(L, mo->radius);
 		break;
 	case mobj_height:
-		lua_pushinteger(L, mo->height);
+		lua_pushfixed(L, mo->height);
 		break;
 	case mobj_momx:
-		lua_pushinteger(L, mo->momx);
+		lua_pushfixed(L, mo->momx);
 		break;
 	case mobj_momy:
-		lua_pushinteger(L, mo->momy);
+		lua_pushfixed(L, mo->momy);
 		break;
 	case mobj_momz:
-		lua_pushinteger(L, mo->momz);
+		lua_pushfixed(L, mo->momz);
 		break;
 	case mobj_pmomz:
-		lua_pushinteger(L, mo->pmomz);
+		lua_pushfixed(L, mo->pmomz);
 		break;
 	case mobj_tics:
 		lua_pushinteger(L, mo->tics);
@@ -299,32 +299,32 @@ static int mobj_get(lua_State *L)
 		LUA_PushUserdata(L, mo->tracer, META_MOBJ);
 		break;
 	case mobj_friction:
-		lua_pushinteger(L, mo->friction);
+		lua_pushfixed(L, mo->friction);
 		break;
 	case mobj_movefactor:
-		lua_pushinteger(L, mo->movefactor);
+		lua_pushfixed(L, mo->movefactor);
 		break;
 	case mobj_fuse:
 		lua_pushinteger(L, mo->fuse);
 		break;
 	case mobj_watertop:
-		lua_pushinteger(L, mo->watertop);
+		lua_pushfixed(L, mo->watertop);
 		break;
 	case mobj_waterbottom:
-		lua_pushinteger(L, mo->waterbottom);
+		lua_pushfixed(L, mo->waterbottom);
 		break;
 	case mobj_mobjnum:
 		// mobjnum is a networking thing generated for $$$.sav
 		// and therefore shouldn't be used by Lua.
 		return UNIMPLEMENTED;
 	case mobj_scale:
-		lua_pushinteger(L, mo->scale);
+		lua_pushfixed(L, mo->scale);
 		break;
 	case mobj_destscale:
-		lua_pushinteger(L, mo->destscale);
+		lua_pushfixed(L, mo->destscale);
 		break;
 	case mobj_scalespeed:
-		lua_pushinteger(L, mo->scalespeed);
+		lua_pushfixed(L, mo->scalespeed);
 		break;
 	case mobj_extravalue1:
 		lua_pushinteger(L, mo->extravalue1);
@@ -382,7 +382,7 @@ static int mobj_set(lua_State *L)
 	{
 		// z doesn't cross sector bounds so it's okay.
 		mobj_t *ptmthing = tmthing;
-		mo->z = (fixed_t)luaL_checkinteger(L, 3);
+		mo->z = luaL_checkfixed(L, 3);
 		P_CheckPosition(mo, mo->x, mo->y);
 		mo->floorz = tmfloorz;
 		mo->ceilingz = tmceilingz;
@@ -394,7 +394,7 @@ static int mobj_set(lua_State *L)
 	case mobj_sprev:
 		return UNIMPLEMENTED;
 	case mobj_angle:
-		mo->angle = (angle_t)luaL_checkinteger(L, 3);
+		mo->angle = luaL_checkangle(L, 3);
 		if (mo->player == &players[consoleplayer])
 			localangle = mo->angle;
 		else if (mo->player == &players[secondarydisplayplayer])
@@ -417,7 +417,7 @@ static int mobj_set(lua_State *L)
 	case mobj_radius:
 	{
 		mobj_t *ptmthing = tmthing;
-		mo->radius = (fixed_t)luaL_checkinteger(L, 3);
+		mo->radius = luaL_checkfixed(L, 3);
 		if (mo->radius < 0)
 			mo->radius = 0;
 		P_CheckPosition(mo, mo->x, mo->y);
@@ -429,7 +429,7 @@ static int mobj_set(lua_State *L)
 	case mobj_height:
 	{
 		mobj_t *ptmthing = tmthing;
-		mo->height = (fixed_t)luaL_checkinteger(L, 3);
+		mo->height = luaL_checkfixed(L, 3);
 		if (mo->height < 0)
 			mo->height = 0;
 		P_CheckPosition(mo, mo->x, mo->y);
@@ -439,16 +439,17 @@ static int mobj_set(lua_State *L)
 		break;
 	}
 	case mobj_momx:
-		mo->momx = (fixed_t)luaL_checkinteger(L, 3);
+		mo->momx = luaL_checkfixed(L, 3);
 		break;
 	case mobj_momy:
-		mo->momy = (fixed_t)luaL_checkinteger(L, 3);
+		mo->momy = luaL_checkfixed(L, 3);
 		break;
 	case mobj_momz:
-		mo->momz = (fixed_t)luaL_checkinteger(L, 3);
+		mo->momz = luaL_checkfixed(L, 3);
 		break;
 	case mobj_pmomz:
-		mo->pmomz = (fixed_t)luaL_checkinteger(L, 3);
+		mo->pmomz = luaL_checkfixed(L, 3);
+		mo->eflags |= MFE_APPLYPMOMZ;
 		break;
 	case mobj_tics:
 		mo->tics = luaL_checkinteger(L, 3);
@@ -572,25 +573,25 @@ static int mobj_set(lua_State *L)
 		}
 		break;
 	case mobj_friction:
-		mo->friction = (fixed_t)luaL_checkinteger(L, 3);
+		mo->friction = luaL_checkfixed(L, 3);
 		break;
 	case mobj_movefactor:
-		mo->movefactor = (fixed_t)luaL_checkinteger(L, 3);
+		mo->movefactor = luaL_checkfixed(L, 3);
 		break;
 	case mobj_fuse:
 		mo->fuse = luaL_checkinteger(L, 3);
 		break;
 	case mobj_watertop:
-		mo->watertop = (fixed_t)luaL_checkinteger(L, 3);
+		mo->watertop = luaL_checkfixed(L, 3);
 		break;
 	case mobj_waterbottom:
-		mo->waterbottom = (fixed_t)luaL_checkinteger(L, 3);
+		mo->waterbottom = luaL_checkfixed(L, 3);
 		break;
 	case mobj_mobjnum:
 		return UNIMPLEMENTED;
 	case mobj_scale:
 	{
-		fixed_t scale = (fixed_t)luaL_checkinteger(L, 3);
+		fixed_t scale = luaL_checkfixed(L, 3);
 		if (scale < FRACUNIT/100)
 			scale = FRACUNIT/100;
 		mo->destscale = scale;
@@ -599,14 +600,14 @@ static int mobj_set(lua_State *L)
 	}
 	case mobj_destscale:
 	{
-		fixed_t scale = (fixed_t)luaL_checkinteger(L, 3);
+		fixed_t scale = luaL_checkfixed(L, 3);
 		if (scale < FRACUNIT/100)
 			scale = FRACUNIT/100;
 		mo->destscale = scale;
 		break;
 	}
 	case mobj_scalespeed:
-		mo->scalespeed = (fixed_t)luaL_checkinteger(L, 3);
+		mo->scalespeed = luaL_checkfixed(L, 3);
 		break;
 	case mobj_extravalue1:
 		mo->extravalue1 = luaL_checkinteger(L, 3);
diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index 7f64fff626e1fcec551daee0a20ded1b5c220917..64513ab9728e6a2e4c7723e3a80ef36ceb9bee59 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -109,15 +109,15 @@ static int player_get(lua_State *L)
 	else if (fastcmp(field,"playerstate"))
 		lua_pushinteger(L, plr->playerstate);
 	else if (fastcmp(field,"viewz"))
-		lua_pushinteger(L, plr->viewz);
+		lua_pushfixed(L, plr->viewz);
 	else if (fastcmp(field,"viewheight"))
-		lua_pushinteger(L, plr->viewheight);
+		lua_pushfixed(L, plr->viewheight);
 	else if (fastcmp(field,"deltaviewheight"))
-		lua_pushinteger(L, plr->deltaviewheight);
+		lua_pushfixed(L, plr->deltaviewheight);
 	else if (fastcmp(field,"bob"))
-		lua_pushinteger(L, plr->bob);
+		lua_pushfixed(L, plr->bob);
 	else if (fastcmp(field,"aiming"))
-		lua_pushinteger(L, plr->aiming);
+		lua_pushangle(L, plr->aiming);
 	else if (fastcmp(field,"health"))
 		lua_pushinteger(L, plr->health);
 	else if (fastcmp(field,"pity"))
@@ -141,13 +141,13 @@ static int player_get(lua_State *L)
 	else if (fastcmp(field,"score"))
 		lua_pushinteger(L, plr->score);
 	else if (fastcmp(field,"dashspeed"))
-		lua_pushinteger(L, plr->dashspeed);
+		lua_pushfixed(L, plr->dashspeed);
 	else if (fastcmp(field,"dashtime"))
 		lua_pushinteger(L, plr->dashtime);
 	else if (fastcmp(field,"normalspeed"))
-		lua_pushinteger(L, plr->normalspeed);
+		lua_pushfixed(L, plr->normalspeed);
 	else if (fastcmp(field,"runspeed"))
-		lua_pushinteger(L, plr->runspeed);
+		lua_pushfixed(L, plr->runspeed);
 	else if (fastcmp(field,"thrustfactor"))
 		lua_pushinteger(L, plr->thrustfactor);
 	else if (fastcmp(field,"accelstart"))
@@ -167,13 +167,13 @@ static int player_get(lua_State *L)
 	else if (fastcmp(field,"revitem"))
 		lua_pushinteger(L, plr->revitem);
 	else if (fastcmp(field,"actionspd"))
-		lua_pushinteger(L, plr->actionspd);
+		lua_pushfixed(L, plr->actionspd);
 	else if (fastcmp(field,"mindash"))
-		lua_pushinteger(L, plr->mindash);
+		lua_pushfixed(L, plr->mindash);
 	else if (fastcmp(field,"maxdash"))
-		lua_pushinteger(L, plr->maxdash);
+		lua_pushfixed(L, plr->maxdash);
 	else if (fastcmp(field,"jumpfactor"))
-		lua_pushinteger(L, plr->jumpfactor);
+		lua_pushfixed(L, plr->jumpfactor);
 	else if (fastcmp(field,"lives"))
 		lua_pushinteger(L, plr->lives);
 	else if (fastcmp(field,"continues"))
@@ -183,7 +183,7 @@ static int player_get(lua_State *L)
 	else if (fastcmp(field,"gotcontinue"))
 		lua_pushinteger(L, plr->gotcontinue);
 	else if (fastcmp(field,"speed"))
-		lua_pushinteger(L, plr->speed);
+		lua_pushfixed(L, plr->speed);
 	else if (fastcmp(field,"jumping"))
 		lua_pushboolean(L, plr->jumping);
 	else if (fastcmp(field,"secondjump"))
@@ -205,13 +205,13 @@ static int player_get(lua_State *L)
 	else if (fastcmp(field,"skidtime"))
 		lua_pushinteger(L, plr->skidtime);
 	else if (fastcmp(field,"cmomx"))
-		lua_pushinteger(L, plr->cmomx);
+		lua_pushfixed(L, plr->cmomx);
 	else if (fastcmp(field,"cmomy"))
-		lua_pushinteger(L, plr->cmomy);
+		lua_pushfixed(L, plr->cmomy);
 	else if (fastcmp(field,"rmomx"))
-		lua_pushinteger(L, plr->rmomx);
+		lua_pushfixed(L, plr->rmomx);
 	else if (fastcmp(field,"rmomy"))
-		lua_pushinteger(L, plr->rmomy);
+		lua_pushfixed(L, plr->rmomy);
 	else if (fastcmp(field,"numboxes"))
 		lua_pushinteger(L, plr->numboxes);
 	else if (fastcmp(field,"totalring"))
@@ -239,11 +239,11 @@ static int player_get(lua_State *L)
 	else if (fastcmp(field,"starposttime"))
 		lua_pushinteger(L, plr->starposttime);
 	else if (fastcmp(field,"starpostangle"))
-		lua_pushinteger(L, plr->starpostangle);
+		lua_pushangle(L, plr->starpostangle);
 	else if (fastcmp(field,"angle_pos"))
-		lua_pushinteger(L, plr->angle_pos);
+		lua_pushangle(L, plr->angle_pos);
 	else if (fastcmp(field,"old_angle_pos"))
-		lua_pushinteger(L, plr->old_angle_pos);
+		lua_pushangle(L, plr->old_angle_pos);
 	else if (fastcmp(field,"axis1"))
 		LUA_PushUserdata(L, plr->axis1, META_MOBJ);
 	else if (fastcmp(field,"axis2"))
@@ -305,16 +305,16 @@ static int player_get(lua_State *L)
 	else if (fastcmp(field,"awayviewtics"))
 		lua_pushinteger(L, plr->awayviewtics);
 	else if (fastcmp(field,"awayviewaiming"))
-		lua_pushinteger(L, plr->awayviewaiming);
+		lua_pushangle(L, plr->awayviewaiming);
 	else if (fastcmp(field,"spectator"))
-		lua_pushinteger(L, plr->spectator);
+		lua_pushboolean(L, plr->spectator);
 	else if (fastcmp(field,"bot"))
 		lua_pushinteger(L, plr->bot);
 	else if (fastcmp(field,"jointime"))
 		lua_pushinteger(L, plr->jointime);
 #ifdef HWRENDER
 	else if (fastcmp(field,"fovadd"))
-		lua_pushinteger(L, plr->fovadd);
+		lua_pushfixed(L, plr->fovadd);
 #endif
 	else {
 		lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
@@ -354,15 +354,15 @@ static int player_set(lua_State *L)
 	else if (fastcmp(field,"playerstate"))
 		plr->playerstate = luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"viewz"))
-		plr->viewz = (fixed_t)luaL_checkinteger(L, 3);
+		plr->viewz = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"viewheight"))
-		plr->viewheight = (fixed_t)luaL_checkinteger(L, 3);
+		plr->viewheight = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"deltaviewheight"))
-		plr->deltaviewheight = (fixed_t)luaL_checkinteger(L, 3);
+		plr->deltaviewheight = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"bob"))
-		plr->bob = (fixed_t)luaL_checkinteger(L, 3);
+		plr->bob = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"aiming")) {
-		plr->aiming = (angle_t)luaL_checkinteger(L, 3);
+		plr->aiming = luaL_checkangle(L, 3);
 		if (plr == &players[consoleplayer])
 			localaiming = plr->aiming;
 		else if (plr == &players[secondarydisplayplayer])
@@ -391,13 +391,13 @@ static int player_set(lua_State *L)
 	else if (fastcmp(field,"score"))
 		plr->score = (UINT32)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"dashspeed"))
-		plr->dashspeed = (fixed_t)luaL_checkinteger(L, 3);
+		plr->dashspeed = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"dashtime"))
 		plr->dashtime = (INT32)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"normalspeed"))
-		plr->normalspeed = (fixed_t)luaL_checkinteger(L, 3);
+		plr->normalspeed = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"runspeed"))
-		plr->runspeed = (fixed_t)luaL_checkinteger(L, 3);
+		plr->runspeed = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"thrustfactor"))
 		plr->thrustfactor = (UINT8)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"accelstart"))
@@ -433,7 +433,7 @@ static int player_set(lua_State *L)
 	else if (fastcmp(field,"gotcontinue"))
 		plr->gotcontinue = (UINT8)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"speed"))
-		plr->speed = (fixed_t)luaL_checkinteger(L, 3);
+		plr->speed = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"jumping"))
 		plr->jumping = luaL_checkboolean(L, 3);
 	else if (fastcmp(field,"secondjump"))
@@ -455,13 +455,13 @@ static int player_set(lua_State *L)
 	else if (fastcmp(field,"skidtime"))
 		plr->skidtime = (tic_t)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"cmomx"))
-		plr->cmomx = (fixed_t)luaL_checkinteger(L, 3);
+		plr->cmomx = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"cmomy"))
-		plr->cmomy = (fixed_t)luaL_checkinteger(L, 3);
+		plr->cmomy = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"rmomx"))
-		plr->rmomx = (fixed_t)luaL_checkinteger(L, 3);
+		plr->rmomx = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"rmomy"))
-		plr->rmomy = (fixed_t)luaL_checkinteger(L, 3);
+		plr->rmomy = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"numboxes"))
 		plr->numboxes = (INT16)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"totalring"))
@@ -489,11 +489,11 @@ static int player_set(lua_State *L)
 	else if (fastcmp(field,"starposttime"))
 		plr->starposttime = (tic_t)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"starpostangle"))
-		plr->starpostangle = (angle_t)luaL_checkinteger(L, 3);
+		plr->starpostangle = luaL_checkangle(L, 3);
 	else if (fastcmp(field,"angle_pos"))
-		plr->angle_pos = (angle_t)luaL_checkinteger(L, 3);
+		plr->angle_pos = luaL_checkangle(L, 3);
 	else if (fastcmp(field,"old_angle_pos"))
-		plr->old_angle_pos = (angle_t)luaL_checkinteger(L, 3);
+		plr->old_angle_pos = luaL_checkangle(L, 3);
 	else if (fastcmp(field,"axis1"))
 		P_SetTarget(&plr->axis1, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)));
 	else if (fastcmp(field,"axis2"))
@@ -569,7 +569,7 @@ static int player_set(lua_State *L)
 			P_SetTarget(&plr->awayviewmobj, plr->mo); // but since the script might set awayviewmobj immediately AFTER setting awayviewtics, use player mobj as filler for now.
 	}
 	else if (fastcmp(field,"awayviewaiming"))
-		plr->awayviewaiming = (angle_t)luaL_checkinteger(L, 3);
+		plr->awayviewaiming = luaL_checkangle(L, 3);
 	else if (fastcmp(field,"spectator"))
 		plr->spectator = lua_toboolean(L, 3);
 	else if (fastcmp(field,"bot"))
@@ -578,7 +578,7 @@ static int player_set(lua_State *L)
 		plr->jointime = (tic_t)luaL_checkinteger(L, 3);
 #ifdef HWRENDER
 	else if (fastcmp(field,"fovadd"))
-		plr->fovadd = (fixed_t)luaL_checkinteger(L, 3);
+		plr->fovadd = luaL_checkfixed(L, 3);
 #endif
 	else {
 		lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
diff --git a/src/lua_script.c b/src/lua_script.c
index 8b40d9f00b5ab9aed332ec84ae67fd1c4fa4dbe1..a7315ad622438608ad207d805ea455aec3570a3a 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -442,7 +442,6 @@ enum
 	ARCH_NULL=0,
 	ARCH_BOOLEAN,
 	ARCH_SIGNED,
-	ARCH_UNSIGNED,
 	ARCH_STRING,
 	ARCH_TABLE,
 
@@ -522,13 +521,8 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex)
 	case LUA_TNUMBER:
 	{
 		lua_Integer number = lua_tointeger(gL, myindex);
-		if (number < 0) {
-			WRITEUINT8(save_p, ARCH_SIGNED);
-			WRITEFIXED(save_p, number);
-		} else {
-			WRITEUINT8(save_p, ARCH_UNSIGNED);
-			WRITEANGLE(save_p, number);
-		}
+        WRITEUINT8(save_p, ARCH_SIGNED);
+        WRITEFIXED(save_p, number);
 		break;
 	}
 	case LUA_TSTRING:
@@ -743,7 +737,7 @@ static int NetArchive(lua_State *L)
 {
 	int TABLESINDEX = lua_upvalueindex(1);
 	int i, n = lua_gettop(L);
-	for (i = 0; i < n; i++)
+	for (i = 1; i <= n; i++)
 		ArchiveValue(TABLESINDEX, i);
 	return n;
 }
@@ -797,9 +791,6 @@ static UINT8 UnArchiveValue(int TABLESINDEX)
 	case ARCH_SIGNED:
 		lua_pushinteger(gL, READFIXED(save_p));
 		break;
-	case ARCH_UNSIGNED:
-		lua_pushinteger(gL, READANGLE(save_p));
-		break;
 	case ARCH_STRING:
 	{
 		char value[1024];
@@ -893,7 +884,7 @@ static int NetUnArchive(lua_State *L)
 {
 	int TABLESINDEX = lua_upvalueindex(1);
 	int i, n = lua_gettop(L);
-	for (i = 0; i < n; i++)
+	for (i = 1; i <= n; i++)
 		UnArchiveValue(TABLESINDEX);
 	return n;
 }
@@ -948,6 +939,14 @@ static void NetArchiveHook(lua_CFunction archFunc)
 	lua_pop(gL, 2);
 }
 
+void LUA_Step(void)
+{
+	if (!gL)
+		return;
+	lua_settop(gL, 0);
+	lua_gc(gL, LUA_GCSTEP, 1);
+}
+
 void LUA_Archive(void)
 {
 	INT32 i;
diff --git a/src/lua_script.h b/src/lua_script.h
index eaef13d1e635fce209fb1e4bc2f694dfb24b3ea8..292160a0b5356e2494d6557207dfe20c2167d993 100644
--- a/src/lua_script.h
+++ b/src/lua_script.h
@@ -19,9 +19,21 @@
 #include "blua/lua.h"
 #include "blua/lualib.h"
 #include "blua/lauxlib.h"
+
 #define lua_optboolean(L, i) (!lua_isnoneornil(L, i) && lua_toboolean(L, i))
 #define lua_opttrueboolean(L, i) (lua_isnoneornil(L, i) || lua_toboolean(L, i))
 
+// fixed_t casting
+// TODO add some distinction between fixed numbers and integer numbers
+// for at least the purpose of printing and maybe math.
+#define luaL_checkfixed(L, i) luaL_checkinteger(L, i)
+#define lua_pushfixed(L, f) lua_pushinteger(L, f)
+
+// angle_t casting
+// we reduce the angle to a fixed point between 0.0 and 1.0
+#define luaL_checkangle(L, i) (((angle_t)(luaL_checkfixed(L, i)&0xFFFF))<<16)
+#define lua_pushangle(L, a) lua_pushfixed(L, a>>16)
+
 #ifdef _DEBUG
 void LUA_ClearExtVars(void);
 #endif
@@ -36,6 +48,7 @@ void LUA_InvalidateUserdata(void *data);
 void LUA_InvalidateLevel(void);
 void LUA_InvalidateMapthings(void);
 void LUA_InvalidatePlayer(player_t *player);
+void LUA_Step(void);
 void LUA_Archive(void);
 void LUA_UnArchive(void);
 void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c
diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c
index f797f30d6cc05a353921d6378692ff4a9fd87868..f07b4564c15d553c9b5640d03d6151fd0e69d87b 100644
--- a/src/lua_skinlib.c
+++ b/src/lua_skinlib.c
@@ -147,19 +147,19 @@ static int skin_get(lua_State *L)
 		lua_pushinteger(L, skin->revitem);
 		break;
 	case skin_actionspd:
-		lua_pushinteger(L, skin->actionspd);
+		lua_pushfixed(L, skin->actionspd);
 		break;
 	case skin_mindash:
-		lua_pushinteger(L, skin->mindash);
+		lua_pushfixed(L, skin->mindash);
 		break;
 	case skin_maxdash:
-		lua_pushinteger(L, skin->maxdash);
+		lua_pushfixed(L, skin->maxdash);
 		break;
 	case skin_normalspeed:
-		lua_pushinteger(L, skin->normalspeed);
+		lua_pushfixed(L, skin->normalspeed);
 		break;
 	case skin_runspeed:
-		lua_pushinteger(L, skin->runspeed);
+		lua_pushfixed(L, skin->runspeed);
 		break;
 	case skin_thrustfactor:
 		lua_pushinteger(L, skin->thrustfactor);
@@ -171,7 +171,7 @@ static int skin_get(lua_State *L)
 		lua_pushinteger(L, skin->acceleration);
 		break;
 	case skin_jumpfactor:
-		lua_pushinteger(L, skin->jumpfactor);
+		lua_pushfixed(L, skin->jumpfactor);
 		break;
 	case skin_starttranscolor:
 		lua_pushinteger(L, skin->starttranscolor);
diff --git a/src/m_cheat.c b/src/m_cheat.c
index 4da9b3ba7bd67af58593debd5de7dfffddacad1c..6eaf31c4affdacf633834ee2a4979da02875e30a 100644
--- a/src/m_cheat.c
+++ b/src/m_cheat.c
@@ -880,12 +880,33 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling)
 
 static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean ceiling)
 {
-	mapthing_t *mt;
+	mapthing_t *mt = mapthings;
+
 #ifdef HAVE_BLUA
 	LUA_InvalidateMapthings();
 #endif
 
 	mapthings = Z_Realloc(mapthings, ++nummapthings * sizeof (*mapthings), PU_LEVEL, NULL);
+
+	// as Z_Realloc can relocate mapthings, quickly go through thinker list and correct
+	// the spawnpoints of any objects that have them to the new location
+	if (mt != mapthings)
+	{
+		thinker_t *th;
+		mobj_t *mo;
+
+		for (th = thinkercap.next; th != &thinkercap; th = th->next)
+		{
+			if (th->function.acp1 != (actionf_p1)P_MobjThinker)
+				continue;
+
+			mo = (mobj_t *)th;
+			// get offset from mt, which points to old mapthings, then add new location
+			if (mo->spawnpoint)
+				mo->spawnpoint = (mo->spawnpoint - mt) + mapthings;
+		}
+	}
+
 	mt = (mapthings+nummapthings-1);
 
 	mt->type = type;
diff --git a/src/m_cond.c b/src/m_cond.c
index 17f7551209b1dcaa4d58bc6e4e27e357c8087e2a..7ef192f7b8774cca8c22c1cf40261fcda72de1ab 100644
--- a/src/m_cond.c
+++ b/src/m_cond.c
@@ -49,7 +49,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"Streams come to an end\n"
 		"where they can no longer fall.\n"
 		"But if you went up...", 0},
-	{0,  -336,  2064,   195, 1, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0,  -336,  2064,   195, 1, 'E', SKINCOLOR_EMERALD, 0,
 		"This one's in plain sight.\n"
 		"Why haven't you claimed it?\n"
 		"Surely you saw it.", 0},
@@ -77,7 +77,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"Near the level's end,\n"
 		"another bridge spans a lake.\n"
 		"What could be under...?", 0},
-	{0,  -170,   491,  3821, 2, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0,  -170,   491,  3821, 2, 'E', SKINCOLOR_EMERALD, 0,
 		"An ivied tunnel\n"
 		"has a corner that's sunlit.\n"
 		"Go reach for the sky!", 0},
@@ -110,7 +110,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"Spinning through small gaps\n"
 		"can slip you into a cave.\n"
 		"In that cave's first stretch...", 0},
-	{0,  2848, -9088,   488, 4, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0,  2848, -9088,   488, 4, 'E', SKINCOLOR_EMERALD, 0,
 		"The slime lake is deep,\n"
 		"but reaching the floor takes height.\n"
 		"Scream \"Geronimo!\"...", 0},
@@ -138,7 +138,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"There is a hallway\n"
 		"that a button floods with slime.\n"
 		"Go through it again!", 0},
-	{0, -2468,-12128,  1312, 5, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0, -2468,-12128,  1312, 5, 'E', SKINCOLOR_EMERALD, 0,
 		"Jumping on turtles\n"
 		"will send you springing skyward.\n"
 		"Now, do that six times...", 0},
@@ -171,7 +171,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"A caved-in hallway?\n"
 		"The floor falls; the path goes down.\n"
 		"But those rocks looked weak...", 0},
-	{0, 12576, 16096,  -992, 7, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0, 12576, 16096,  -992, 7, 'E', SKINCOLOR_EMERALD, 0,
 		"The end is quite dry.\n"
 		"Some rocks dam the water in.\n"
 		"Knuckles can fix that...", 0},
@@ -199,7 +199,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"In the current maze\n"
 		"hides a dark room of columns.\n"
 		"Find it, then look up.", 0},
-	{0,  3104, 16192,  2408, 8, 'E', SKINCOLOR_NEONGREEN,  0,
+	{0,  3104, 16192,  2408, 8, 'E', SKINCOLOR_EMERALD,  0,
 		"That same dragon's eye\n"
 		"hides another secret room.\n"
 		"There, solve its riddle.", 0},
@@ -232,7 +232,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"The final approach!\n"
 		"A tower holds the emblem\n"
 		"near a ring arrow.", 0},
-	{0,  9472, -5890,   710, 10, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0,  9472, -5890,   710, 10, 'E', SKINCOLOR_EMERALD, 0,
 		"The right starting path\n"
 		"hides this near a canopy,\n"
 		"high, where two trees meet.", 0},
@@ -260,7 +260,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"Some of these bookshelves\n"
 		"are not flush against the walls.\n"
 		"Wonder why that is?", 0},
-	{0, 12708,-13536,  4768, 11, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0, 12708,-13536,  4768, 11, 'E', SKINCOLOR_EMERALD, 0,
 		"The ending's towers\n"
 		"are hiding a small alcove.\n"
 		"Check around outside.", 0},
@@ -293,7 +293,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"Not far from the start,\n"
 		"if you climb toward the sky,\n"
 		"the cliffs hide something.", 0},
-	{0, 12504,  6848,  3424, 13, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0, 12504,  6848,  3424, 13, 'E', SKINCOLOR_EMERALD, 0,
 		"Right by the exit,\n"
 		"an emblem lies on a cliff.\n"
 		"Ride ropes to reach it.", 0},
@@ -321,7 +321,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"Where once a bridge stood,\n"
 		"now magma falls from above.\n"
 		"The bridge dropped something...", 0},
-	{0,  8287,-11043,  1328, 16, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0,  8287,-11043,  1328, 16, 'E', SKINCOLOR_EMERALD, 0,
 		"A lake of magma\n"
 		"ebbs and flows unendingly.\n"
 		"Wait for its nadir.", 0},
@@ -349,7 +349,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"Don't jump too high here!\n"
 		"No conveyor will catch you;\n"
 		"you'd fall to your death.", 0},
-	{0, -6432, -6192,   584, 22, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0, -6432, -6192,   584, 22, 'E', SKINCOLOR_EMERALD, 0,
 		"Conveyors! Magma!\n"
 		"What an intense room this is!\n"
 		"But, what brought you here?", 0},
@@ -377,7 +377,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"Gears with missing teeth\n"
 		"can hide a clever secret!\n"
 		"Think Green Hill Zone boss.", 0},
-	{0,  1920, 20608,  1064, 23, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0,  1920, 20608,  1064, 23, 'E', SKINCOLOR_EMERALD, 0,
 		"Just before you reach\n"
 		"the defective cargo bay,\n"
 		"fly under a bridge.", 0},
@@ -398,7 +398,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"[PH] In the ceiling of the conveyor belt + laser hallway.", 0},
 	{0,-13728,-13728,  1552, 24, 'D', SKINCOLOR_ORANGE, 0,
 		"[PH] On top of the platform with rows of spikes in reverse gravity.", 0},
-	{0,-14944,   768,  1232, 24, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0,-14944,   768,  1232, 24, 'E', SKINCOLOR_EMERALD, 0,
 		"Follow the leader.", 0},
 */
 
@@ -430,7 +430,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"The underground room\n"
 		"with platforms that fall and rise\n"
 		"only LOOKS empty...", 0},
-	{0 , 4960, -6112,  1312, 30, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0 , 4960, -6112,  1312, 30, 'E', SKINCOLOR_EMERALD, 0,
 		"This one's straightforward.\n"
 		"What comes to mind when I say:\n"
 		"\"WELCOME TO WARP ZONE!\"?", 0},
@@ -458,7 +458,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"Much like the last one,\n"
 		"you need to find some switches.\n"
 		"Only two, this time.", 0},
-	{0, 13184, 18880,  6672, 40, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0, 13184, 18880,  6672, 40, 'E', SKINCOLOR_EMERALD, 0,
 		"The inner sanctum!\n"
 		"Teleport to its switches;\n"
 		"then, check near the goal.", 0},
@@ -486,7 +486,7 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 		"A room of currents;\n"
 		"most of them are marked by spikes.\n"
 		"This one? A corner.", 0},
-	{0, -4128, 21344,  1120, 41, 'E', SKINCOLOR_NEONGREEN, 0,
+	{0, -4128, 21344,  1120, 41, 'E', SKINCOLOR_EMERALD, 0,
 		"The only way to hit\n"
 		"all those gems at once is with\n"
 		"a radial blast.", 0},
@@ -498,63 +498,63 @@ emblem_t emblemlocations[MAXEMBLEMS] =
 
 	// FLORAL FIELD
 	// ---
-	{0, 5394, -996, 160, 50, 'N', SKINCOLOR_ROSEWOOD, 0, "", 0},
+	{0, 5394, -996, 160, 50, 'N', SKINCOLOR_RUST, 0, "", 0},
 	{ET_NGRADE, 0,0,0,   50, 'Q', SKINCOLOR_TEAL,     GRADE_A, "", 0},
 	{ET_NTIME,  0,0,0,   50, 'T', SKINCOLOR_GREY,  40*TICRATE, "", 0},
 
 
 	// TOXIC PLATEAU
 	// ---
-	{0, 780, -1664, 32, 51, 'N', SKINCOLOR_ROSEWOOD, 0, "", 0},
+	{0, 780, -1664, 32, 51, 'N', SKINCOLOR_RUST, 0, "", 0},
 	{ET_NGRADE, 0,0,0,  51, 'Q', SKINCOLOR_TEAL,     GRADE_A, "", 0},
 	{ET_NTIME,  0,0,0,  51, 'T', SKINCOLOR_GREY,  50*TICRATE, "", 0},
 
 
 	// FLOODED COVE
 	// ---
-	{0, 1824, -1888, 2448, 52, 'N', SKINCOLOR_ROSEWOOD, 0, "", 0},
+	{0, 1824, -1888, 2448, 52, 'N', SKINCOLOR_RUST, 0, "", 0},
 	{ET_NGRADE, 0,0,0,     52, 'Q', SKINCOLOR_TEAL,     GRADE_A, "", 0},
 	{ET_NTIME,  0,0,0,     52, 'T', SKINCOLOR_GREY,  90*TICRATE, "", 0},
 
 
 	// CAVERN FORTRESS
 	// ---
-	{0, -3089, -431, 1328, 53, 'N', SKINCOLOR_ROSEWOOD, 0, "", 0},
+	{0, -3089, -431, 1328, 53, 'N', SKINCOLOR_RUST, 0, "", 0},
 	{ET_NGRADE, 0,0,0,     53, 'Q', SKINCOLOR_TEAL,     GRADE_A, "", 0},
 	{ET_NTIME,  0,0,0,     53, 'T', SKINCOLOR_GREY,  75*TICRATE, "", 0},
 
 
 	// DUSTY WASTELAND
 	// ---
-	{0, 957, 924, 2956, 54, 'N', SKINCOLOR_ROSEWOOD, 0, "", 0},
+	{0, 957, 924, 2956, 54, 'N', SKINCOLOR_RUST, 0, "", 0},
 	{ET_NGRADE, 0,0,0,  54, 'Q', SKINCOLOR_TEAL,     GRADE_A, "", 0},
 	{ET_NTIME,  0,0,0,  54, 'T', SKINCOLOR_GREY,  65*TICRATE, "", 0},
 
 
 	// MAGMA CAVES
 	// ---
-	{0, -2752, 3104, 1800, 55, 'N', SKINCOLOR_ROSEWOOD, 0, "", 0},
+	{0, -2752, 3104, 1800, 55, 'N', SKINCOLOR_RUST, 0, "", 0},
 	{ET_NGRADE, 0,0,0,     55, 'Q', SKINCOLOR_TEAL,     GRADE_A, "", 0},
 	{ET_NTIME,  0,0,0,     55, 'T', SKINCOLOR_GREY,  80*TICRATE, "", 0},
 
 
 	// EGG SATELLITE
 	// ---
-	{0, 5334, -609, 3426, 56, 'N', SKINCOLOR_ROSEWOOD, 0, "", 0},
+	{0, 5334, -609, 3426, 56, 'N', SKINCOLOR_RUST, 0, "", 0},
 	{ET_NGRADE, 0,0,0,    56, 'Q', SKINCOLOR_TEAL,     GRADE_A, "", 0},
 	{ET_NTIME,  0,0,0,    56, 'T', SKINCOLOR_GREY, 120*TICRATE, "", 0},
 
 
 	// BLACK HOLE
 	// ---
-	{0, 2108, 3776, 32, 57, 'N', SKINCOLOR_ROSEWOOD, 0, "", 0},
+	{0, 2108, 3776, 32, 57, 'N', SKINCOLOR_RUST, 0, "", 0},
 	{ET_NGRADE, 0,0,0,  57, 'Q', SKINCOLOR_TEAL,     GRADE_A, "", 0},
 	{ET_NTIME,  0,0,0,  57, 'T', SKINCOLOR_GREY, 150*TICRATE, "", 0},
 
 
 	// SPRING HILL
 	// ---
-	{0, -1840, -1024, 1644, 58, 'N', SKINCOLOR_ROSEWOOD, 0, "", 0},
+	{0, -1840, -1024, 1644, 58, 'N', SKINCOLOR_RUST, 0, "", 0},
 	{ET_NGRADE, 0,0,0,      58, 'Q', SKINCOLOR_TEAL,     GRADE_A, "", 0},
 	{ET_NTIME,  0,0,0,      58, 'T', SKINCOLOR_GREY,  60*TICRATE, "", 0},
 };
@@ -565,7 +565,7 @@ extraemblem_t extraemblems[MAXEXTRAEMBLEMS] =
 	{"Game Complete",  "Complete 1P Mode",                    10, 'X', SKINCOLOR_BLUE, 0},
 	{"All Emeralds",   "Complete 1P Mode with all Emeralds",  11, 'V', SKINCOLOR_GREY, 0},
 	{"Perfect Bonus",  "Perfect Bonus on a non-secret stage", 30, 'P', SKINCOLOR_GOLD, 0},
-	{"SRB1 Remake",    "Complete SRB1 Remake",                21, 'O', SKINCOLOR_ROSEWOOD, 0},
+	{"SRB1 Remake",    "Complete SRB1 Remake",                21, 'O', SKINCOLOR_RUST, 0},
 	{"NiGHTS Mastery", "Show your mastery of NiGHTS!",        22, 'W', SKINCOLOR_TEAL, 0},
 };
 
diff --git a/src/m_fixed.c b/src/m_fixed.c
index 25a25a96695dd8c7d020d22f6af57bdd2452be7f..53974936e4d0ccc9b5ac210065c1f170a5385888 100644
--- a/src/m_fixed.c
+++ b/src/m_fixed.c
@@ -119,8 +119,6 @@ fixed_t FixedHypot(fixed_t x, fixed_t y)
 	return FixedMul(ax, yx1); // |x|*((1 + (x/y)^2)^1/2)
 }
 
-#ifdef NEED_FIXED_VECTOR
-
 vector2_t *FV2_Load(vector2_t *vec, fixed_t x, fixed_t y)
 {
 	vec->x = x;
@@ -863,8 +861,6 @@ void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z)
 #undef M
 }
 
-#endif
-
 #ifdef M_TESTCASE
 //#define MULDIV_TEST
 #define SQRT_TEST
diff --git a/src/m_fixed.h b/src/m_fixed.h
index e68de03080fb4a3de8342ff6f0d8d1c4fab953c8..cd22d483fdea89c91a8a91b688a62ad391583b53 100644
--- a/src/m_fixed.h
+++ b/src/m_fixed.h
@@ -357,8 +357,6 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedRound(fixed_t x)
 	return INT32_MAX;
 }
 
-#ifdef NEED_FIXED_VECTOR
-
 typedef struct
 {
 	fixed_t x;
@@ -437,6 +435,4 @@ void FM_MultMatrix(matrix_t *dest, const matrix_t *multme);
 void FM_Translate(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
 void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
 
-#endif // defined NEED_FIXED_VECTOR
-
 #endif //m_fixed.h
diff --git a/src/m_menu.c b/src/m_menu.c
index 45b8d6f1a67136bbdcd849ce1e9b794b4febecb0..f25b902035de62ac90268b6b2a0c72c304f5b9ba 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -2202,6 +2202,7 @@ boolean M_Responder(event_t *ev)
 				if (modeattacking)
 					return true;
 				M_StartControlPanel();
+				M_Options(0);
 				currentMenu = &OP_SoundOptionsDef;
 				itemOn = 0;
 				return true;
@@ -2211,6 +2212,7 @@ boolean M_Responder(event_t *ev)
 				if (modeattacking)
 					return true;
 				M_StartControlPanel();
+				M_Options(0);
 				M_VideoModeMenu(0);
 				return true;
 #endif
@@ -2222,6 +2224,7 @@ boolean M_Responder(event_t *ev)
 				if (modeattacking)
 					return true;
 				M_StartControlPanel();
+				M_Options(0);
 				M_SetupNextMenu(&OP_MainDef);
 				return true;
 
@@ -2459,11 +2462,14 @@ void M_Drawer(void)
 			V_DrawThinString(vid.dupx, vid.height - 9*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, customversionstring);
 		}
 		else
-#if VERSION > 0 || SUBVERSION > 0
+		{
+#ifdef DEVELOP // Development -- show revision / branch info
+			V_DrawThinString(vid.dupx, vid.height - 17*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, compbranch);
+			V_DrawThinString(vid.dupx, vid.height - 9*vid.dupy,  V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision);
+#else // Regular build
 			V_DrawThinString(vid.dupx, vid.height - 9*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s", VERSIONSTRING));
-#else // Trunk build, show revision info
-			V_DrawThinString(vid.dupx, vid.height - 9*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s (%s)", VERSIONSTRING, comprevision));
 #endif
+		}
 	}
 }
 
@@ -2819,7 +2825,7 @@ static void M_DrawSlider(INT32 x, INT32 y, const consvar_t *cv)
 void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines)
 {
 	// Solid color textbox.
-	V_DrawFill(x+5, y+5, width*8+6, boxlines*8+6, 239);
+	V_DrawFill(x+5, y+5, width*8+6, boxlines*8+6, 159);
 	//V_DrawFill(x+8, y+8, width*8, boxlines*8, 31);
 /*
 	patch_t *p;
diff --git a/src/m_misc.c b/src/m_misc.c
index 57b8c4585166904d7f5ae2e6adb418d79ed10625..eaafc06967c24e6eb8c16cf8101a08bbf6d1131d 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -1800,16 +1800,14 @@ UINT8 M_HighestBit(UINT32 num)
 
 const char *GetRevisionString(void)
 {
-	INT32 vinfo;
-	static char rev[8] = {0};
+	static char rev[9] = {0};
 	if (rev[0])
 		return rev;
 
-	vinfo = atoi(&comprevision[1]);
-	if (vinfo)
-		snprintf(rev, 7, "r%d", vinfo);
+	if (comprevision[0] == 'r')
+		strncpy(rev, comprevision, 7);
 	else
-		strcpy(rev, "rNULL");
+		snprintf(rev, 7, "r%s", comprevision);
 	rev[7] = '\0';
 
 	return rev;
diff --git a/src/p_enemy.c b/src/p_enemy.c
index a1cc9dabc0118ecdaacb012d1bcbfa124c3e2c9b..09274b5a80de2fa6185eb4113dac01ba332cc5f5 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -5024,7 +5024,7 @@ void A_MaceRotate(mobj_t *actor)
 		actor->movecount += actor->target->lastlook;
 		actor->movecount &= FINEMASK;
 
-		actor->threshold = FixedMul(FINECOSINE(actor->movecount), actor->target->lastlook);
+		actor->threshold = FixedMul(FINECOSINE(actor->movecount), actor->target->lastlook << FRACBITS);
 
 		v[0] = FRACUNIT;
 		v[1] = 0;
@@ -5032,7 +5032,7 @@ void A_MaceRotate(mobj_t *actor)
 		v[3] = FRACUNIT;
 
 		// Calculate the angle matrixes for the link.
-		res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->threshold << FRACBITS)));
+		res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->threshold)));
 		M_Memcpy(&v, res, sizeof(v));
 		res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT));
 		M_Memcpy(&v, res, sizeof(v));
@@ -5606,8 +5606,13 @@ void A_MixUp(mobj_t *actor)
 
 				P_SetThingPosition(players[i].mo);
 
+#ifdef ESLOPE
+				players[i].mo->floorz = P_GetFloorZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL);
+				players[i].mo->ceilingz = P_GetCeilingZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL);
+#else
 				players[i].mo->floorz = players[i].mo->subsector->sector->floorheight;
 				players[i].mo->ceilingz = players[i].mo->subsector->sector->ceilingheight;
+#endif
 
 				P_CheckPosition(players[i].mo, players[i].mo->x, players[i].mo->y);
 			}
@@ -7592,48 +7597,35 @@ void A_SetTargetsTarget(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-	mobj_t *targetedmobj = NULL;
-	thinker_t *th;
-	mobj_t *mo2;
+	mobj_t *oldtarg = NULL, *newtarg = NULL;
 #ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SetTargetsTarget", actor))
 		return;
 #endif
 
-	if ((!locvar1 && (!actor->target)) || (locvar1 && (!actor->tracer)))
-		return;
-
-	if ((!locvar1 && !locvar2 && (!actor->target->target))
-	|| (!locvar1 && locvar2 && (!actor->target->tracer))
-	|| (locvar1 && !locvar2 && (!actor->tracer->target))
-	|| (locvar1 && locvar2 && (!actor->tracer->tracer)))
-		return; // Don't search for nothing.
-
-	// scan the thinkers
-	for (th = thinkercap.next; th != &thinkercap; th = th->next)
-	{
-		if (th->function.acp1 != (actionf_p1)P_MobjThinker)
-			continue;
+	// actor's target
+	if (locvar1) // or tracer
+		oldtarg = actor->tracer;
+	else
+		oldtarg = actor->target;
 
-		mo2 = (mobj_t *)th;
+	if (P_MobjWasRemoved(oldtarg))
+		return;
 
-		if ((!locvar1 && !locvar2 && (mo2 == actor->target->target))
-		|| (!locvar1 && locvar2 && (mo2 == actor->target->tracer))
-		|| (locvar1 && !locvar2 && (mo2 == actor->tracer->target))
-		|| (locvar1 && locvar2 && (mo2 == actor->tracer->tracer)))
-		{
-			targetedmobj = mo2;
-			break;
-		}
-	}
+	// actor's target's target!
+	if (locvar2) // or tracer
+		newtarg = oldtarg->tracer;
+	else
+		newtarg = oldtarg->target;
 
-	if (!targetedmobj)
-		return; // Oops, nothing found..
+	if (P_MobjWasRemoved(newtarg))
+		return;
 
-	if (!locvar1)
-		P_SetTarget(&actor->target, targetedmobj);
+	// set actor's new target
+	if (locvar1) // or tracer
+		P_SetTarget(&actor->tracer, newtarg);
 	else
-		P_SetTarget(&actor->tracer, targetedmobj);
+		P_SetTarget(&actor->target, newtarg);
 }
 
 // Function: A_SetObjectFlags
@@ -7650,26 +7642,33 @@ void A_SetObjectFlags(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
+	boolean unlinkthings = false;
 #ifdef HAVE_BLUA
 	if (LUA_CallAction("A_SetObjectFlags", actor))
 		return;
 #endif
 
-	P_UnsetThingPosition(actor);
-	if (sector_list)
-	{
-		P_DelSeclist(sector_list);
-		sector_list = NULL;
-	}
-
 	if (locvar2 == 2)
-		actor->flags |= locvar1;
+		locvar1 = actor->flags | locvar1;
 	else if (locvar2 == 1)
-		actor->flags &= ~locvar1;
-	else
-		actor->flags = locvar1;
+		locvar1 = actor->flags & ~locvar1;
 
-	P_SetThingPosition(actor);
+	if ((locvar1 & (MF_NOBLOCKMAP|MF_NOSECTOR)) != (actor->flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) // Blockmap/sector status has changed, so reset the links
+		unlinkthings = true;
+
+	if (unlinkthings) {
+		P_UnsetThingPosition(actor);
+		if (sector_list)
+		{
+			P_DelSeclist(sector_list);
+			sector_list = NULL;
+		}
+	}
+
+	actor->flags = locvar1;
+
+	if (unlinkthings)
+		P_SetThingPosition(actor);
 }
 
 // Function: A_SetObjectFlags2
diff --git a/src/p_floor.c b/src/p_floor.c
index fd85fd2ccf2c0949c6512b2b9cd9436cad0ebb57..ec52abeb96601bc61b78fbba51bbc676f1617925 100644
--- a/src/p_floor.c
+++ b/src/p_floor.c
@@ -1174,12 +1174,15 @@ void T_SpikeSector(levelspecthink_t *spikes)
 
 		if (affectsec == spikes->sector) // Applied to an actual sector
 		{
+			fixed_t affectfloor = P_GetSpecialBottomZ(thing, affectsec, affectsec);
+			fixed_t affectceil = P_GetSpecialTopZ(thing, affectsec, affectsec);
+
 			if (affectsec->flags & SF_FLIPSPECIAL_FLOOR)
 			{
 				if (!(thing->eflags & MFE_VERTICALFLIP) && thing->momz > 0)
 					continue;
 
-				if (thing->z == affectsec->floorheight)
+				if (thing->z == affectfloor)
 					dothepain = true;
 			}
 
@@ -1188,18 +1191,20 @@ void T_SpikeSector(levelspecthink_t *spikes)
 				if ((thing->eflags & MFE_VERTICALFLIP) && thing->momz < 0)
 					continue;
 
-				if (thing->z + thing->height == affectsec->ceilingheight)
+				if (thing->z + thing->height == affectceil)
 					dothepain = true;
 			}
 		}
 		else
 		{
+			fixed_t affectfloor = P_GetSpecialBottomZ(thing, affectsec, spikes->sector);
+			fixed_t affectceil = P_GetSpecialTopZ(thing, affectsec, spikes->sector);
 			if (affectsec->flags & SF_FLIPSPECIAL_FLOOR)
 			{
 				if (!(thing->eflags & MFE_VERTICALFLIP) && thing->momz > 0)
 					continue;
 
-				if (thing->z == affectsec->ceilingheight)
+				if (thing->z == affectceil)
 					dothepain = true;
 			}
 
@@ -1208,7 +1213,7 @@ void T_SpikeSector(levelspecthink_t *spikes)
 				if ((thing->eflags & MFE_VERTICALFLIP) && thing->momz < 0)
 					continue;
 
-				if (thing->z + thing->height == affectsec->floorheight)
+				if (thing->z + thing->height == affectfloor)
 					dothepain = true;
 			}
 		}
@@ -2085,6 +2090,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
 	boolean FOFsector = false;
 	boolean inAndOut = false;
 	boolean floortouch = false;
+	fixed_t bottomheight, topheight;
 
 	for (i = 0; i < MAXPLAYERS; i++)
 	{
@@ -2149,10 +2155,13 @@ void T_EachTimeThinker(levelspecthink_t *eachtime)
 					if (players[j].mo->subsector->sector != targetsec)
 						continue;
 
-					if (players[j].mo->z > sec->ceilingheight)
+					topheight = P_GetSpecialTopZ(players[j].mo, sec, targetsec);
+					bottomheight = P_GetSpecialBottomZ(players[j].mo, sec, targetsec);
+
+					if (players[j].mo->z > topheight)
 						continue;
 
-					if (players[j].mo->z + players[j].mo->height < sec->floorheight)
+					if (players[j].mo->z + players[j].mo->height < bottomheight)
 						continue;
 
 					if (floortouch == true && P_IsObjectOnGroundIn(players[j].mo, targetsec))
@@ -2312,7 +2321,7 @@ void T_RaiseSector(levelspecthink_t *raise)
 			if (raise->vars[1] && !(thing->player->pflags & PF_STARTDASH))
 				continue;
 
-			if (!(thing->z == raise->sector->ceilingheight))
+			if (!(thing->z == P_GetSpecialTopZ(thing, raise->sector, sector)))
 				continue;
 
 			playeronme = true;
diff --git a/src/p_inter.c b/src/p_inter.c
index d305cfc83a0fac01c3d7c6edb6b5c95d547339e0..e49d89eb4fb92b21601dce92f995b7ca33f73a37 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -1479,7 +1479,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
 		return; // Presumably it's obvious what's happening in splitscreen.
 
 #ifdef HAVE_BLUA
-	if (LUAh_DeathMsg(player, inflictor, source))
+	if (LUAh_HurtMsg(player, inflictor, source))
 		return;
 #endif
 
@@ -1648,11 +1648,126 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour
 		CONS_Printf(str, targetname, deadtarget ? M_GetText("killed") : M_GetText("hit"));
 }
 
+/** Checks if the level timer is over the timelimit and the round should end,
+  * unless you are in overtime. In which case leveltime may stretch out beyond
+  * timelimitintics and overtime's status will be checked here each tick.
+  * Verify that the value of ::cv_timelimit is greater than zero before
+  * calling this function.
+  *
+  * \sa cv_timelimit, P_CheckPointLimit, P_UpdateSpecials
+  */
+void P_CheckTimeLimit(void)
+{
+	INT32 i, k;
+
+	if (!cv_timelimit.value)
+		return;
+
+	if (!(multiplayer || netgame))
+		return;
+
+	if (G_PlatformGametype())
+		return;
+
+	if (leveltime < timelimitintics)
+		return;
+
+	if (gameaction == ga_completed)
+		return;
+
+	//Tagmode round end but only on the tic before the
+	//XD_EXITLEVEL packet is recieved by all players.
+	if (G_TagGametype())
+	{
+		if (leveltime == (timelimitintics + 1))
+		{
+			for (i = 0; i < MAXPLAYERS; i++)
+			{
+				if (!playeringame[i] || players[i].spectator
+				 || (players[i].pflags & PF_TAGGED) || (players[i].pflags & PF_TAGIT))
+					continue;
+
+				CONS_Printf(M_GetText("%s recieved double points for surviving the round.\n"), player_names[i]);
+				P_AddPlayerScore(&players[i], players[i].score);
+			}
+		}
+
+		if (server)
+			SendNetXCmd(XD_EXITLEVEL, NULL, 0);
+	}
+
+	//Optional tie-breaker for Match/CTF
+	else if (cv_overtime.value)
+	{
+		INT32 playerarray[MAXPLAYERS];
+		INT32 tempplayer = 0;
+		INT32 spectators = 0;
+		INT32 playercount = 0;
+
+		//Figure out if we have enough participating players to care.
+		for (i = 0; i < MAXPLAYERS; i++)
+		{
+			if (playeringame[i] && players[i].spectator)
+				spectators++;
+		}
+
+		if ((D_NumPlayers() - spectators) > 1)
+		{
+			// Play the starpost sfx after the first second of overtime.
+			if (gamestate == GS_LEVEL && (leveltime == (timelimitintics + TICRATE)))
+				S_StartSound(NULL, sfx_strpst);
+
+			// Normal Match
+			if (!G_GametypeHasTeams())
+			{
+				//Store the nodes of participating players in an array.
+				for (i = 0; i < MAXPLAYERS; i++)
+				{
+					if (playeringame[i] && !players[i].spectator)
+					{
+						playerarray[playercount] = i;
+						playercount++;
+					}
+				}
+
+				//Sort 'em.
+				for (i = 1; i < playercount; i++)
+				{
+					for (k = i; k < playercount; k++)
+					{
+						if (players[playerarray[i-1]].score < players[playerarray[k]].score)
+						{
+							tempplayer = playerarray[i-1];
+							playerarray[i-1] = playerarray[k];
+							playerarray[k] = tempplayer;
+						}
+					}
+				}
+
+				//End the round if the top players aren't tied.
+				if (players[playerarray[0]].score == players[playerarray[1]].score)
+					return;
+			}
+			else
+			{
+				//In team match and CTF, determining a tie is much simpler. =P
+				if (redscore == bluescore)
+					return;
+			}
+		}
+		if (server)
+			SendNetXCmd(XD_EXITLEVEL, NULL, 0);
+	}
+
+	if (server)
+		SendNetXCmd(XD_EXITLEVEL, NULL, 0);
+}
+
 /** Checks if a player's score is over the pointlimit and the round should end.
   * Verify that the value of ::cv_pointlimit is greater than zero before
   * calling this function.
   *
-  * \sa cv_pointlimit, P_UpdateSpecials
+  * \sa cv_pointlimit, P_CheckTimeLimit, P_UpdateSpecials
   */
 void P_CheckPointLimit(void)
 {
@@ -1953,7 +2068,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 	{
 		target->flags &= ~(MF_SOLID|MF_SHOOTABLE); // does not block
 		P_UnsetThingPosition(target);
-		target->flags |= MF_NOBLOCKMAP;
+		target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY;
 		P_SetThingPosition(target);
 
 		if (!target->player->bot && !G_IsSpecialStage(gamemap)
@@ -1996,7 +2111,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 			// allow them to try again, rather than sitting the whole thing out.
 			if (leveltime >= hidetime * TICRATE)
 			{
-				if (gametype == GT_HIDEANDSEEK)//suiciding in survivor makes you IT.
+				if (gametype == GT_TAG)//suiciding in survivor makes you IT.
 				{
 					target->player->pflags |= PF_TAGIT;
 					CONS_Printf(M_GetText("%s is now IT!\n"), player_names[target->player-players]); // Tell everyone who is it!
@@ -2289,7 +2404,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 		}
 	}
 	else if (target->player)
-		P_SetPlayerMobjState(target, target->info->deathstate);
+	{
+		if (damagetype == DMG_DROWNED || damagetype == DMG_SPACEDROWN)
+			P_SetPlayerMobjState(target, target->info->xdeathstate);
+		else
+			P_SetPlayerMobjState(target, target->info->deathstate);
+	}
 	else
 #ifdef DEBUG_NULL_DEATHSTATE
 		P_SetMobjState(target, S_NULL);
@@ -2582,7 +2702,7 @@ static inline void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *so
 	P_InstaThrust(player->mo, ang, fallbackspeed);
 
 	if (player->charflags & SF_SUPERANIMS)
-		P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_PAIN);
+		P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_STUN);
 	else
 		P_SetPlayerMobjState(player->mo, player->mo->info->painstate);
 
diff --git a/src/p_local.h b/src/p_local.h
index e496990ca3450e15890d75e75ef851f8b911794d..6bd40291288457425d2ba97548e0f9a4da5320a7 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -38,6 +38,9 @@
 #define MAPBMASK      (MAPBLOCKSIZE-1)
 #define MAPBTOFRAC    (MAPBLOCKSHIFT-FRACBITS)
 
+// Convenience macro to fix issue with collision along bottom/left edges of blockmap -Red
+#define BMBOUNDFIX(xl, xh, yl, yh) {if (xl > xh) xl = 0; if (yl > yh) yl = 0;}
+
 // player radius used only in am_map.c
 #define PLAYERRADIUS (16*FRACUNIT)
 
@@ -214,6 +217,23 @@ boolean P_RailThinker(mobj_t *mobj);
 void P_PushableThinker(mobj_t *mobj);
 void P_SceneryThinker(mobj_t *mobj);
 
+
+fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect);
+fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect);
+#define P_GetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(mobj, sector, NULL, x, y, line, false, false)
+#define P_GetCeilingZ(mobj, sector, x, y, line) P_MobjCeilingZ(mobj, sector, NULL, x, y, line, true, false)
+#define P_GetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(mobj, sectors + fof->secnum, sector, x, y, line, false, false)
+#define P_GetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(mobj, sectors + fof->secnum, sector, x, y, line, true, false)
+#define P_GetSpecialBottomZ(mobj, src, bound) P_MobjFloorZ(mobj, src, bound, mobj->x, mobj->y, NULL, src != bound, true)
+#define P_GetSpecialTopZ(mobj, src, bound) P_MobjCeilingZ(mobj, src, bound, mobj->x, mobj->y, NULL, src == bound, true)
+
+fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect);
+fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect);
+#define P_CameraGetFloorZ(mobj, sector, x, y, line) P_CameraFloorZ(mobj, sector, NULL, x, y, line, false, false)
+#define P_CameraGetCeilingZ(mobj, sector, x, y, line) P_CameraCeilingZ(mobj, sector, NULL, x, y, line, true, false)
+#define P_CameraGetFOFTopZ(mobj, sector, fof, x, y, line) P_CameraCeilingZ(mobj, sectors + fof->secnum, sector, x, y, line, false, false)
+#define P_CameraGetFOFBottomZ(mobj, sector, fof, x, y, line) P_CameraFloorZ(mobj, sectors + fof->secnum, sector, x, y, line, true, false)
+
 boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover);
 boolean P_CheckDeathPitCollide(mobj_t *mo);
 boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover);
@@ -273,8 +293,13 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
 extern boolean floatok;
 extern fixed_t tmfloorz;
 extern fixed_t tmceilingz;
-extern mobj_t *tmfloorthing, *tmthing;
+extern mobj_t *tmfloorthing, *tmhitthing, *tmthing;
 extern camera_t *mapcampointer;
+extern fixed_t tmx;
+extern fixed_t tmy;
+#ifdef ESLOPE
+extern pslope_t *tmfloorslope, *tmceilingslope;
+#endif
 
 /* cphipps 2004/08/30 */
 extern void P_MapStart(void);
@@ -313,7 +338,7 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist);
 fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height);
 boolean PIT_PushableMoved(mobj_t *thing);
 
-void P_DoSpring(mobj_t *spring, mobj_t *object);
+boolean P_DoSpring(mobj_t *spring, mobj_t *object);
 
 //
 // P_SETUP
@@ -372,6 +397,7 @@ void P_PlayerEmeraldBurst(player_t *player, boolean toss);
 
 void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck);
 void P_PlayerFlagBurst(player_t *player, boolean toss);
+void P_CheckTimeLimit(void);
 void P_CheckPointLimit(void);
 void P_CheckSurvivors(void);
 boolean P_CheckRacers(void);
diff --git a/src/p_map.c b/src/p_map.c
index 8bdf6987bf9bd835e34a1a41331a178ae150b4ef..2f9824641841618a732cd8991a91ce14434bff45 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -27,6 +27,10 @@
 
 #include "r_splats.h"
 
+#ifdef ESLOPE
+#include "p_slopes.h"
+#endif
+
 #include "z_zone.h"
 
 #include "lua_hook.h"
@@ -34,8 +38,8 @@
 fixed_t tmbbox[4];
 mobj_t *tmthing;
 static INT32 tmflags;
-static fixed_t tmx;
-static fixed_t tmy;
+fixed_t tmx;
+fixed_t tmy;
 
 static precipmobj_t *tmprecipthing;
 static fixed_t preciptmbbox[4];
@@ -47,7 +51,10 @@ boolean floatok;
 fixed_t tmfloorz, tmceilingz;
 static fixed_t tmdropoffz, tmdrpoffceilz; // drop-off floor/ceiling heights
 mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz is from a sector
-static mobj_t *tmhitthing; // the solid thing you bumped into (for collisions)
+mobj_t *tmhitthing; // the solid thing you bumped into (for collisions)
+#ifdef ESLOPE
+pslope_t *tmfloorslope, *tmceilingslope;
+#endif
 
 // keep track of the line that lowers the ceiling,
 // so missiles don't explode against sky hack walls
@@ -102,7 +109,7 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
 //                       MOVEMENT ITERATOR FUNCTIONS
 // =========================================================================
 
-void P_DoSpring(mobj_t *spring, mobj_t *object)
+boolean P_DoSpring(mobj_t *spring, mobj_t *object)
 {
 	INT32 pflags;
 	fixed_t offx, offy;
@@ -110,18 +117,18 @@ void P_DoSpring(mobj_t *spring, mobj_t *object)
 	fixed_t horizspeed = spring->info->damage;
 
 	if (object->eflags & MFE_SPRUNG) // Object was already sprung this tic
-		return;
+		return false;
 
 	// Spectators don't trigger springs.
 	if (object->player && object->player->spectator)
-		return;
+		return false;
 
 	if (object->player && (object->player->pflags & PF_NIGHTSMODE))
 	{
 		/*Someone want to make these work like bumpers?*/
-		return;
+		return false;
 	}
-	
+
 	object->eflags |= MFE_SPRUNG; // apply this flag asap!
 	spring->flags &= ~(MF_SOLID|MF_SPECIAL); // De-solidify
 
@@ -192,7 +199,7 @@ void P_DoSpring(mobj_t *spring, mobj_t *object)
 		P_ResetPlayer(object->player);
 
 		if (P_MobjFlip(object)*vertispeed > 0)
-			P_SetPlayerMobjState(object, S_PLAY_JUMP);
+			P_SetPlayerMobjState(object, S_PLAY_SPRING);
 		else if (P_MobjFlip(object)*vertispeed < 0)
 			P_SetPlayerMobjState(object, S_PLAY_FALL);
 		else // horizontal spring
@@ -206,9 +213,10 @@ void P_DoSpring(mobj_t *spring, mobj_t *object)
 		if (spring->info->painchance)
 		{
 			object->player->pflags |= PF_JUMPED;
-			P_SetPlayerMobjState(object, S_PLAY_SPIN);
+			P_SetPlayerMobjState(object, S_PLAY_JUMP);
 		}
 	}
+	return true;
 }
 
 static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
@@ -365,6 +373,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails)
 static boolean PIT_CheckThing(mobj_t *thing)
 {
 	fixed_t blockdist;
+	boolean iwassprung = false;
 
 	// don't clip against self
 	if (thing == tmthing)
@@ -829,7 +838,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
 		{
 			if ( thing->z <= tmthing->z + tmthing->height
 			&& tmthing->z <= thing->z + thing->height)
-				P_DoSpring(thing, tmthing);
+				iwassprung = P_DoSpring(thing, tmthing);
 		}
 	}
 
@@ -916,7 +925,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
 		{
 			if ( thing->z <= tmthing->z + tmthing->height
 			&& tmthing->z <= thing->z + thing->height)
-				P_DoSpring(thing, tmthing);
+				iwassprung = P_DoSpring(thing, tmthing);
 		}
 		// Are you touching the side of the object you're interacting with?
 		else if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height
@@ -938,12 +947,14 @@ static boolean PIT_CheckThing(mobj_t *thing)
 		}
 	}
 
-
-	if (thing->flags & MF_SPRING && (tmthing->player || tmthing->flags & MF_PUSHABLE));
-	else
+	if (thing->flags & MF_SPRING && (tmthing->player || tmthing->flags & MF_PUSHABLE))
+	{
+		if (iwassprung) // this spring caused you to gain MFE_SPRUNG just now...
+			return false; // "cancel" P_TryMove via blocking so you keep your current position
+	}
 	// Monitors are not treated as solid to players who are jumping, spinning or gliding,
 	// unless it's a CTF team monitor and you're on the wrong team
-	if (thing->flags & MF_MONITOR && tmthing->player && tmthing->player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING)
+	else if (thing->flags & MF_MONITOR && tmthing->player && tmthing->player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING)
 	&& !((thing->type == MT_REDRINGBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_BLUERINGBOX && tmthing->player->ctfteam != 2)))
 		;
 	// z checking at last
@@ -963,6 +974,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
 				if (thing->z + thing->height > tmfloorz)
 				{
 					tmfloorz = thing->z + thing->height;
+#ifdef ESLOPE
+					tmfloorslope = NULL;
+#endif
 				}
 				return true;
 			}
@@ -981,6 +995,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
 			else if (topz < tmceilingz && tmthing->z+tmthing->height <= thing->z+thing->height)
 			{
 				tmceilingz = topz;
+#ifdef ESLOPE
+				tmceilingslope = NULL;
+#endif
 				tmfloorthing = thing; // thing we may stand on
 			}
 		}
@@ -994,6 +1011,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
 				if (thing->z < tmceilingz)
 				{
 					tmceilingz = thing->z;
+#ifdef ESLOPE
+					tmceilingslope = NULL;
+#endif
 				}
 				return true;
 			}
@@ -1011,6 +1031,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
 			else if (topz > tmfloorz && tmthing->z >= thing->z)
 			{
 				tmfloorz = topz;
+#ifdef ESLOPE
+				tmfloorslope = NULL;
+#endif
 				tmfloorthing = thing; // thing we may stand on
 			}
 		}
@@ -1133,11 +1156,13 @@ static boolean PIT_CheckLine(line_t *ld)
 	{
 		tmceilingz = opentop;
 		ceilingline = ld;
+		tmceilingslope = opentopslope;
 	}
 
 	if (openbottom > tmfloorz)
 	{
 		tmfloorz = openbottom;
+		tmfloorslope = openbottomslope;
 	}
 
 	if (highceiling > tmdrpoffceilz)
@@ -1214,8 +1239,12 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 	// that contains the point.
 	// Any contacted lines the step closer together
 	// will adjust them.
-	tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
-	tmceilingz = tmdrpoffceilz = newsubsec->sector->ceilingheight;
+	tmfloorz = tmdropoffz = P_GetFloorZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->floorheight;
+	tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight;
+#ifdef ESLOPE
+	tmfloorslope = newsubsec->sector->f_slope;
+	tmceilingslope = newsubsec->sector->c_slope;
+#endif
 
 	// Check list of fake floors and see if tmfloorz/tmceilingz need to be altered.
 	if (newsubsec->sector->ffloors)
@@ -1226,35 +1255,48 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 
 		for (rover = newsubsec->sector->ffloors; rover; rover = rover->next)
 		{
+			fixed_t topheight, bottomheight;
+
 			if (!(rover->flags & FF_EXISTS))
 				continue;
 
+			topheight = P_GetFOFTopZ(thing, newsubsec->sector, rover, x, y, NULL);
+			bottomheight = P_GetFOFBottomZ(thing, newsubsec->sector, rover, x, y, NULL);
+
 			if (rover->flags & FF_GOOWATER && !(thing->flags & MF_NOGRAVITY))
 			{
 				// If you're inside goowater and slowing down
 				fixed_t sinklevel = FixedMul(thing->info->height/6, thing->scale);
-				fixed_t minspeed = FixedMul(thing->info->height/12, thing->scale);
-				if (thing->z < *rover->topheight && *rover->bottomheight < thingtop
+				fixed_t minspeed = FixedMul(thing->info->height/9, thing->scale);
+				if (thing->z < topheight && bottomheight < thingtop
 				&& abs(thing->momz) < minspeed)
 				{
 					// Oh no! The object is stick in between the surface of the goo and sinklevel! help them out!
-					if (!(thing->eflags & MFE_VERTICALFLIP) && thing->z > *rover->topheight - sinklevel
+					if (!(thing->eflags & MFE_VERTICALFLIP) && thing->z > topheight - sinklevel
 					&& thing->momz >= 0 && thing->momz < (minspeed>>2))
 						thing->momz += minspeed>>2;
-					else if (thing->eflags & MFE_VERTICALFLIP && thingtop < *rover->bottomheight + sinklevel
+					else if (thing->eflags & MFE_VERTICALFLIP && thingtop < bottomheight + sinklevel
 					&& thing->momz <= 0 && thing->momz > -(minspeed>>2))
 						thing->momz -= minspeed>>2;
 
 					// Land on the top or the bottom, depending on gravity flip.
-					if (!(thing->eflags & MFE_VERTICALFLIP) && thing->z >= *rover->topheight - sinklevel && thing->momz <= 0)
+					if (!(thing->eflags & MFE_VERTICALFLIP) && thing->z >= topheight - sinklevel && thing->momz <= 0)
 					{
-						if (tmfloorz < *rover->topheight - sinklevel)
-							tmfloorz = *rover->topheight - sinklevel;
+						if (tmfloorz < topheight - sinklevel) {
+							tmfloorz = topheight - sinklevel;
+#ifdef ESLOPE
+							tmfloorslope = *rover->t_slope;
+#endif
+						}
 					}
-					else if (thing->eflags & MFE_VERTICALFLIP && thingtop <= *rover->bottomheight + sinklevel && thing->momz >= 0)
+					else if (thing->eflags & MFE_VERTICALFLIP && thingtop <= bottomheight + sinklevel && thing->momz >= 0)
 					{
-						if (tmceilingz > *rover->bottomheight + sinklevel)
-							tmceilingz = *rover->bottomheight + sinklevel;
+						if (tmceilingz > bottomheight + sinklevel) {
+							tmceilingz = bottomheight + sinklevel;
+#ifdef ESLOPE
+							tmceilingslope = *rover->b_slope;
+#endif
+						}
 					}
 				}
 				continue;
@@ -1271,30 +1313,40 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 
 			if (rover->flags & FF_QUICKSAND)
 			{
-				if (thing->z < *rover->topheight && *rover->bottomheight < thingtop)
+				if (thing->z < topheight && bottomheight < thingtop)
 				{
-					if (tmfloorz < thing->z)
+					if (tmfloorz < thing->z) {
 						tmfloorz = thing->z;
+#ifdef ESLOPE
+						tmfloorslope = NULL;
+#endif
+					}
 				}
 				// Quicksand blocks never change heights otherwise.
 				continue;
 			}
 
-			delta1 = thing->z - (*rover->bottomheight
-				+ ((*rover->topheight - *rover->bottomheight)/2));
-			delta2 = thingtop - (*rover->bottomheight
-				+ ((*rover->topheight - *rover->bottomheight)/2));
+			delta1 = thing->z - (bottomheight
+				+ ((topheight - bottomheight)/2));
+			delta2 = thingtop - (bottomheight
+				+ ((topheight - bottomheight)/2));
 
-			if (*rover->topheight > tmfloorz && abs(delta1) < abs(delta2)
+			if (topheight > tmfloorz && abs(delta1) < abs(delta2)
 				&& !(rover->flags & FF_REVERSEPLATFORM))
 			{
-				tmfloorz = tmdropoffz = *rover->topheight;
+				tmfloorz = tmdropoffz = topheight;
+#ifdef ESLOPE
+				tmfloorslope = *rover->t_slope;
+#endif
 			}
-			if (*rover->bottomheight < tmceilingz && abs(delta1) >= abs(delta2)
+			if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2)
 				&& !(rover->flags & FF_PLATFORM)
 				&& !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)))
 			{
-				tmceilingz = tmdrpoffceilz = *rover->bottomheight;
+				tmceilingz = tmdrpoffceilz = bottomheight;
+#ifdef ESLOPE
+				tmceilingslope = *rover->b_slope;
+#endif
 			}
 		}
 	}
@@ -1304,10 +1356,12 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 	// based on their origin point, and can overlap
 	// into adjacent blocks by up to MAXRADIUS units.
 
-	xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
-	xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
-	yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
-	yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
+	xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
+	xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
+	yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
+	yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
+
+	BMBOUNDFIX(xl, xh, yl, yh);
 
 #ifdef POLYOBJECTS
 	// Check polyobjects and see if tmfloorz/tmceilingz need to be altered
@@ -1365,11 +1419,19 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
 						delta1 = thing->z - (polybottom + ((polytop - polybottom)/2));
 						delta2 = thingtop - (polybottom + ((polytop - polybottom)/2));
 
-						if (polytop > tmfloorz && abs(delta1) < abs(delta2))
+						if (polytop > tmfloorz && abs(delta1) < abs(delta2)) {
 							tmfloorz = tmdropoffz = polytop;
+#ifdef ESLOPE
+							tmfloorslope = NULL;
+#endif
+						}
 
-						if (polybottom < tmceilingz && abs(delta1) >= abs(delta2))
+						if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) {
 							tmceilingz = tmdrpoffceilz = polybottom;
+#ifdef ESLOPE
+							tmceilingslope = NULL;
+#endif
+						}
 					}
 					plink = (polymaplink_t *)(plink->link.next);
 				}
@@ -1471,8 +1533,9 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
 	// that contains the point.
 	// Any contacted lines the step closer together
 	// will adjust them.
-	tmfloorz = tmdropoffz = newsubsec->sector->floorheight;
-	tmceilingz = tmdrpoffceilz = newsubsec->sector->ceilingheight;
+	tmfloorz = tmdropoffz = P_CameraGetFloorZ(thiscam, newsubsec->sector, x, y, NULL);
+
+	tmceilingz = P_CameraGetCeilingZ(thiscam, newsubsec->sector, x, y, NULL);
 
 	// Cameras use the heightsec's heights rather then the actual sector heights.
 	// If you can see through it, why not move the camera through it too?
@@ -1498,20 +1561,24 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
 
 		for (rover = newsubsec->sector->ffloors; rover; rover = rover->next)
 		{
+			fixed_t topheight, bottomheight;
 			if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERALL) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12)
 				continue;
 
-			delta1 = thiscam->z - (*rover->bottomheight
-				+ ((*rover->topheight - *rover->bottomheight)/2));
-			delta2 = thingtop - (*rover->bottomheight
-				+ ((*rover->topheight - *rover->bottomheight)/2));
-			if (*rover->topheight > tmfloorz && abs(delta1) < abs(delta2))
+			topheight = P_CameraGetFOFTopZ(thiscam, newsubsec->sector, rover, x, y, NULL);
+			bottomheight = P_CameraGetFOFBottomZ(thiscam, newsubsec->sector, rover, x, y, NULL);
+
+			delta1 = thiscam->z - (bottomheight
+				+ ((topheight - bottomheight)/2));
+			delta2 = thingtop - (bottomheight
+				+ ((topheight - bottomheight)/2));
+			if (topheight > tmfloorz && abs(delta1) < abs(delta2))
 			{
-				tmfloorz = tmdropoffz = *rover->topheight;
+				tmfloorz = tmdropoffz = topheight;
 			}
-			if (*rover->bottomheight < tmceilingz && abs(delta1) >= abs(delta2))
+			if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2))
 			{
-				tmceilingz = tmdrpoffceilz = *rover->bottomheight;
+				tmceilingz = tmdrpoffceilz = bottomheight;
 			}
 		}
 	}
@@ -1521,10 +1588,12 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
 	// based on their origin point, and can overlap
 	// into adjacent blocks by up to MAXRADIUS units.
 
-	xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
-	xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
-	yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
-	yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
+	xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
+	xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
+	yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
+	yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
+
+	BMBOUNDFIX(xl, xh, yl, yh);
 
 #ifdef POLYOBJECTS
 	// Check polyobjects and see if tmfloorz/tmceilingz need to be altered
@@ -1704,8 +1773,8 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
 	}
 	else
 	{
-		tmfloorz = thiscam->subsector->sector->floorheight;
-		tmceilingz = thiscam->subsector->sector->ceilingheight;
+		tmfloorz = P_CameraGetFloorZ(thiscam, thiscam->subsector->sector, x, y, NULL);
+		tmceilingz = P_CameraGetCeilingZ(thiscam, thiscam->subsector->sector, x, y, NULL);
 	}
 
 	// the move is ok,
@@ -1771,6 +1840,10 @@ boolean PIT_PushableMoved(mobj_t *thing)
 		mobj_t *oldthing = tmthing;
 		line_t *oldceilline = ceilingline;
 		line_t *oldblockline = blockingline;
+#ifdef ESLOPE
+		pslope_t *oldfslope = tmfloorslope;
+		pslope_t *oldcslope = tmceilingslope;
+#endif
 
 		// Move the player
 		P_TryMove(thing, thing->x+stand->momx, thing->y+stand->momy, true);
@@ -1783,6 +1856,10 @@ boolean PIT_PushableMoved(mobj_t *thing)
 		P_SetTarget(&tmthing, oldthing);
 		ceilingline = oldceilline;
 		blockingline = oldblockline;
+#ifdef ESLOPE
+		tmfloorslope = oldfslope;
+		tmceilingslope = oldcslope;
+#endif
 		thing->momz = stand->momz;
 	}
 	else
@@ -1804,6 +1881,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 	fixed_t tryy = thing->y;
 	fixed_t radius = thing->radius;
 	fixed_t thingtop = thing->z + thing->height;
+#ifdef ESLOPE
+	fixed_t startingonground = P_IsObjectOnGround(thing);
+#endif
 	floatok = false;
 
 	if (radius < MAXRADIUS/2)
@@ -1849,7 +1929,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 
 				// Don't 'step up' while springing,
 				// Only step up "if needed".
-				if (thing->state-states == S_PLAY_JUMP
+				if (thing->player->panim == PA_SPRING
 				&& P_MobjFlip(thing)*thing->momz > FixedMul(FRACUNIT, thing->scale))
 					maxstep = 0;
 			}
@@ -1892,13 +1972,23 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 				{
 					if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep)
 					{
-						thing->z = tmceilingz - thing->height;
+						thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
+						thing->eflags |= MFE_JUSTSTEPPEDDOWN;
+					}
+					else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
+					{
+						thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
 						thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 					}
 				}
 				else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep)
 				{
-					thing->z = tmfloorz;
+					thing->z = thing->floorz = tmfloorz;
+					thing->eflags |= MFE_JUSTSTEPPEDDOWN;
+				}
+				else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
+				{
+					thing->z = thing->floorz = tmfloorz;
 					thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 				}
 			}
@@ -1948,10 +2038,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 	{
 		INT32 bx, by, xl, xh, yl, yh;
 
-		yh = (thing->y + MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT;
-		yl = (thing->y - MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT;
-		xh = (thing->x + MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT;
-		xl = (thing->x - MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT;
+		yh = (unsigned)(thing->y + MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT;
+		yl = (unsigned)(thing->y - MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT;
+		xh = (unsigned)(thing->x + MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT;
+		xl = (unsigned)(thing->x - MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT;
+
+		BMBOUNDFIX(xl, xh, yl, yh);
 
 		stand = thing;
 		standx = x;
@@ -1967,6 +2059,25 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 
 	thing->floorz = tmfloorz;
 	thing->ceilingz = tmceilingz;
+
+#ifdef ESLOPE
+	// Assign thing's standingslope if needed
+	if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) {
+		if (!startingonground && tmfloorslope)
+			P_HandleSlopeLanding(thing, tmfloorslope);
+
+		if (thing->momz <= 0)
+			thing->standingslope = tmfloorslope;
+	}
+	else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) {
+		if (!startingonground && tmceilingslope)
+			P_HandleSlopeLanding(thing, tmceilingslope);
+
+		if (thing->momz >= 0)
+			thing->standingslope = tmceilingslope;
+	}
+#endif
+
 	thing->x = x;
 	thing->y = y;
 
@@ -1982,6 +2093,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
 {
 	fixed_t tryx, tryy;
+
 	tryx = thing->x;
 	tryy = thing->y;
 	do {
@@ -2046,6 +2158,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
 //
 static boolean P_ThingHeightClip(mobj_t *thing)
 {
+	boolean floormoved;
 	fixed_t oldfloorz = thing->floorz;
 	boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz);
 
@@ -2057,6 +2170,9 @@ static boolean P_ThingHeightClip(mobj_t *thing)
 	if (P_MobjWasRemoved(thing))
 		return true;
 
+	floormoved = (thing->eflags & MFE_VERTICALFLIP && tmceilingz != thing->ceilingz)
+		|| (!(thing->eflags & MFE_VERTICALFLIP) && tmfloorz != thing->floorz);
+
 	thing->floorz = tmfloorz;
 	thing->ceilingz = tmceilingz;
 
@@ -2065,20 +2181,13 @@ static boolean P_ThingHeightClip(mobj_t *thing)
 	if (tmfloorz > oldfloorz+thing->height)
 		return true;
 
-	if (/*!tmfloorthing && */onfloor && !(thing->flags & MF_NOGRAVITY))
+	if (onfloor && !(thing->flags & MF_NOGRAVITY) && floormoved)
 	{
 		if (thing->eflags & MFE_VERTICALFLIP)
 			thing->pmomz = thing->ceilingz - (thing->z + thing->height);
 		else
 			thing->pmomz = thing->floorz - thing->z;
-
-		if (thing->player)
-		{
-			if (splitscreen && camera2.chase && thing->player == &players[secondarydisplayplayer])
-				camera2.z += thing->pmomz;
-			else if (camera.chase && thing->player == &players[displayplayer])
-				camera.z += thing->pmomz;
-		}
+		thing->eflags |= MFE_APPLYPMOMZ;
 
 		if (thing->eflags & MFE_VERTICALFLIP)
 			thing->z = thing->ceilingz - thing->height;
@@ -2307,15 +2416,25 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
 {
 	fixed_t platx, platy;
 	subsector_t *glidesector;
+	fixed_t floorz, ceilingz;
 
 	platx = P_ReturnThrustX(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
 	platy = P_ReturnThrustY(player->mo, angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale));
 
 	glidesector = R_PointInSubsector(player->mo->x + platx, player->mo->y + platy);
 
+#ifdef ESLOPE
+	floorz = glidesector->sector->f_slope ? P_GetZAt(glidesector->sector->f_slope, player->mo->x, player->mo->y) : glidesector->sector->floorheight;
+	ceilingz = glidesector->sector->c_slope ? P_GetZAt(glidesector->sector->c_slope, player->mo->x, player->mo->y) : glidesector->sector->ceilingheight;
+#else
+	floorz = glidesector->sector->floorheight;
+	ceilingz = glidesector->sector->ceilingheight;
+#endif
+
 	if (glidesector->sector != player->mo->subsector->sector)
 	{
 		boolean floorclimb = false;
+		fixed_t topheight, bottomheight;
 
 		if (glidesector->sector->ffloors)
 		{
@@ -2325,34 +2444,44 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
 				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER))
 					continue;
 
+				topheight = *rover->topheight;
+				bottomheight = *rover->bottomheight;
+
+#ifdef ESLOPE
+				if (*rover->t_slope)
+					topheight = P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y);
+				if (*rover->b_slope)
+					bottomheight = P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y);
+#endif
+
 				floorclimb = true;
 
 				if (player->mo->eflags & MFE_VERTICALFLIP)
 				{
-					if ((*rover->topheight < player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) < *rover->topheight))
+					if ((topheight < player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) < topheight))
 					{
 						floorclimb = true;
 					}
-					if (*rover->topheight < player->mo->z) // Waaaay below the ledge.
+					if (topheight < player->mo->z) // Waaaay below the ledge.
 					{
 						floorclimb = false;
 					}
-					if (*rover->bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale))
+					if (bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale))
 					{
 						floorclimb = false;
 					}
 				}
 				else
 				{
-					if ((*rover->bottomheight > player->mo->z) && ((player->mo->z - player->mo->momz) > *rover->bottomheight))
+					if ((bottomheight > player->mo->z) && ((player->mo->z - player->mo->momz) > bottomheight))
 					{
 						floorclimb = true;
 					}
-					if (*rover->bottomheight > player->mo->z + player->mo->height) // Waaaay below the ledge.
+					if (bottomheight > player->mo->z + player->mo->height) // Waaaay below the ledge.
 					{
 						floorclimb = false;
 					}
-					if (*rover->topheight < player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale))
+					if (topheight < player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale))
 					{
 						floorclimb = false;
 					}
@@ -2365,30 +2494,30 @@ static boolean P_IsClimbingValid(player_t *player, angle_t angle)
 
 		if (player->mo->eflags & MFE_VERTICALFLIP)
 		{
-			if ((glidesector->sector->floorheight <= player->mo->z + player->mo->height)
-				&& ((player->mo->z + player->mo->height - player->mo->momz) <= glidesector->sector->floorheight))
+			if ((floorz <= player->mo->z + player->mo->height)
+				&& ((player->mo->z + player->mo->height - player->mo->momz) <= floorz))
 				floorclimb = true;
 
-			if ((glidesector->sector->floorheight > player->mo->z)
+			if ((floorz > player->mo->z)
 				&& glidesector->sector->floorpic == skyflatnum)
 				return false;
 
-			if ((player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale) > glidesector->sector->ceilingheight)
-				|| (player->mo->z + player->mo->height <= glidesector->sector->floorheight))
+			if ((player->mo->z + player->mo->height - FixedMul(16*FRACUNIT,player->mo->scale) > ceilingz)
+				|| (player->mo->z + player->mo->height <= floorz))
 				floorclimb = true;
 		}
 		else
 		{
-			if ((glidesector->sector->ceilingheight >= player->mo->z)
-				&& ((player->mo->z - player->mo->momz) >= glidesector->sector->ceilingheight))
+			if ((ceilingz >= player->mo->z)
+				&& ((player->mo->z - player->mo->momz) >= ceilingz))
 				floorclimb = true;
 
-			if ((glidesector->sector->ceilingheight < player->mo->z+player->mo->height)
+			if ((ceilingz < player->mo->z+player->mo->height)
 				&& glidesector->sector->ceilingpic == skyflatnum)
 				return false;
 
-			if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < glidesector->sector->floorheight)
-				|| (player->mo->z >= glidesector->sector->ceilingheight))
+			if ((player->mo->z + FixedMul(16*FRACUNIT,player->mo->scale) < ceilingz)
+				|| (player->mo->z >= ceilingz))
 				floorclimb = true;
 		}
 
@@ -2460,6 +2589,7 @@ isblocking:
 		line_t *checkline = li;
 		sector_t *checksector;
 		ffloor_t *rover;
+		fixed_t topheight, bottomheight;
 		boolean fofline = false;
 		INT32 side = P_PointOnLineSide(slidemo->x, slidemo->y, li);
 
@@ -2475,13 +2605,23 @@ isblocking:
 				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
 					continue;
 
-				if (*rover->topheight < slidemo->z)
+				topheight = *rover->topheight;
+				bottomheight = *rover->bottomheight;
+
+#ifdef ESLOPE
+				if (*rover->t_slope)
+					topheight = P_GetZAt(*rover->t_slope, slidemo->x, slidemo->y);
+				if (*rover->b_slope)
+					bottomheight = P_GetZAt(*rover->b_slope, slidemo->x, slidemo->y);
+#endif
+
+				if (topheight < slidemo->z)
 					continue;
 
-				if (*rover->bottomheight > slidemo->z + slidemo->height)
+				if (bottomheight > slidemo->z + slidemo->height)
 					continue;
 
-				// Got this far, so I guess it's climbable.
+				// Got this far, so I guess it's climbable. // TODO: Climbing check, also, better method to do this?
 				if (rover->master->flags & ML_TFERLINE)
 				{
 					size_t linenum = li-checksector->lines[0];
@@ -3034,10 +3174,12 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist)
 	fixed_t dist;
 
 	dist = FixedMul(damagedist, spot->scale) + MAXRADIUS;
-	yh = (spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT;
-	yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT;
-	xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT;
-	xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT;
+	yh = (unsigned)(spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT;
+	yl = (unsigned)(spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT;
+	xh = (unsigned)(spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT;
+	xl = (unsigned)(spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT;
+
+	BMBOUNDFIX(xl, xh, yl, yh);
 
 	bombspot = spot;
 	bombsource = source;
@@ -3099,6 +3241,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
 		if (thing->subsector->sector->ffloors && (realcrush || thing->flags & MF_PUSHABLE))
 		{
 			ffloor_t *rover;
+			fixed_t topheight, bottomheight;
 			fixed_t delta1, delta2;
 			INT32 thingtop = thing->z + thing->height;
 
@@ -3108,9 +3251,19 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
 				|| ((rover->flags & FF_BLOCKOTHERS) && !thing->player)) || !(rover->flags & FF_EXISTS))
 					continue;
 
-				delta1 = thing->z - (*rover->bottomheight + *rover->topheight)/2;
-				delta2 = thingtop - (*rover->bottomheight + *rover->topheight)/2;
-				if (*rover->bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2))
+				topheight = *rover->topheight;
+				bottomheight = *rover->bottomheight;
+
+/*#ifdef ESLOPE
+				if (rover->t_slope)
+					topheight = P_GetZAt(rover->t_slope, thing->x, thing->y);
+				if (rover->b_slope)
+					bottomheight = P_GetZAt(rover->b_slope, thing->x, thing->y);
+#endif*/
+
+				delta1 = thing->z - (bottomheight + topheight)/2;
+				delta2 = thingtop - (bottomheight + topheight)/2;
+				if (bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2))
 				{
 					if (thing->flags & MF_PUSHABLE)
 					{
@@ -3648,10 +3801,12 @@ void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y)
 
 	validcount++; // used to make sure we only process a line once
 
-	xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
-	xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
-	yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
-	yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
+	xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
+	xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
+	yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
+	yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
+
+	BMBOUNDFIX(xl, xh, yl, yh);
 
 	for (bx = xl; bx <= xh; bx++)
 		for (by = yl; by <= yh; by++)
@@ -3725,10 +3880,12 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing,fixed_t x,fixed_t y)
 
 	validcount++; // used to make sure we only process a line once
 
-	xl = (preciptmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
-	xh = (preciptmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
-	yl = (preciptmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
-	yh = (preciptmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
+	xl = (unsigned)(preciptmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
+	xh = (unsigned)(preciptmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
+	yl = (unsigned)(preciptmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
+	yh = (unsigned)(preciptmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
+
+	BMBOUNDFIX(xl, xh, yl, yh);
 
 	for (bx = xl; bx <= xh; bx++)
 		for (by = yl; by <= yh; by++)
@@ -3777,7 +3934,7 @@ void P_MapEnd(void)
 }
 
 // P_FloorzAtPos
-// Returns the floorz of the XYZ position
+// Returns the floorz of the XYZ position // TODO: Need ceilingpos function too
 // Tails 05-26-2003
 fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
 {
@@ -3792,15 +3949,26 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
 
 		for (rover = sec->ffloors; rover; rover = rover->next)
 		{
+			fixed_t topheight, bottomheight;
 			if (!(rover->flags & FF_EXISTS))
 				continue;
 
 			if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE)))
 				continue;
 
+			topheight = *rover->topheight;
+			bottomheight = *rover->bottomheight;
+
+#ifdef ESLOPE
+			if (*rover->t_slope)
+				topheight = P_GetZAt(*rover->t_slope, x, y);
+			if (*rover->b_slope)
+				bottomheight = P_GetZAt(*rover->b_slope, x, y);
+#endif
+
 			if (rover->flags & FF_QUICKSAND)
 			{
-				if (z < *rover->topheight && *rover->bottomheight < thingtop)
+				if (z < topheight && bottomheight < thingtop)
 				{
 					if (floorz < z)
 						floorz = z;
@@ -3808,10 +3976,10 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
 				continue;
 			}
 
-			delta1 = z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-			if (*rover->topheight > floorz && abs(delta1) < abs(delta2))
-				floorz = *rover->topheight;
+			delta1 = z - (bottomheight + ((topheight - bottomheight)/2));
+			delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2));
+			if (topheight > floorz && abs(delta1) < abs(delta2))
+				floorz = topheight;
 		}
 	}
 
diff --git a/src/p_maputl.c b/src/p_maputl.c
index 63972dd0ac5314b1c6959fed48ef51178e886296..8f349a2a99118cffc884b6d4302eab8f2e6d1dd6 100644
--- a/src/p_maputl.c
+++ b/src/p_maputl.c
@@ -17,8 +17,10 @@
 
 #include "p_local.h"
 #include "r_main.h"
+#include "r_data.h"
 #include "p_maputl.h"
 #include "p_polyobj.h"
+#include "p_slopes.h"
 #include "z_zone.h"
 
 //
@@ -321,6 +323,9 @@ fixed_t P_InterceptVector(divline_t *v2, divline_t *v1)
 // OPTIMIZE: keep this precalculated
 //
 fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
+#ifdef ESLOPE
+pslope_t *opentopslope, *openbottomslope;
+#endif
 
 // P_CameraLineOpening
 // P_LineOpening, but for camera
@@ -347,31 +352,56 @@ void P_CameraLineOpening(line_t *linedef)
 	{
 		frontfloor = sectors[front->camsec].floorheight;
 		frontceiling = sectors[front->camsec].ceilingheight;
+#ifdef ESLOPE
+		if (sectors[front->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
+			frontfloor = P_GetZAt(sectors[front->camsec].f_slope, camera.x, camera.y);
+		if (sectors[front->camsec].c_slope)
+			frontceiling = P_GetZAt(sectors[front->camsec].c_slope, camera.x, camera.y);
+#endif
+
 	}
 	else if (front->heightsec >= 0)
 	{
 		frontfloor = sectors[front->heightsec].floorheight;
 		frontceiling = sectors[front->heightsec].ceilingheight;
+#ifdef ESLOPE
+		if (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
+			frontfloor = P_GetZAt(sectors[front->heightsec].f_slope, camera.x, camera.y);
+		if (sectors[front->heightsec].c_slope)
+			frontceiling = P_GetZAt(sectors[front->heightsec].c_slope, camera.x, camera.y);
+#endif
 	}
 	else
 	{
-		frontfloor = front->floorheight;
-		frontceiling = front->ceilingheight;
+		frontfloor = P_CameraGetFloorZ(mapcampointer, front, tmx, tmy, linedef);
+		frontceiling = P_CameraGetCeilingZ(mapcampointer, front, tmx, tmy, linedef);
 	}
 	if (back->camsec >= 0)
 	{
 		backfloor = sectors[back->camsec].floorheight;
 		backceiling = sectors[back->camsec].ceilingheight;
+#ifdef ESLOPE
+		if (sectors[back->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
+			frontfloor = P_GetZAt(sectors[back->camsec].f_slope, camera.x, camera.y);
+		if (sectors[back->camsec].c_slope)
+			frontceiling = P_GetZAt(sectors[back->camsec].c_slope, camera.x, camera.y);
+#endif
 	}
 	else if (back->heightsec >= 0)
 	{
 		backfloor = sectors[back->heightsec].floorheight;
 		backceiling = sectors[back->heightsec].ceilingheight;
+#ifdef ESLOPE
+		if (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope)
+			frontfloor = P_GetZAt(sectors[back->heightsec].f_slope, camera.x, camera.y);
+		if (sectors[back->heightsec].c_slope)
+			frontceiling = P_GetZAt(sectors[back->heightsec].c_slope, camera.x, camera.y);
+#endif
 	}
 	else
 	{
-		backfloor = back->floorheight;
-		backceiling = back->ceilingheight;
+		backfloor = P_CameraGetFloorZ(mapcampointer, back, tmx, tmy, linedef);
+		backceiling = P_CameraGetCeilingZ(mapcampointer, back, tmx, tmy, linedef);
 	}
 
 	{
@@ -413,40 +443,48 @@ void P_CameraLineOpening(line_t *linedef)
 			if (front->ffloors)
 				for (rover = front->ffloors; rover; rover = rover->next)
 				{
+					fixed_t topheight, bottomheight;
 					if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12)
 						continue;
 
-					delta1 = abs(mapcampointer->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-					delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-					if (*rover->bottomheight < lowestceiling && delta1 >= delta2)
-						lowestceiling = *rover->bottomheight;
-					else if (*rover->bottomheight < highestceiling && delta1 >= delta2)
-						highestceiling = *rover->bottomheight;
-
-					if (*rover->topheight > highestfloor && delta1 < delta2)
-						highestfloor = *rover->topheight;
-					else if (*rover->topheight > lowestfloor && delta1 < delta2)
-						lowestfloor = *rover->topheight;
+					topheight = P_CameraGetFOFTopZ(mapcampointer, front, rover, tmx, tmy, linedef);
+					bottomheight = P_CameraGetFOFBottomZ(mapcampointer, front, rover, tmx, tmy, linedef);
+
+					delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2)));
+					delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
+					if (bottomheight < lowestceiling && delta1 >= delta2)
+						lowestceiling = bottomheight;
+					else if (bottomheight < highestceiling && delta1 >= delta2)
+						highestceiling = bottomheight;
+
+					if (topheight > highestfloor && delta1 < delta2)
+						highestfloor = topheight;
+					else if (topheight > lowestfloor && delta1 < delta2)
+						lowestfloor = topheight;
 				}
 
 			// Check for backsectors fake floors
 			if (back->ffloors)
 				for (rover = back->ffloors; rover; rover = rover->next)
 				{
+					fixed_t topheight, bottomheight;
 					if (!(rover->flags & FF_BLOCKOTHERS) || !(rover->flags & FF_RENDERALL) || !(rover->flags & FF_EXISTS) || GETSECSPECIAL(rover->master->frontsector->special, 4) == 12)
 						continue;
 
-					delta1 = abs(mapcampointer->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-					delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-					if (*rover->bottomheight < lowestceiling && delta1 >= delta2)
-						lowestceiling = *rover->bottomheight;
-					else if (*rover->bottomheight < highestceiling && delta1 >= delta2)
-						highestceiling = *rover->bottomheight;
-
-					if (*rover->topheight > highestfloor && delta1 < delta2)
-						highestfloor = *rover->topheight;
-					else if (*rover->topheight > lowestfloor && delta1 < delta2)
-						lowestfloor = *rover->topheight;
+					topheight = P_CameraGetFOFTopZ(mapcampointer, back, rover, tmx, tmy, linedef);
+					bottomheight = P_CameraGetFOFBottomZ(mapcampointer, back, rover, tmx, tmy, linedef);
+
+					delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2)));
+					delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
+					if (bottomheight < lowestceiling && delta1 >= delta2)
+						lowestceiling = bottomheight;
+					else if (bottomheight < highestceiling && delta1 >= delta2)
+						highestceiling = bottomheight;
+
+					if (topheight > highestfloor && delta1 < delta2)
+						highestfloor = topheight;
+					else if (topheight > lowestfloor && delta1 < delta2)
+						lowestfloor = topheight;
 				}
 
 			if (highestceiling < highceiling)
@@ -494,32 +532,91 @@ void P_LineOpening(line_t *linedef)
 	I_Assert(front != NULL);
 	I_Assert(back != NULL);
 
-	if (front->ceilingheight < back->ceilingheight)
-	{
-		opentop = front->ceilingheight;
-		highceiling = back->ceilingheight;
-	}
-	else
-	{
-		opentop = back->ceilingheight;
-		highceiling = front->ceilingheight;
-	}
+	{ // Set open and high/low values here
+		fixed_t frontheight, backheight;
 
-	if (front->floorheight > back->floorheight)
-	{
-		openbottom = front->floorheight;
-		lowfloor = back->floorheight;
-	}
-	else
-	{
-		openbottom = back->floorheight;
-		lowfloor = front->floorheight;
+		frontheight = P_GetCeilingZ(tmthing, front, tmx, tmy, linedef);
+		backheight = P_GetCeilingZ(tmthing, back, tmx, tmy, linedef);
+
+		if (frontheight < backheight)
+		{
+			opentop = frontheight;
+			highceiling = backheight;
+			opentopslope = front->c_slope;
+		}
+		else
+		{
+			opentop = backheight;
+			highceiling = frontheight;
+			opentopslope = back->c_slope;
+		}
+
+		frontheight = P_GetFloorZ(tmthing, front, tmx, tmy, linedef);
+		backheight = P_GetFloorZ(tmthing, back, tmx, tmy, linedef);
+
+		if (frontheight > backheight)
+		{
+			openbottom = frontheight;
+			lowfloor = backheight;
+			openbottomslope = front->f_slope;
+		}
+		else
+		{
+			openbottom = backheight;
+			lowfloor = frontheight;
+			openbottomslope = back->f_slope;
+		}
 	}
 
 	if (tmthing)
 	{
 		fixed_t thingtop = tmthing->z + tmthing->height;
 
+		// Check for collision with front side's midtexture if Effect 4 is set
+		if (linedef->flags & ML_EFFECT4) {
+			side_t *side = &sides[linedef->sidenum[0]];
+			fixed_t textop, texbottom, texheight;
+			fixed_t texmid, delta1, delta2;
+
+			// Get the midtexture's height
+			texheight = textures[texturetranslation[side->midtexture]]->height << FRACBITS;
+
+			// Set texbottom and textop to the Z coordinates of the texture's boundaries
+#ifdef POLYOBJECTS
+			if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) {
+				if (linedef->flags & ML_DONTPEGBOTTOM) {
+					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_DONTPEGBOTTOM) {
+					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;
+
+			delta1 = abs(tmthing->z - texmid);
+			delta2 = abs(thingtop - texmid);
+
+			if (delta1 > delta2) { // Below
+				if (opentop > texbottom)
+					opentop = texbottom;
+			} else { // Above
+				if (openbottom < textop)
+					openbottom = textop;
+			}
+		}
+
 		// Check for fake floors in the sector.
 		if (front->ffloors || back->ffloors
 #ifdef POLYOBJECTS
@@ -534,10 +631,15 @@ void P_LineOpening(line_t *linedef)
 			fixed_t highestfloor = openbottom;
 			fixed_t lowestfloor = lowfloor;
 			fixed_t delta1, delta2;
+#ifdef ESLOPE
+			pslope_t *ceilingslope = opentopslope;
+			pslope_t *floorslope = openbottomslope;
+#endif
 
 			// Check for frontsector's fake floors
 			for (rover = front->ffloors; rover; rover = rover->next)
 			{
+				fixed_t topheight, bottomheight;
 				if (!(rover->flags & FF_EXISTS))
 					continue;
 
@@ -547,29 +649,41 @@ void P_LineOpening(line_t *linedef)
 					|| (rover->flags & FF_BLOCKOTHERS && !tmthing->player)))
 					continue;
 
-				delta1 = abs(tmthing->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-				delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
+				topheight = P_GetFOFTopZ(tmthing, front, rover, tmx, tmy, linedef);
+				bottomheight = P_GetFOFBottomZ(tmthing, front, rover, tmx, tmy, linedef);
+
+				delta1 = abs(tmthing->z - (bottomheight + ((topheight - bottomheight)/2)));
+				delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
 
 				if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF
 				{
-					if (*rover->bottomheight < lowestceiling)
-						lowestceiling = *rover->bottomheight;
-					else if (*rover->bottomheight < highestceiling)
-						highestceiling = *rover->bottomheight;
+					if (bottomheight < lowestceiling) {
+						lowestceiling = bottomheight;
+#ifdef ESLOPE
+						ceilingslope = *rover->b_slope;
+#endif
+					}
+					else if (bottomheight < highestceiling)
+						highestceiling = bottomheight;
 				}
 
 				if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF
 				{
-					if (*rover->topheight > highestfloor)
-						highestfloor = *rover->topheight;
-					else if (*rover->topheight > lowestfloor)
-						lowestfloor = *rover->topheight;
+					if (topheight > highestfloor) {
+						highestfloor = topheight;
+#ifdef ESLOPE
+						floorslope = *rover->t_slope;
+#endif
+					}
+					else if (topheight > lowestfloor)
+						lowestfloor = topheight;
 				}
 			}
 
 			// Check for backsectors fake floors
 			for (rover = back->ffloors; rover; rover = rover->next)
 			{
+				fixed_t topheight, bottomheight;
 				if (!(rover->flags & FF_EXISTS))
 					continue;
 
@@ -579,23 +693,34 @@ void P_LineOpening(line_t *linedef)
 					|| (rover->flags & FF_BLOCKOTHERS && !tmthing->player)))
 					continue;
 
-				delta1 = abs(tmthing->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
-				delta2 = abs(thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2)));
+				topheight = P_GetFOFTopZ(tmthing, back, rover, tmx, tmy, linedef);
+				bottomheight = P_GetFOFBottomZ(tmthing, back, rover, tmx, tmy, linedef);
+
+				delta1 = abs(tmthing->z - (bottomheight + ((topheight - bottomheight)/2)));
+				delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2)));
 
 				if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF
 				{
-					if (*rover->bottomheight < lowestceiling)
-						lowestceiling = *rover->bottomheight;
-					else if (*rover->bottomheight < highestceiling)
-						highestceiling = *rover->bottomheight;
+					if (bottomheight < lowestceiling) {
+						lowestceiling = bottomheight;
+#ifdef ESLOPE
+						ceilingslope = *rover->b_slope;
+#endif
+					}
+					else if (bottomheight < highestceiling)
+						highestceiling = bottomheight;
 				}
 
 				if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF
 				{
-					if (*rover->topheight > highestfloor)
-						highestfloor = *rover->topheight;
-					else if (*rover->topheight > lowestfloor)
-						lowestfloor = *rover->topheight;
+					if (topheight > highestfloor) {
+						highestfloor = topheight;
+#ifdef ESLOPE
+						floorslope = *rover->t_slope;
+#endif
+					}
+					else if (topheight > lowestfloor)
+						lowestfloor = topheight;
 				}
 			}
 
@@ -607,13 +732,21 @@ void P_LineOpening(line_t *linedef)
 
 				delta1 = abs(tmthing->z - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2)));
 				delta2 = abs(thingtop - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2)));
-				if (polysec->floorheight < lowestceiling && delta1 >= delta2)
+				if (polysec->floorheight < lowestceiling && delta1 >= delta2) {
 					lowestceiling = polysec->floorheight;
+#ifdef ESLOPE
+					ceilingslope = NULL;
+#endif
+				}
 				else if (polysec->floorheight < highestceiling && delta1 >= delta2)
 					highestceiling = polysec->floorheight;
 
-				if (polysec->ceilingheight > highestfloor && delta1 < delta2)
+				if (polysec->ceilingheight > highestfloor && delta1 < delta2) {
 					highestfloor = polysec->ceilingheight;
+#ifdef ESLOPE
+					floorslope = NULL;
+#endif
+				}
 				else if (polysec->ceilingheight > lowestfloor && delta1 < delta2)
 					lowestfloor = polysec->ceilingheight;
 			}
@@ -621,11 +754,19 @@ void P_LineOpening(line_t *linedef)
 			if (highestceiling < highceiling)
 				highceiling = highestceiling;
 
-			if (highestfloor > openbottom)
+			if (highestfloor > openbottom) {
 				openbottom = highestfloor;
+#ifdef ESLOPE
+				openbottomslope = floorslope;
+#endif
+			}
 
-			if (lowestceiling < opentop)
+			if (lowestceiling < opentop) {
 				opentop = lowestceiling;
+#ifdef ESLOPE
+				opentopslope = ceilingslope;
+#endif
+			}
 
 			if (lowestfloor > lowfloor)
 				lowfloor = lowestfloor;
@@ -723,6 +864,7 @@ void P_SetThingPosition(mobj_t *thing)
 {                                                      // link into subsector
 	subsector_t *ss;
 	sector_t *oldsec = NULL;
+	fixed_t tfloorz, tceilz;
 
 	I_Assert(thing != NULL);
 	I_Assert(!P_MobjWasRemoved(thing));
@@ -768,8 +910,8 @@ void P_SetThingPosition(mobj_t *thing)
 	if (!(thing->flags & MF_NOBLOCKMAP))
 	{
 		// inert things don't need to be in blockmap
-		const INT32 blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
-		const INT32 blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
+		const INT32 blockx = (unsigned)(thing->x - bmaporgx)>>MAPBLOCKSHIFT;
+		const INT32 blocky = (unsigned)(thing->y - bmaporgy)>>MAPBLOCKSHIFT;
 		if (blockx >= 0 && blockx < bmapwidth
 			&& blocky >= 0 && blocky < bmapheight)
 		{
@@ -792,12 +934,15 @@ void P_SetThingPosition(mobj_t *thing)
 	// sector's floor is the same height.
 	if (thing->player && oldsec != NULL && thing->subsector && oldsec != thing->subsector->sector)
 	{
+		tfloorz = P_GetFloorZ(thing, ss->sector, thing->x, thing->y, NULL);
+		tceilz = P_GetCeilingZ(thing, ss->sector, thing->x, thing->y, NULL);
+
 		if (thing->eflags & MFE_VERTICALFLIP)
 		{
-			if (thing->z + thing->height >= thing->subsector->sector->ceilingheight)
+			if (thing->z + thing->height >= tceilz)
 				thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 		}
-		else if (thing->z <= thing->subsector->sector->floorheight)
+		else if (thing->z <= tfloorz)
 			thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 	}
 }
@@ -1271,10 +1416,10 @@ boolean P_RadiusLinesCheck(fixed_t radius, fixed_t x, fixed_t y,
 	tmbbox[BOXLEFT] = x - radius;
 
 	// check lines
-	xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
-	xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
-	yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
-	yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
+	xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
+	xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
+	yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
+	yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
 
 	for (bx = xl; bx <= xh; bx++)
 		for (by = yl; by <= yh; by++)
diff --git a/src/p_maputl.h b/src/p_maputl.h
index 66f7db2dbaeb30e215e231b0ca256fc450eb164a..7471899cc5bb0bc88e34b7e197621231e99eb289 100644
--- a/src/p_maputl.h
+++ b/src/p_maputl.h
@@ -55,6 +55,9 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y);
 boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y);
 
 extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
+#ifdef ESLOPE
+extern pslope_t *opentopslope, *openbottomslope;
+#endif
 
 void P_LineOpening(line_t *plinedef);
 
diff --git a/src/p_mobj.c b/src/p_mobj.c
index cf71137741e8ab1fff685ce683b09a87571e0a95..40421a8a211101e0022e3b5c12c10f5dbd746752 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -31,6 +31,9 @@
 #include "i_video.h"
 #include "lua_hook.h"
 #include "b_bot.h"
+#ifdef ESLOPE
+#include "p_slopes.h"
+#endif
 
 // protos.
 static CV_PossibleValue_t viewheight_cons_t[] = {{16, "MIN"}, {56, "MAX"}, {0, NULL}};
@@ -142,24 +145,33 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 		{
 		case S_PLAY_STND:
 		case S_PLAY_WAIT:
-		case S_PLAY_GASP:
-			P_SetPlayerMobjState(mobj, S_PLAY_SUPER_STND);
-			return true;
-		case S_PLAY_FALL:
-		case S_PLAY_JUMP:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_STND);
 		case S_PLAY_WALK:
-			P_SetPlayerMobjState(mobj, S_PLAY_SUPER_WALK);
-			return true;
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_WALK);
 		case S_PLAY_RUN:
-			P_SetPlayerMobjState(mobj, S_PLAY_SUPER_RUN);
-			return true;
-		case S_PLAY_EDGE:
-			P_SetPlayerMobjState(mobj, S_PLAY_SUPER_EDGE);
-			return true;
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_RUN);
+		case S_PLAY_PAIN:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_PAIN);
+		case S_PLAY_DEAD:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_DEAD);
+		case S_PLAY_DRWN:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_DRWN);
 		case S_PLAY_SPIN:
 			if (!(player->charflags & SF_SUPERSPIN))
 				return true;
-			break;
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_SPIN);
+		case S_PLAY_GASP:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_GASP);
+		case S_PLAY_JUMP:
+			if (!(player->charflags & SF_SUPERSPIN))
+				return true;
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_JUMP);
+		case S_PLAY_SPRING:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_SPRING);
+		case S_PLAY_FALL:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_FALL);
+		case S_PLAY_EDGE:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_EDGE);
 		default:
 			break;
 		}
@@ -178,30 +190,50 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 	{
 	case S_PLAY_STND:
 	case S_PLAY_WAIT:
-	case S_PLAY_EDGE:
-	case S_PLAY_RIDE:
 	case S_PLAY_SUPER_STND:
-	case S_PLAY_SUPER_EDGE:
 		player->panim = PA_IDLE;
 		break;
+	case S_PLAY_EDGE:
+	case S_PLAY_SUPER_EDGE:
+		player->panim = PA_EDGE;
+		break;
 	case S_PLAY_WALK:
 	case S_PLAY_SUPER_WALK:
+	case S_PLAY_SUPER_FLOAT:
 		player->panim = PA_WALK;
 		break;
 	case S_PLAY_RUN:
 	case S_PLAY_SUPER_RUN:
 		player->panim = PA_RUN;
 		break;
+	case S_PLAY_PAIN:
+	case S_PLAY_SUPER_PAIN:
+	case S_PLAY_SUPER_STUN:
+		player->panim = PA_PAIN;
+		break;
 	case S_PLAY_SPIN:
+	case S_PLAY_DASH:
+	case S_PLAY_JUMP:
+	case S_PLAY_SUPER_SPIN:
+	case S_PLAY_SUPER_JUMP:
 		player->panim = PA_ROLL;
 		break;
+	case S_PLAY_SPRING:
+	case S_PLAY_SUPER_SPRING:
+		player->panim = PA_SPRING;
+		break;
 	case S_PLAY_FALL:
+	case S_PLAY_SUPER_FALL:
 		player->panim = PA_FALL;
 		break;
 	case S_PLAY_FLY:
 	case S_PLAY_GLIDE:
 		player->panim = PA_ABILITY;
 		break;
+	case S_PLAY_RIDE:
+	case S_PLAY_SUPER_RIDE:
+		player->panim = PA_RIDE;
+		break;
 	default:
 		player->panim = PA_ETC;
 		break;
@@ -272,8 +304,115 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 		// Player animations
 		if (st->sprite == SPR_PLAY)
 		{
+			boolean noalt = false;
 			UINT8 spr2 = st->frame & FF_FRAMEMASK;
 			UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
+
+			while (((skin_t *)mobj->skin)->sprites[spr2].numframes <= 0
+				&& spr2 != SPR2_STND)
+			{
+				switch(spr2)
+				{
+				case SPR2_RUN:
+					spr2 = SPR2_WALK;
+					break;
+				case SPR2_DRWN:
+					spr2 = SPR2_DEAD;
+					break;
+				case SPR2_DASH:
+					spr2 = SPR2_SPIN;
+					break;
+				case SPR2_GASP:
+					spr2 = SPR2_SPNG;
+					break;
+				case SPR2_JUMP:
+					spr2 = SPR2_SPIN;
+					break;
+				case SPR2_SPNG: // spring
+					spr2 = SPR2_FALL;
+					break;
+				case SPR2_FALL:
+					spr2 = SPR2_WALK;
+					break;
+				case SPR2_RIDE:
+					spr2 = SPR2_FALL;
+					break;
+
+				case SPR2_FLY:
+					spr2 = SPR2_SPNG;
+					break;
+				case SPR2_TIRE:
+					spr2 = SPR2_FLY;
+					break;
+
+				case SPR2_GLID:
+					spr2 = SPR2_FLY;
+					break;
+				case SPR2_CLMB:
+					spr2 = SPR2_WALK;
+					break;
+				case SPR2_CLNG:
+					spr2 = SPR2_CLMB;
+					break;
+
+				case SPR2_SIGN:
+				case SPR2_LIFE:
+					noalt = true;
+					break;
+
+				// Super sprites fallback to regular sprites
+				case SPR2_SWLK:
+					spr2 = SPR2_WALK;
+					break;
+				case SPR2_SRUN:
+					spr2 = SPR2_RUN;
+					break;
+				case SPR2_SPAN:
+					spr2 = SPR2_PAIN;
+					break;
+				case SPR2_SMSL:
+					spr2 = SPR2_SPAN;
+					break;
+				case SPR2_SDTH:
+					spr2 = SPR2_DEAD;
+					break;
+				case SPR2_SDRN:
+					spr2 = SPR2_DRWN;
+					break;
+				case SPR2_SSPN:
+					spr2 = SPR2_SPIN;
+					break;
+				case SPR2_SGSP:
+					spr2 = SPR2_GASP;
+					break;
+				case SPR2_SJMP:
+					spr2 = SPR2_JUMP;
+					break;
+				case SPR2_SSPG:
+					spr2 = SPR2_SPNG;
+					break;
+				case SPR2_SFAL:
+					spr2 = SPR2_FALL;
+					break;
+				case SPR2_SEDG:
+					spr2 = SPR2_EDGE;
+					break;
+				case SPR2_SRID:
+					spr2 = SPR2_RIDE;
+					break;
+				case SPR2_SFLT:
+					spr2 = SPR2_SWLK;
+					break;
+
+				// Dunno? Just go to standing then.
+				default:
+					spr2 = SPR2_STND;
+					break;
+				}
+				if (noalt)
+					break;
+			}
+
 			if (mobj->sprite != SPR_PLAY)
 			{
 				mobj->sprite = SPR_PLAY;
@@ -281,6 +420,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 			}
 			else if (mobj->sprite2 != spr2)
 				frame = 0;
+
 			mobj->sprite2 = spr2;
 			if (!mobj->skin || frame >= ((skin_t *)mobj->skin)->sprites[spr2].numframes)
 				frame = 0;
@@ -731,6 +871,7 @@ void P_ExplodeMissile(mobj_t *mo)
 // Returns TRUE if mobj is inside a non-solid 3d floor.
 boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover)
 {
+	fixed_t topheight, bottomheight;
 	if (!(rover->flags & FF_EXISTS))
 		return false;
 
@@ -738,15 +879,441 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover)
 		|| ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
 		return false;
 
-	if (mobj->z > *rover->topheight)
+	topheight = *rover->topheight;
+	bottomheight = *rover->bottomheight;
+
+#ifdef ESLOPE
+	if (*rover->t_slope)
+		topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
+	if (*rover->b_slope)
+		bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
+#endif
+
+	if (mobj->z > topheight)
 		return false;
 
-	if (mobj->z + mobj->height < *rover->bottomheight)
+	if (mobj->z + mobj->height < bottomheight)
 		return false;
 
 	return true;
 }
 
+// P_GetFloorZ (and its ceiling counterpart)
+// Gets the floor height (or ceiling height) of the mobj's contact point in sector, assuming object's center if moved to [x, y]
+// If line is supplied, it's a divider line on the sector. Set it to NULL if you're not checking for collision with a line
+// Supply boundsec ONLY when checking for specials! It should be the "in-level" sector, and sector the control sector (if separate).
+// If set, then this function will iterate through boundsec's linedefs to find the highest contact point on the slope. Non-special-checking
+// usage will handle that later.
+static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line, pslope_t *slope, boolean actuallylowest)
+{
+	// Alright, so we're sitting on a line that contains our slope sector, and need to figure out the highest point we're touching...
+	// The solution is simple! Get the line's vertices, and pull each one in along its line until it touches the object's bounding box
+	// (assuming it isn't already inside), then test each point's slope Z and return the higher of the two.
+	vertex_t v1, v2;
+	v1.x = line->v1->x;
+	v1.y = line->v1->y;
+	v2.x = line->v2->x;
+	v2.y = line->v2->y;
+
+	/*CONS_Printf("BEFORE: v1 = %f %f %f\n",
+				FIXED_TO_FLOAT(v1.x),
+				FIXED_TO_FLOAT(v1.y),
+				FIXED_TO_FLOAT(P_GetZAt(slope, v1.x, v1.y))
+				);
+	CONS_Printf("        v2 = %f %f %f\n",
+				FIXED_TO_FLOAT(v2.x),
+				FIXED_TO_FLOAT(v2.y),
+				FIXED_TO_FLOAT(P_GetZAt(slope, v2.x, v2.y))
+				);*/
+
+	if (abs(v1.x-x) > radius) {
+		// v1's x is out of range, so rein it in
+		fixed_t diff = abs(v1.x-x) - radius;
+
+		if (v1.x < x) { // Moving right
+			v1.x += diff;
+			v1.y += FixedMul(diff, FixedDiv(line->dy, line->dx));
+		} else { // Moving left
+			v1.x -= diff;
+			v1.y -= FixedMul(diff, FixedDiv(line->dy, line->dx));
+		}
+	}
+
+	if (abs(v1.y-y) > radius) {
+		// v1's y is out of range, so rein it in
+		fixed_t diff = abs(v1.y-y) - radius;
+
+		if (v1.y < y) { // Moving up
+			v1.y += diff;
+			v1.x += FixedMul(diff, FixedDiv(line->dx, line->dy));
+		} else { // Moving down
+			v1.y -= diff;
+			v1.x -= FixedMul(diff, FixedDiv(line->dx, line->dy));
+		}
+	}
+
+	if (abs(v2.x-x) > radius) {
+		// v1's x is out of range, so rein it in
+		fixed_t diff = abs(v2.x-x) - radius;
+
+		if (v2.x < x) { // Moving right
+			v2.x += diff;
+			v2.y += FixedMul(diff, FixedDiv(line->dy, line->dx));
+		} else { // Moving left
+			v2.x -= diff;
+			v2.y -= FixedMul(diff, FixedDiv(line->dy, line->dx));
+		}
+	}
+
+	if (abs(v2.y-y) > radius) {
+		// v2's y is out of range, so rein it in
+		fixed_t diff = abs(v2.y-y) - radius;
+
+		if (v2.y < y) { // Moving up
+			v2.y += diff;
+			v2.x += FixedMul(diff, FixedDiv(line->dx, line->dy));
+		} else { // Moving down
+			v2.y -= diff;
+			v2.x -= FixedMul(diff, FixedDiv(line->dx, line->dy));
+		}
+	}
+
+	/*CONS_Printf("AFTER:  v1 = %f %f %f\n",
+				FIXED_TO_FLOAT(v1.x),
+				FIXED_TO_FLOAT(v1.y),
+				FIXED_TO_FLOAT(P_GetZAt(slope, v1.x, v1.y))
+				);
+	CONS_Printf("        v2 = %f %f %f\n",
+				FIXED_TO_FLOAT(v2.x),
+				FIXED_TO_FLOAT(v2.y),
+				FIXED_TO_FLOAT(P_GetZAt(slope, v2.x, v2.y))
+				);*/
+
+	// Return the higher of the two points
+	if (actuallylowest)
+		return min(
+			P_GetZAt(slope, v1.x, v1.y),
+			P_GetZAt(slope, v2.x, v2.y)
+		);
+	else
+		return max(
+			P_GetZAt(slope, v1.x, v1.y),
+			P_GetZAt(slope, v2.x, v2.y)
+		);
+}
+
+fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect)
+{
+	I_Assert(mobj != NULL);
+	I_Assert(sector != NULL);
+#ifdef ESLOPE
+	if (sector->f_slope) {
+		fixed_t testx, testy;
+		pslope_t *slope = sector->f_slope;
+
+		// Get the corner of the object that should be the highest on the slope
+		if (slope->d.x < 0)
+			testx = mobj->radius;
+		else
+			testx = -mobj->radius;
+
+		if (slope->d.y < 0)
+			testy = mobj->radius;
+		else
+			testy = -mobj->radius;
+
+		if ((slope->zdelta > 0) ^ !!(lowest)) {
+			testx = -testx;
+			testy = -testy;
+		}
+
+		testx += x;
+		testy += y;
+
+		// If the highest point is in the sector, then we have it easy! Just get the Z at that point
+		if (R_PointInSubsector(testx, testy)->sector == (boundsec ?: sector))
+			return P_GetZAt(slope, testx, testy);
+
+		// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
+		if (perfect) {
+			size_t i;
+			line_t *ld;
+			fixed_t bbox[4];
+			fixed_t finalheight;
+
+			if (lowest)
+				finalheight = INT32_MAX;
+			else
+				finalheight = INT32_MIN;
+
+			bbox[BOXLEFT] = x-mobj->radius;
+			bbox[BOXRIGHT] = x+mobj->radius;
+			bbox[BOXTOP] = y+mobj->radius;
+			bbox[BOXBOTTOM] = y-mobj->radius;
+			for (i = 0; i < boundsec->linecount; i++) {
+				ld = boundsec->lines[i];
+
+				if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
+				|| bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
+					continue;
+
+				if (P_BoxOnLineSide(bbox, ld) != -1)
+					continue;
+
+				if (lowest)
+					finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true));
+				else
+					finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false));
+			}
+
+			return finalheight;
+		}
+
+		// If we're just testing for base sector location (no collision line), just go for the center's spot...
+		// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
+		if (line == NULL)
+			return P_GetZAt(slope, x, y);
+
+		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
+	} else // Well, that makes it easy. Just get the floor height
+#endif
+		return sector->floorheight;
+}
+
+fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect)
+{
+	I_Assert(mobj != NULL);
+	I_Assert(sector != NULL);
+#ifdef ESLOPE
+	if (sector->c_slope) {
+		fixed_t testx, testy;
+		pslope_t *slope = sector->c_slope;
+
+		// Get the corner of the object that should be the highest on the slope
+		if (slope->d.x < 0)
+			testx = mobj->radius;
+		else
+			testx = -mobj->radius;
+
+		if (slope->d.y < 0)
+			testy = mobj->radius;
+		else
+			testy = -mobj->radius;
+
+		if ((slope->zdelta > 0) ^ !!(lowest)) {
+			testx = -testx;
+			testy = -testy;
+		}
+
+		testx += x;
+		testy += y;
+
+		// If the highest point is in the sector, then we have it easy! Just get the Z at that point
+		if (R_PointInSubsector(testx, testy)->sector == (boundsec ?: sector))
+			return P_GetZAt(slope, testx, testy);
+
+		// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
+		if (perfect) {
+			size_t i;
+			line_t *ld;
+			fixed_t bbox[4];
+			fixed_t finalheight;
+
+			if (lowest)
+				finalheight = INT32_MAX;
+			else
+				finalheight = INT32_MIN;
+
+			bbox[BOXLEFT] = x-mobj->radius;
+			bbox[BOXRIGHT] = x+mobj->radius;
+			bbox[BOXTOP] = y+mobj->radius;
+			bbox[BOXBOTTOM] = y-mobj->radius;
+			for (i = 0; i < boundsec->linecount; i++) {
+				ld = boundsec->lines[i];
+
+				if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
+				|| bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
+					continue;
+
+				if (P_BoxOnLineSide(bbox, ld) != -1)
+					continue;
+
+				if (lowest)
+					finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true));
+				else
+					finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false));
+			}
+
+			return finalheight;
+		}
+
+		// If we're just testing for base sector location (no collision line), just go for the center's spot...
+		// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
+		if (line == NULL)
+			return P_GetZAt(slope, x, y);
+
+		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
+	} else // Well, that makes it easy. Just get the ceiling height
+#endif
+		return sector->ceilingheight;
+}
+
+// Now do the same as all above, but for cameras because apparently cameras are special?
+fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect)
+{
+	I_Assert(mobj != NULL);
+	I_Assert(sector != NULL);
+#ifdef ESLOPE
+	if (sector->f_slope) {
+		fixed_t testx, testy;
+		pslope_t *slope = sector->f_slope;
+
+		// Get the corner of the object that should be the highest on the slope
+		if (slope->d.x < 0)
+			testx = mobj->radius;
+		else
+			testx = -mobj->radius;
+
+		if (slope->d.y < 0)
+			testy = mobj->radius;
+		else
+			testy = -mobj->radius;
+
+		if ((slope->zdelta > 0) ^ !!(lowest)) {
+			testx = -testx;
+			testy = -testy;
+		}
+
+		testx += x;
+		testy += y;
+
+		// If the highest point is in the sector, then we have it easy! Just get the Z at that point
+		if (R_PointInSubsector(testx, testy)->sector == (boundsec ?: sector))
+			return P_GetZAt(slope, testx, testy);
+
+		// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
+		if (perfect) {
+			size_t i;
+			line_t *ld;
+			fixed_t bbox[4];
+			fixed_t finalheight;
+
+			if (lowest)
+				finalheight = INT32_MAX;
+			else
+				finalheight = INT32_MIN;
+
+			bbox[BOXLEFT] = x-mobj->radius;
+			bbox[BOXRIGHT] = x+mobj->radius;
+			bbox[BOXTOP] = y+mobj->radius;
+			bbox[BOXBOTTOM] = y-mobj->radius;
+			for (i = 0; i < boundsec->linecount; i++) {
+				ld = boundsec->lines[i];
+
+				if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
+				|| bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
+					continue;
+
+				if (P_BoxOnLineSide(bbox, ld) != -1)
+					continue;
+
+				if (lowest)
+					finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true));
+				else
+					finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false));
+			}
+
+			return finalheight;
+		}
+
+		// If we're just testing for base sector location (no collision line), just go for the center's spot...
+		// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
+		if (line == NULL)
+			return P_GetZAt(slope, x, y);
+
+		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
+	} else // Well, that makes it easy. Just get the floor height
+#endif
+		return sector->floorheight;
+}
+
+fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect)
+{
+	I_Assert(mobj != NULL);
+	I_Assert(sector != NULL);
+#ifdef ESLOPE
+	if (sector->c_slope) {
+		fixed_t testx, testy;
+		pslope_t *slope = sector->c_slope;
+
+		// Get the corner of the object that should be the highest on the slope
+		if (slope->d.x < 0)
+			testx = mobj->radius;
+		else
+			testx = -mobj->radius;
+
+		if (slope->d.y < 0)
+			testy = mobj->radius;
+		else
+			testy = -mobj->radius;
+
+		if ((slope->zdelta > 0) ^ !!(lowest)) {
+			testx = -testx;
+			testy = -testy;
+		}
+
+		testx += x;
+		testy += y;
+
+		// If the highest point is in the sector, then we have it easy! Just get the Z at that point
+		if (R_PointInSubsector(testx, testy)->sector == (boundsec ?: sector))
+			return P_GetZAt(slope, testx, testy);
+
+		// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
+		if (perfect) {
+			size_t i;
+			line_t *ld;
+			fixed_t bbox[4];
+			fixed_t finalheight;
+
+			if (lowest)
+				finalheight = INT32_MAX;
+			else
+				finalheight = INT32_MIN;
+
+			bbox[BOXLEFT] = x-mobj->radius;
+			bbox[BOXRIGHT] = x+mobj->radius;
+			bbox[BOXTOP] = y+mobj->radius;
+			bbox[BOXBOTTOM] = y-mobj->radius;
+			for (i = 0; i < boundsec->linecount; i++) {
+				ld = boundsec->lines[i];
+
+				if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
+				|| bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
+					continue;
+
+				if (P_BoxOnLineSide(bbox, ld) != -1)
+					continue;
+
+				if (lowest)
+					finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true));
+				else
+					finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false));
+			}
+
+			return finalheight;
+		}
+
+		// If we're just testing for base sector location (no collision line), just go for the center's spot...
+		// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
+		if (line == NULL)
+			return P_GetZAt(slope, x, y);
+
+		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
+	} else // Well, that makes it easy. Just get the ceiling height
+#endif
+		return sector->ceilingheight;
+}
 static void P_PlayerFlip(mobj_t *mo)
 {
 	if (!mo->player)
@@ -1013,7 +1580,11 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
 		}
 		else if (abs(player->rmomx) < FixedMul(STOPSPEED, mo->scale)
 		    && abs(player->rmomy) < FixedMul(STOPSPEED, mo->scale)
-		    && (!(player->cmd.forwardmove && !(twodlevel || mo->flags2 & MF2_TWOD)) && !player->cmd.sidemove && !(player->pflags & PF_SPINNING)))
+		    && (!(player->cmd.forwardmove && !(twodlevel || mo->flags2 & MF2_TWOD)) && !player->cmd.sidemove && !(player->pflags & PF_SPINNING))
+#ifdef ESLOPE
+			&& !(player->mo->standingslope && abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)
+#endif
+				)
 		{
 			// if in a walking frame, stop moving
 			if (player->panim == PA_WALK)
@@ -1157,6 +1728,11 @@ void P_XYMovement(mobj_t *mo)
 	fixed_t xmove, ymove;
 	fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls
 	boolean moved;
+#ifdef ESLOPE
+	pslope_t *oldslope = NULL;
+	vector3_t slopemom;
+	fixed_t predictedz = 0;
+#endif
 
 	I_Assert(mo != NULL);
 	I_Assert(!P_MobjWasRemoved(mo));
@@ -1188,6 +1764,30 @@ void P_XYMovement(mobj_t *mo)
 	oldx = mo->x;
 	oldy = mo->y;
 
+#ifdef ESLOPE
+	// adjust various things based on slope
+	if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) {
+		if (!P_IsObjectOnGround(mo)) { // We fell off at some point? Do the twisty thing!
+			P_SlopeLaunch(mo);
+			xmove = mo->momx;
+			ymove = mo->momy;
+		} else { // Still on the ground.
+			slopemom.x = xmove;
+			slopemom.y = ymove;
+			slopemom.z = 0;
+			P_QuantizeMomentumToSlope(&slopemom, mo->standingslope);
+
+			xmove = slopemom.x;
+			ymove = slopemom.y;
+
+			predictedz = mo->z + slopemom.z; // We'll use this later...
+
+			oldslope = mo->standingslope;
+		}
+	} else if (P_IsObjectOnGround(mo) && !mo->momz)
+		predictedz = mo->z;
+#endif
+
 	// Pushables can break some blocks
 	if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE)
 		P_PushableCheckBustables(mo);
@@ -1308,6 +1908,54 @@ void P_XYMovement(mobj_t *mo)
 	if (P_MobjWasRemoved(mo)) // MF_SPECIAL touched a player! O_o;;
 		return;
 
+#ifdef ESLOPE
+	if (moved && oldslope) { // Check to see if we ran off
+
+		if (oldslope != mo->standingslope) { // First, compare different slopes
+			angle_t oldangle, newangle;
+			angle_t moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy);
+
+			oldangle = FixedMul((signed)oldslope->zangle, FINECOSINE((moveangle - oldslope->xydirection) >> ANGLETOFINESHIFT));
+
+			if (mo->standingslope)
+				newangle = FixedMul((signed)mo->standingslope->zangle, FINECOSINE((moveangle - mo->standingslope->xydirection) >> ANGLETOFINESHIFT));
+			else
+				newangle = 0;
+
+			// Now compare the Zs of the different quantizations
+			if (oldangle-newangle > ANG30 && oldangle-newangle < ANGLE_180) { // Allow for a bit of sticking - this value can be adjusted later
+				mo->standingslope = oldslope;
+				P_SlopeLaunch(mo);
+
+				//CONS_Printf("launched off of slope - ");
+			}
+
+			/*CONS_Printf("old angle %f - new angle %f = %f\n",
+						FIXED_TO_FLOAT(AngleFixed(oldangle)),
+						FIXED_TO_FLOAT(AngleFixed(newangle)),
+						FIXED_TO_FLOAT(AngleFixed(oldangle-newangle))
+						);*/
+		} else if (predictedz-mo->z > abs(slopemom.z/2)) { // Now check if we were supposed to stick to this slope
+			//CONS_Printf("%d-%d > %d\n", (predictedz), (mo->z), (slopemom.z/2));
+			P_SlopeLaunch(mo);
+		}
+	} else if (moved && mo->standingslope && predictedz) {
+		angle_t moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy);
+		angle_t newangle = FixedMul((signed)mo->standingslope->zangle, FINECOSINE((moveangle - mo->standingslope->xydirection) >> ANGLETOFINESHIFT));
+
+			/*CONS_Printf("flat to angle %f - predicted z of %f\n",
+						FIXED_TO_FLOAT(AngleFixed(ANGLE_MAX-newangle)),
+						FIXED_TO_FLOAT(predictedz)
+						);*/
+		if (ANGLE_MAX-newangle > ANG30 && newangle > ANGLE_180) {
+			mo->momz = P_MobjFlip(mo)*FRACUNIT/2;
+			mo->z = predictedz + P_MobjFlip(mo);
+			mo->standingslope = NULL;
+			//CONS_Printf("Launched off of flat surface running into downward slope\n");
+		}
+	}
+#endif
+
 	// Check the gravity status.
 	P_CheckGravity(mo, false);
 
@@ -1354,6 +2002,12 @@ void P_XYMovement(mobj_t *mo)
 	if (player && player->homing) // no friction for homing
 		return;
 
+#ifdef ESLOPE
+	if ((mo->type == MT_BIGTUMBLEWEED || mo->type == MT_LITTLETUMBLEWEED)
+			&& (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8)) // Special exception for tumbleweeds on slopes
+		return;
+#endif
+
 	if (((!(mo->eflags & MFE_VERTICALFLIP) && mo->z > mo->floorz) || (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height < mo->ceilingz))
 		&& !(player && player->pflags & PF_SLIDING))
 		return; // no friction when airborne
@@ -1410,6 +2064,7 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp
 {
 	ffloor_t *rover;
 	fixed_t delta1, delta2, thingtop;
+	fixed_t topheight, bottomheight;
 
 	I_Assert(mo != NULL);
 	I_Assert(!P_MobjWasRemoved(mo));
@@ -1421,6 +2076,9 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp
 		if (!(rover->flags & FF_EXISTS))
 			continue;
 
+		topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL);
+		bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL);
+
 		if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should be affected
 			;
 		else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only
@@ -1435,14 +2093,14 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp
 			switch (motype)
 			{
 				case 2: // scenery does things differently for some reason
-					if (mo->z < *rover->topheight && *rover->bottomheight < thingtop)
+					if (mo->z < topheight && bottomheight < thingtop)
 					{
 						mo->floorz = mo->z;
 						continue;
 					}
 					break;
 				default:
-					if (mo->z < *rover->topheight && *rover->bottomheight < thingtop)
+					if (mo->z < topheight && bottomheight < thingtop)
 					{
 						if (mo->floorz < mo->z)
 							mo->floorz = mo->z;
@@ -1451,17 +2109,17 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp
 			}
 		}
 
-		delta1 = mo->z - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-		delta2 = thingtop - (*rover->bottomheight + ((*rover->topheight - *rover->bottomheight)/2));
-		if (*rover->topheight > mo->floorz && abs(delta1) < abs(delta2)
+		delta1 = mo->z - (bottomheight + ((topheight - bottomheight)/2));
+		delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2));
+		if (topheight > mo->floorz && abs(delta1) < abs(delta2)
 			&& !(rover->flags & FF_REVERSEPLATFORM))
 		{
-			mo->floorz = *rover->topheight;
+			mo->floorz = topheight;
 		}
-		if (*rover->bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2)
+		if (bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2)
 			&& !(rover->flags & FF_PLATFORM))
 		{
-			mo->ceilingz = *rover->bottomheight;
+			mo->ceilingz = bottomheight;
 		}
 	}
 }
@@ -1531,10 +2189,10 @@ static void P_RingZMovement(mobj_t *mo)
 		P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector);
 
 	// adjust height
-	if (mo->pmomz && mo->z != mo->floorz)
+	if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
 	{
 		mo->momz += mo->pmomz;
-		mo->pmomz = 0;
+		mo->eflags &= ~MFE_APPLYPMOMZ;
 	}
 	mo->z += mo->momz;
 
@@ -1593,6 +2251,11 @@ static boolean P_ZMovement(mobj_t *mo)
 	I_Assert(mo != NULL);
 	I_Assert(!P_MobjWasRemoved(mo));
 
+#ifdef ESLOPE
+	if (mo->standingslope && !P_IsObjectOnGround(mo))
+			P_SlopeLaunch(mo);
+#endif
+
 	// Intercept the stupid 'fall through 3dfloors' bug
 	if (mo->subsector->sector->ffloors)
 		P_AdjustMobjFloorZ_FFloors(mo, mo->subsector->sector, 0);
@@ -1600,10 +2263,10 @@ static boolean P_ZMovement(mobj_t *mo)
 		P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector);
 
 	// adjust height
-	if (mo->pmomz && mo->z != mo->floorz)
+	if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
 	{
 		mo->momz += mo->pmomz;
-		mo->pmomz = 0;
+		mo->eflags &= ~MFE_APPLYPMOMZ;
 	}
 	mo->z += mo->momz;
 
@@ -1780,14 +2443,31 @@ static boolean P_ZMovement(mobj_t *mo)
 		|| (mo->z + mo->height >= mo->ceilingz && mo->eflags & MFE_VERTICALFLIP))
 	&& !(mo->flags & MF_NOCLIPHEIGHT))
 	{
+		vector3_t mom;
+		mom.x = mo->momx;
+		mom.y = mo->momy;
+		mom.z = mo->momz;
+
 		if (mo->eflags & MFE_VERTICALFLIP)
 			mo->z = mo->ceilingz - mo->height;
 		else
 			mo->z = mo->floorz;
 
+#ifdef ESLOPE
+		P_CheckPosition(mo, mo->x, mo->y); // Sets mo->standingslope correctly
+		if ((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) {
+			mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope;
+
+			// Reverse quantizing might could use its own function later
+			mo->standingslope->zangle = ANGLE_MAX-mo->standingslope->zangle;
+			P_QuantizeMomentumToSlope(&mom, mo->standingslope);
+			mo->standingslope->zangle = ANGLE_MAX-mo->standingslope->zangle;
+		}
+#endif
+
 		// hit the floor
 		if (mo->type == MT_FIREBALL) // special case for the fireball
-			mo->momz = P_MobjFlip(mo)*FixedMul(5*FRACUNIT, mo->scale);
+			mom.z = P_MobjFlip(mo)*FixedMul(5*FRACUNIT, mo->scale);
 		else if (mo->type == MT_SPINFIRE) // elemental shield fire is another exception here
 			;
 		else if (mo->flags & MF_MISSILE)
@@ -1802,12 +2482,12 @@ static boolean P_ZMovement(mobj_t *mo)
 				if (mo->flags & MF_GRENADEBOUNCE)
 				{
 					// Going down? (Or up in reverse gravity?)
-					if (P_MobjFlip(mo)*mo->momz < 0)
+					if (P_MobjFlip(mo)*mom.z < 0)
 					{
 						// If going slower than a fracunit, just stop.
-						if (abs(mo->momz) < FixedMul(FRACUNIT, mo->scale))
+						if (abs(mom.z) < FixedMul(FRACUNIT, mo->scale))
 						{
-							mo->momx = mo->momy = mo->momz = 0;
+							mom.x = mom.y = mom.z = 0;
 
 							// Napalm hack
 							if (mo->type == MT_CYBRAKDEMON_NAPALM_BOMB_LARGE && mo->fuse)
@@ -1815,7 +2495,7 @@ static boolean P_ZMovement(mobj_t *mo)
 						}
 						// Otherwise bounce up at half speed.
 						else
-							mo->momz = -mo->momz/2;
+							mom.z = -mom.z/2;
 						S_StartSound(mo, mo->info->activesound);
 					}
 				}
@@ -1838,14 +2518,14 @@ static boolean P_ZMovement(mobj_t *mo)
 			}
 		}
 
-		if (P_MobjFlip(mo)*mo->momz < 0) // falling
+		if (P_MobjFlip(mo)*mom.z < 0) // falling
 		{
 			if (!tmfloorthing || tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR)
 			|| tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER)
 				mo->eflags |= MFE_JUSTHITFLOOR;
 
 			if (mo->flags2 & MF2_SKULLFLY) // the skull slammed into something
-				mo->momz = -mo->momz;
+				mom.z = -mom.z;
 			else
 			// Flingrings bounce
 			if (mo->type == MT_FLINGRING
@@ -1858,35 +2538,42 @@ static boolean P_ZMovement(mobj_t *mo)
 				|| mo->type == MT_FALLINGROCK)
 			{
 				if (maptol & TOL_NIGHTS)
-					mo->momz = -FixedDiv(mo->momz, 10*FRACUNIT);
+					mom.z = -FixedDiv(mom.z, 10*FRACUNIT);
 				else
-					mo->momz = -FixedMul(mo->momz, FixedDiv(17*FRACUNIT,20*FRACUNIT));
+					mom.z = -FixedMul(mom.z, FixedDiv(17*FRACUNIT,20*FRACUNIT));
 
 				if (mo->type == MT_BIGTUMBLEWEED || mo->type == MT_LITTLETUMBLEWEED)
 				{
-					if (abs(mo->momx) < FixedMul(STOPSPEED, mo->scale)
-						&& abs(mo->momy) < FixedMul(STOPSPEED, mo->scale)
-						&& abs(mo->momz) < FixedMul(STOPSPEED*3, mo->scale))
+					if (abs(mom.x) < FixedMul(STOPSPEED, mo->scale)
+						&& abs(mom.y) < FixedMul(STOPSPEED, mo->scale)
+						&& abs(mom.z) < FixedMul(STOPSPEED*3, mo->scale))
 					{
-						if (!(mo->flags & MF_AMBUSH))
-						{
-							mo->momx = mo->momy = mo->momz = 0;
-							P_SetMobjState(mo, mo->info->spawnstate);
-						}
-						else
+						if (mo->flags & MF_AMBUSH)
 						{
 							// If deafed, give the tumbleweed another random kick if it runs out of steam.
-							mo->momz += P_MobjFlip(mo)*FixedMul(6*FRACUNIT, mo->scale);
+							mom.z += P_MobjFlip(mo)*FixedMul(6*FRACUNIT, mo->scale);
 
 							if (P_Random() & 1)
-								mo->momx += FixedMul(6*FRACUNIT, mo->scale);
+								mom.x += FixedMul(6*FRACUNIT, mo->scale);
 							else
-								mo->momx -= FixedMul(6*FRACUNIT, mo->scale);
+								mom.x -= FixedMul(6*FRACUNIT, mo->scale);
 
 							if (P_Random() & 1)
-								mo->momy += FixedMul(6*FRACUNIT, mo->scale);
+								mom.y += FixedMul(6*FRACUNIT, mo->scale);
 							else
-								mo->momy -= FixedMul(6*FRACUNIT, mo->scale);
+								mom.y -= FixedMul(6*FRACUNIT, mo->scale);
+						}
+#ifdef ESLOPE
+						else if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8)
+						{
+							// Pop the object up a bit to encourage bounciness
+							//mom.z = P_MobjFlip(mo)*mo->scale;
+						}
+#endif
+						else
+						{
+							mom.x = mom.y = mom.z = 0;
+							P_SetMobjState(mo, mo->info->spawnstate);
 						}
 					}
 
@@ -1896,14 +2583,14 @@ static boolean P_ZMovement(mobj_t *mo)
 				}
 				else if (mo->type == MT_FALLINGROCK)
 				{
-					if (P_MobjFlip(mo)*mo->momz > FixedMul(2*FRACUNIT, mo->scale))
+					if (P_MobjFlip(mo)*mom.z > FixedMul(2*FRACUNIT, mo->scale))
 						S_StartSound(mo, mo->info->activesound + P_RandomKey(mo->info->mass));
 
-					mo->momz /= 2; // Rocks not so bouncy
+					mom.z /= 2; // Rocks not so bouncy
 
-					if (abs(mo->momx) < FixedMul(STOPSPEED, mo->scale)
-						&& abs(mo->momy) < FixedMul(STOPSPEED, mo->scale)
-						&& abs(mo->momz) < FixedMul(STOPSPEED*3, mo->scale))
+					if (abs(mom.x) < FixedMul(STOPSPEED, mo->scale)
+						&& abs(mom.y) < FixedMul(STOPSPEED, mo->scale)
+						&& abs(mom.z) < FixedMul(STOPSPEED*3, mo->scale))
 					{
 						P_RemoveMobj(mo);
 						return false;
@@ -1911,20 +2598,30 @@ static boolean P_ZMovement(mobj_t *mo)
 				}
 				else if (mo->type == MT_CANNONBALLDECOR)
 				{
-					mo->momz /= 2;
-					if (abs(mo->momz) < FixedMul(STOPSPEED*3, mo->scale))
-						mo->momz = 0;
+					mom.z /= 2;
+					if (abs(mom.z) < FixedMul(STOPSPEED*3, mo->scale))
+						mom.z = 0;
 				}
 			}
 			else if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR)
 			|| tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER))
-				mo->momz = tmfloorthing->momz;
+				mom.z = tmfloorthing->momz;
 			else if (!tmfloorthing)
-				mo->momz = 0;
+				mom.z = 0;
 		}
 		else if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR)
 		|| tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER))
-			mo->momz = tmfloorthing->momz;
+			mom.z = tmfloorthing->momz;
+
+#ifdef ESLOPE
+		if (mo->standingslope) {
+			P_QuantizeMomentumToSlope(&mom, mo->standingslope);
+		}
+#endif
+
+		mo->momx = mom.x;
+		mo->momy = mom.y;
+		mo->momz = mom.z;
 
 		if (mo->type == MT_STEAM)
 			return true;
@@ -2025,11 +2722,11 @@ static void P_PlayerZMovement(mobj_t *mo)
 	}
 
 	// adjust height
-/*	if (mo->pmomz && mo->z > mo->floorz && !(mo->player->pflags & PF_JUMPED))
+	if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
 	{
 		mo->momz += mo->pmomz;
-		mo->pmomz = 0;
-	}*/
+		mo->eflags &= ~MFE_APPLYPMOMZ;
+	}
 
 	mo->z += mo->momz;
 
@@ -2038,6 +2735,11 @@ static void P_PlayerZMovement(mobj_t *mo)
 	|| mo->player->playerstate == PST_REBORN)
 		return;
 
+#ifdef ESLOPE
+	if (mo->standingslope && !P_IsObjectOnGround(mo))
+			P_SlopeLaunch(mo);
+#endif
+
 	// clip movement
 	if (P_IsObjectOnGround(mo) && !(mo->flags & MF_NOCLIPHEIGHT))
 	{
@@ -2046,7 +2748,7 @@ static void P_PlayerZMovement(mobj_t *mo)
 		else
 			mo->z = mo->floorz;
 
-		if (mo->player && (mo->player->pflags & PF_NIGHTSMODE))
+		if (mo->player->pflags & PF_NIGHTSMODE)
 		{
 			if (mo->player->flyangle < 90 || mo->player->flyangle >= 270)
 				mo->player->flyangle += P_MobjFlip(mo)*90;
@@ -2056,17 +2758,23 @@ static void P_PlayerZMovement(mobj_t *mo)
 			goto nightsdone;
 		}
 		// Get up if you fell.
-		if (mo->state == &states[mo->info->painstate] || mo->state-states == S_PLAY_SUPER_PAIN)
+		if (mo->player->panim == PA_PAIN)
 			P_SetPlayerMobjState(mo, S_PLAY_STND);
 
+#ifdef ESLOPE
+		if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) {
+			// Handle landing on slope during Z movement
+			P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope));
+		}
+#endif
+
 		if (P_MobjFlip(mo)*mo->momz < 0) // falling
 		{
+			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),
-			if (mo->player)
-			{
-				if (P_MobjFlip(mo)*mo->momz < -FixedMul(8*FRACUNIT, mo->scale))
-					mo->player->deltaviewheight = (P_MobjFlip(mo)*mo->momz)>>3; // make sure momz is negative
-			}
+			if (P_MobjFlip(mo)*mo->momz < -FixedMul(8*FRACUNIT, mo->scale))
+				mo->player->deltaviewheight = (P_MobjFlip(mo)*mo->momz)>>3; // make sure momz is negative
 
 			if (!tmfloorthing || tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR)
 				|| tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER) // Spin Attack
@@ -2139,14 +2847,14 @@ static void P_PlayerZMovement(mobj_t *mo)
 
 					// Cut momentum in half when you hit the ground and
 					// aren't pressing any controls.
-					if (!mo->player || (!(mo->player->cmd.forwardmove || mo->player->cmd.sidemove) && !mo->player->cmomx && !mo->player->cmomy && !(mo->player->pflags & PF_SPINNING)))
+					if (!(mo->player->cmd.forwardmove || mo->player->cmd.sidemove) && !mo->player->cmomx && !mo->player->cmomy && !(mo->player->pflags & PF_SPINNING))
 					{
 						mo->momx = mo->momx/2;
 						mo->momy = mo->momy/2;
 					}
 				}
 
-				if (mo->health && mo->player)
+				if (mo->health)
 				{
 					if (mo->player->pflags & PF_GLIDING) // ground gliding
 					{
@@ -2160,7 +2868,7 @@ static void P_PlayerZMovement(mobj_t *mo)
 						{
 							if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale) && mo->player->panim != PA_RUN)
 								P_SetPlayerMobjState(mo, S_PLAY_RUN);
-							else if ((mo->player->rmomx || mo->player->rmomy) && mo->player->panim != PA_WALK)
+							else if ((mo->player->rmomx || mo->player->rmomy) && (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_SUPER_FLOAT))
 								P_SetPlayerMobjState(mo, S_PLAY_WALK);
 							else if (!mo->player->rmomx && !mo->player->rmomy && mo->player->panim != PA_IDLE)
 								P_SetPlayerMobjState(mo, S_PLAY_STND);
@@ -2169,7 +2877,7 @@ static void P_PlayerZMovement(mobj_t *mo)
 						{
 							if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale) && mo->player->panim != PA_RUN)
 								P_SetPlayerMobjState(mo, S_PLAY_RUN);
-							else if ((mo->momx || mo->momy) && mo->player->panim != PA_WALK)
+							else if ((mo->momx || mo->momy) && (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_SUPER_FLOAT))
 								P_SetPlayerMobjState(mo, S_PLAY_WALK);
 							else if (!mo->momx && !mo->momy && mo->player->panim != PA_IDLE)
 								P_SetPlayerMobjState(mo, S_PLAY_STND);
@@ -2192,7 +2900,7 @@ static void P_PlayerZMovement(mobj_t *mo)
 					mo->player->powers[pw_tailsfly] = 0;
 				}
 			}
-			if (mo->player && !(mo->player->pflags & PF_SPINNING))
+			if (!(mo->player->pflags & PF_SPINNING))
 				mo->player->pflags &= ~PF_STARTDASH;
 
 			if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR)
@@ -2235,7 +2943,7 @@ nightsdone:
 		else
 			mo->z = mo->ceilingz - mo->height;
 
-		if (mo->player && (mo->player->pflags & PF_NIGHTSMODE))
+		if (mo->player->pflags & PF_NIGHTSMODE)
 		{
 			if (mo->player->flyangle < 90 || mo->player->flyangle >= 270)
 				mo->player->flyangle -= P_MobjFlip(mo)*90;
@@ -2250,7 +2958,7 @@ nightsdone:
 		{
 			msecnode_t *node;
 
-			if (CheckForMarioBlocks && mo->player && !(netgame && mo->player->spectator)) // Only let the player punch
+			if (CheckForMarioBlocks && !(netgame && mo->player->spectator)) // Only let the player punch
 			{
 				// Search the touching sectors, from side-to-side...
 				for (node = mo->touching_sectorlist; node; node = node->m_snext)
@@ -2278,7 +2986,7 @@ nightsdone:
 			if (mariomode)
 				S_StartSound(mo, sfx_mario1);
 
-			if (!(mo->player && mo->player->climbing))
+			if (!mo->player->climbing)
 				mo->momz = 0;
 		}
 	}
@@ -2293,10 +3001,10 @@ static boolean P_SceneryZMovement(mobj_t *mo)
 		P_AdjustMobjFloorZ_PolyObjs(mo, mo->subsector);
 
 	// adjust height
-	if (mo->pmomz && mo->z != mo->floorz)
+	if (mo->eflags & MFE_APPLYPMOMZ && !P_IsObjectOnGround(mo))
 	{
 		mo->momz += mo->pmomz;
-		mo->pmomz = 0;
+		mo->eflags &= ~MFE_APPLYPMOMZ;
 	}
 	mo->z += mo->momz;
 
@@ -2467,46 +3175,58 @@ void P_MobjCheckWater(mobj_t *mobj)
 	player_t *p = mobj->player; // Will just be null if not a player.
 
 	// Default if no water exists.
-	mobj->watertop = mobj->waterbottom = mobj->subsector->sector->floorheight - 1000*FRACUNIT;
+	mobj->watertop = mobj->waterbottom = mobj->z - 1000*FRACUNIT;
 
 	// Reset water state.
 	mobj->eflags &= ~(MFE_UNDERWATER|MFE_TOUCHWATER|MFE_GOOWATER);
 
 	for (rover = sector->ffloors; rover; rover = rover->next)
 	{
+		fixed_t topheight, bottomheight;
 		if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE)
 		 || (((rover->flags & FF_BLOCKPLAYER) && mobj->player)
 		 || ((rover->flags & FF_BLOCKOTHERS) && !mobj->player)))
 			continue;
 
+		topheight = *rover->topheight;
+		bottomheight = *rover->bottomheight;
+
+#ifdef ESLOPE
+		if (*rover->t_slope)
+			topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
+
+		if (*rover->b_slope)
+			bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
+#endif
+
 		if (mobj->eflags & MFE_VERTICALFLIP)
 		{
-			if (*rover->topheight < (thingtop - FixedMul(mobj->info->height/2, mobj->scale))
-			 || *rover->bottomheight > thingtop)
+			if (topheight < (thingtop - FixedMul(mobj->info->height/2, mobj->scale))
+			 || bottomheight > thingtop)
 				continue;
 		}
 		else
 		{
-			if (*rover->topheight < mobj->z
-			 || *rover->bottomheight > (mobj->z + FixedMul(mobj->info->height/2, mobj->scale)))
+			if (topheight < mobj->z
+			 || bottomheight > (mobj->z + FixedMul(mobj->info->height/2, mobj->scale)))
 				continue;
 		}
 
 		// Set the watertop and waterbottom
-		mobj->watertop = *rover->topheight;
-		mobj->waterbottom = *rover->bottomheight;
+		mobj->watertop = topheight;
+		mobj->waterbottom = bottomheight;
 
 		// Just touching the water?
-		if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - FixedMul(mobj->info->height, mobj->scale) < *rover->bottomheight)
-		 || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + FixedMul(mobj->info->height, mobj->scale) > *rover->topheight))
+		if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - FixedMul(mobj->info->height, mobj->scale) < bottomheight)
+		 || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + FixedMul(mobj->info->height, mobj->scale) > topheight))
 		{
 			mobj->eflags |= MFE_TOUCHWATER;
 			if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY))
 				mobj->eflags |= MFE_GOOWATER;
 		}
 		// Actually in the water?
-		if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - FixedMul(mobj->info->height/2, mobj->scale) > *rover->bottomheight)
-		 || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + FixedMul(mobj->info->height/2, mobj->scale) < *rover->topheight))
+		if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - FixedMul(mobj->info->height/2, mobj->scale) > bottomheight)
+		 || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + FixedMul(mobj->info->height/2, mobj->scale) < topheight))
 		{
 			mobj->eflags |= MFE_UNDERWATER;
 			if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY))
@@ -2564,10 +3284,8 @@ void P_MobjCheckWater(mobj_t *mobj)
 			return;
 
 		if ((mobj->eflags & MFE_GOOWATER || wasingoo)) { // Decide what happens to your momentum when you enter/leave goopy water.
-			if (wasinwater && P_MobjFlip(mobj)*mobj->momz > 0)
-				mobj->momz = FixedMul(mobj->momz, FixedDiv(9*FRACUNIT, 8*FRACUNIT)); // Give the mobj a little out-of-goo boost.
-			else if (P_MobjFlip(mobj)*mobj->momz < 0)
-				mobj->momz = FixedMul(mobj->momz, FixedDiv(2*FRACUNIT, 5*FRACUNIT)); // KILL its momentum.
+			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.
 		}
 		else if (wasinwater && P_MobjFlip(mobj)*mobj->momz > 0)
 			mobj->momz = FixedMul(mobj->momz, FixedDiv(780*FRACUNIT, 457*FRACUNIT)); // Give the mobj a little out-of-water boost.
@@ -2685,7 +3403,7 @@ static void P_SceneryCheckWater(mobj_t *mobj)
 	sector_t *sector;
 
 	// Default if no water exists.
-	mobj->watertop = mobj->waterbottom = mobj->subsector->sector->floorheight - 1000*FRACUNIT;
+	mobj->watertop = mobj->waterbottom = mobj->z - 1000*FRACUNIT;
 
 	// see if we are in water, and set some flags for later
 	sector = mobj->subsector->sector;
@@ -2693,6 +3411,7 @@ static void P_SceneryCheckWater(mobj_t *mobj)
 	if (sector->ffloors)
 	{
 		ffloor_t *rover;
+		fixed_t topheight, bottomheight;
 
 		mobj->eflags &= ~(MFE_UNDERWATER|MFE_TOUCHWATER);
 
@@ -2700,20 +3419,32 @@ static void P_SceneryCheckWater(mobj_t *mobj)
 		{
 			if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKOTHERS)
 				continue;
-			if (*rover->topheight <= mobj->z
-				|| *rover->bottomheight > (mobj->z + FixedMul(mobj->info->height >> 1, mobj->scale)))
+
+			topheight = *rover->topheight;
+			bottomheight = *rover->bottomheight;
+
+#ifdef ESLOPE
+			if (*rover->t_slope)
+				topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
+
+			if (*rover->b_slope)
+				bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y);
+#endif
+
+			if (topheight <= mobj->z
+				|| bottomheight > (mobj->z + FixedMul(mobj->info->height >> 1, mobj->scale)))
 				continue;
 
-			if (mobj->z + FixedMul(mobj->info->height, mobj->scale) > *rover->topheight)
+			if (mobj->z + FixedMul(mobj->info->height, mobj->scale) > topheight)
 				mobj->eflags |= MFE_TOUCHWATER;
 			else
 				mobj->eflags &= ~MFE_TOUCHWATER;
 
 			// Set the watertop and waterbottom
-			mobj->watertop = *rover->topheight;
-			mobj->waterbottom = *rover->bottomheight;
+			mobj->watertop = topheight;
+			mobj->waterbottom = bottomheight;
 
-			if (mobj->z + FixedMul(mobj->info->height >> 1, mobj->scale) < *rover->topheight)
+			if (mobj->z + FixedMul(mobj->info->height >> 1, mobj->scale) < topheight)
 				mobj->eflags |= MFE_UNDERWATER;
 			else
 				mobj->eflags &= ~MFE_UNDERWATER;
@@ -2743,7 +3474,15 @@ static boolean P_CameraCheckHeat(camera_t *thiscam)
 			if (!(rover->flags & FF_EXISTS))
 				continue;
 
-			if (halfheight >= *rover->topheight || halfheight <= *rover->bottomheight)
+			if (halfheight >= (
+#ifdef ESLOPE
+					*rover->t_slope ? P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) :
+#endif
+					*rover->topheight) || halfheight <= (
+#ifdef ESLOPE
+					*rover->b_slope ? P_GetZAt(*rover->b_slope, thiscam->x, thiscam->y) :
+#endif
+					*rover->bottomheight))
 				continue;
 
 			if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1)
@@ -2771,7 +3510,15 @@ static boolean P_CameraCheckWater(camera_t *thiscam)
 			if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKOTHERS)
 				continue;
 
-			if (halfheight >= *rover->topheight || halfheight <= *rover->bottomheight)
+			if (halfheight >= (
+#ifdef ESLOPE
+					*rover->t_slope ? P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) :
+#endif
+					*rover->topheight) || halfheight <= (
+#ifdef ESLOPE
+					*rover->b_slope ? P_GetZAt(*rover->b_slope, thiscam->x, thiscam->y) :
+#endif
+					*rover->bottomheight))
 				continue;
 
 			return true;
@@ -2876,10 +3623,10 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
 	thiscam->floorz = tmfloorz;
 	thiscam->ceilingz = tmceilingz;
 
-	if (thiscam->momz)
+	if (thiscam->momz || player->mo->pmomz)
 	{
 		// adjust height
-		thiscam->z += thiscam->momz;
+		thiscam->z += thiscam->momz + player->mo->pmomz;
 
 		if (!itsatwodlevel && !(player->pflags & PF_NOCLIP))
 		{
@@ -2937,10 +3684,15 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
 	msecnode_t *node;
 
 	I_Assert(mobj != NULL);
+	I_Assert(mobj->player != NULL);
 	I_Assert(!P_MobjWasRemoved(mobj));
 
 	P_MobjCheckWater(mobj);
 
+#ifdef ESLOPE
+	P_ButteredSlope(mobj);
+#endif
+
 	// momentum movement
 	mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN;
 
@@ -2955,7 +3707,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
 		P_CheckPosition(mobj, mobj->x, mobj->y);
 		goto animonly;
 	}
-	else if (mobj->player && (mobj->player->pflags & PF_MACESPIN) && mobj->tracer)
+	else if (mobj->player->pflags & PF_MACESPIN && mobj->tracer)
 	{
 		P_CheckPosition(mobj, mobj->x, mobj->y);
 		goto animonly;
@@ -2974,11 +3726,12 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
 	else
 		P_TryMove(mobj, mobj->x, mobj->y, true);
 
-	if (!(netgame && mobj->player && mobj->player->spectator))
+	if (!(netgame && mobj->player->spectator))
 	{
 		// Crumbling platforms
 		for (node = mobj->touching_sectorlist; node; node = node->m_snext)
 		{
+			fixed_t topheight, bottomheight;
 			ffloor_t *rover;
 
 			for (rover = node->m_sector->ffloors; rover; rover = rover->next)
@@ -2986,8 +3739,11 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
 				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_CRUMBLE))
 					continue;
 
-				if ((*rover->topheight == mobj->z && !(mobj->eflags & MFE_VERTICALFLIP))
-				|| (*rover->bottomheight == mobj->z + mobj->height && mobj->eflags & MFE_VERTICALFLIP)) // You nut.
+				topheight = P_GetSpecialTopZ(mobj, sectors + rover->secnum, node->m_sector);
+				bottomheight = P_GetSpecialBottomZ(mobj, sectors + rover->secnum, node->m_sector);
+
+				if ((topheight == mobj->z && !(mobj->eflags & MFE_VERTICALFLIP))
+				|| (bottomheight == mobj->z + mobj->height && mobj->eflags & MFE_VERTICALFLIP)) // You nut.
 					EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), mobj->player, rover->alpha, !(rover->flags & FF_NORETURN));
 			}
 		}
@@ -3057,18 +3813,14 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
 	}
 	else
 	{
-		if (mobj->player)
+		mobj->player->jumping = 0;
+		mobj->player->pflags &= ~PF_JUMPED;
+		if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly])
 		{
-			mobj->player->jumping = 0;
-			mobj->player->pflags &= ~PF_JUMPED;
-			if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly])
-			{
-				mobj->player->secondjump = 0;
-				mobj->player->powers[pw_tailsfly] = 0;
-				P_SetPlayerMobjState(mobj, S_PLAY_WALK);
-			}
+			mobj->player->secondjump = 0;
+			mobj->player->powers[pw_tailsfly] = 0;
+			P_SetPlayerMobjState(mobj, S_PLAY_WALK);
 		}
-		mobj->pmomz = 0;
 		mobj->eflags &= ~MFE_JUSTHITFLOOR;
 	}
 
@@ -5184,8 +5936,6 @@ static void P_NightsItemChase(mobj_t *thing)
 
 static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
 {
-	fixed_t destx, desty;
-
 	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]
 		|| thing->target->player->powers[pw_invulnerability] > 1)
@@ -5210,26 +5960,6 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
 		return false;
 	}
 
-	if (!splitscreen && rendermode != render_soft)
-	{
-		angle_t viewingangle;
-
-		if (players[displayplayer].awayviewtics)
-			viewingangle = R_PointToAngle2(thing->target->x, thing->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y);
-		else if (!camera.chase && players[displayplayer].mo)
-			viewingangle = R_PointToAngle2(thing->target->x, thing->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y);
-		else
-			viewingangle = R_PointToAngle2(thing->target->x, thing->target->y, camera.x, camera.y);
-
-		destx = thing->target->x + P_ReturnThrustX(thing->target, viewingangle, FixedMul(FRACUNIT, thing->scale));
-		desty = thing->target->y + P_ReturnThrustY(thing->target, viewingangle, FixedMul(FRACUNIT, thing->scale));
-	}
-	else
-	{
-		destx = thing->target->x;
-		desty = thing->target->y;
-	}
-
 	if (shield == SH_FORCE && thing->movecount != (thing->target->player->powers[pw_shield] & 0xFF))
 	{
 		thing->movecount = (thing->target->player->powers[pw_shield] & 0xFF);
@@ -5254,8 +5984,8 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
 
 	P_SetScale(thing, thing->target->scale);
 	P_UnsetThingPosition(thing);
-	thing->x = destx;
-	thing->y = desty;
+	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);
 	else
@@ -5496,6 +6226,8 @@ void P_MobjThinker(mobj_t *mobj)
 
 	mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG);
 
+	tmfloorthing = tmhitthing = NULL;
+
 	// 970 allows ANY mobj to trigger a linedef exec
 	if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8)
 	{
@@ -6543,19 +7275,22 @@ void P_MobjThinker(mobj_t *mobj)
 						if (mobj->spawnpoint->options & MTF_OBJECTFLIP)
 						{
 							z = ss->sector->ceilingheight - mobjinfo[mobj->type].height;
-							if (mobj->spawnpoint->z)
-								z -= mobj->spawnpoint->z << FRACBITS;
+							if (mobj->spawnpoint->options >> ZSHIFT)
+								z -= (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS;
 						}
 						else
 						{
 							z = ss->sector->floorheight;
-							if (mobj->spawnpoint->z)
-								z += mobj->spawnpoint->z << FRACBITS;
+							if (mobj->spawnpoint->options >> ZSHIFT)
+								z += (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS;
 						}
 						flagmo = P_SpawnMobj(x, y, z, mobj->type);
 						flagmo->spawnpoint = mobj->spawnpoint;
 						if (mobj->spawnpoint->options & MTF_OBJECTFLIP)
-							flagmo->spawnpoint->options |= MTF_OBJECTFLIP;
+						{
+							flagmo->eflags |= MFE_VERTICALFLIP;
+							flagmo->flags2 |= MF2_OBJECTFLIP;
+						}
 
 						if (mobj->type == MT_REDFLAG)
 						{
@@ -6689,21 +7424,25 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
 	}
 	else
 	{
-		if (mobj->player)
-		{
-			mobj->player->jumping = 0;
-			mobj->player->pflags &= ~PF_JUMPED;
-			if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly])
-			{
-				mobj->player->secondjump = 0;
-				mobj->player->powers[pw_tailsfly] = 0;
-				P_SetPlayerMobjState(mobj, S_PLAY_WALK);
-			}
-		}
 		mobj->pmomz = 0; // to prevent that weird rocketing gargoyle bug
 		mobj->eflags &= ~MFE_JUSTHITFLOOR;
 	}
 
+#ifdef ESLOPE // Sliding physics for slidey mobjs!
+	if (mobj->type == MT_FLINGRING
+		|| mobj->type == MT_FLINGCOIN
+		|| P_WeaponOrPanel(mobj->type)
+		|| mobj->type == MT_FLINGEMERALD
+		|| mobj->type == MT_BIGTUMBLEWEED
+		|| mobj->type == MT_LITTLETUMBLEWEED
+		|| mobj->type == MT_CANNONBALLDECOR
+		|| mobj->type == MT_FALLINGROCK) {
+		P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly
+		//if (mobj->standingslope) CONS_Printf("slope physics on mobj\n");
+		P_ButteredSlope(mobj);
+	}
+#endif
+
 	if (mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->health
 		&& P_CheckDeathPitCollide(mobj)) // extra pit check in case these didn't have momz
 	{
@@ -6900,17 +7639,6 @@ void P_SceneryThinker(mobj_t *mobj)
 	}
 	else
 	{
-		if (mobj->player)
-		{
-			mobj->player->jumping = 0;
-			mobj->player->pflags &= ~PF_JUMPED;
-			if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly])
-			{
-				mobj->player->secondjump = 0;
-				mobj->player->powers[pw_tailsfly] = 0;
-				P_SetPlayerMobjState(mobj, S_PLAY_WALK);
-			}
-		}
 		mobj->pmomz = 0; // to prevent that weird rocketing gargoyle bug
 		mobj->eflags &= ~MFE_JUSTHITFLOOR;
 	}
@@ -6977,8 +7705,16 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 	// Make sure scale matches destscale immediately when spawned
 	P_SetScale(mobj, mobj->destscale);
 
-	mobj->floorz = mobj->subsector->sector->floorheight;
-	mobj->ceilingz = mobj->subsector->sector->ceilingheight;
+	mobj->floorz =
+#ifdef ESLOPE
+				mobj->subsector->sector->f_slope ? P_GetZAt(mobj->subsector->sector->f_slope, x, y) :
+#endif
+				mobj->subsector->sector->floorheight;
+	mobj->ceilingz =
+#ifdef ESLOPE
+				mobj->subsector->sector->c_slope ? P_GetZAt(mobj->subsector->sector->c_slope, x, y) :
+#endif
+				mobj->subsector->sector->ceilingheight;
 
 	// Tells MobjCheckWater that the water height was not set.
 	mobj->watertop = INT32_MAX;
@@ -8035,7 +8771,11 @@ void P_SpawnMapThing(mapthing_t *mthing)
 			return;
 
 		ss = R_PointInSubsector(mthing->x << FRACBITS, mthing->y << FRACBITS);
-		mthing->z = (INT16)((ss->sector->floorheight>>FRACBITS) + (mthing->options >> ZSHIFT));
+		mthing->z = (INT16)(((
+#ifdef ESLOPE
+								ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, mthing->x << FRACBITS, mthing->y << FRACBITS) :
+#endif
+								ss->sector->floorheight)>>FRACBITS) + (mthing->options >> ZSHIFT));
 
 		if (numhuntemeralds < MAXHUNTEMERALDS)
 			huntemeralds[numhuntemeralds++] = mthing;
@@ -8153,14 +8893,22 @@ void P_SpawnMapThing(mapthing_t *mthing)
 	ss = R_PointInSubsector(x, y);
 
 	if (i == MT_NIGHTSBUMPER)
-		z = ss->sector->floorheight + ((mthing->options >> ZSHIFT) << FRACBITS);
+		z = (
+#ifdef ESLOPE
+			ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) :
+#endif
+			ss->sector->floorheight) + ((mthing->options >> ZSHIFT) << FRACBITS);
 	else if (i == MT_AXIS || i == MT_AXISTRANSFER || i == MT_AXISTRANSFERLINE)
 		z = ONFLOORZ;
 	else if (i == MT_SPECIALSPIKEBALL || P_WeaponOrPanel(i) || i == MT_EMERALDSPAWN || i == MT_EMMY)
 	{
 		if (mthing->options & MTF_OBJECTFLIP)
 		{
-			z = ss->sector->ceilingheight;
+			z = (
+#ifdef ESLOPE
+			ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) :
+#endif
+			ss->sector->ceilingheight);
 
 			if (mthing->options & MTF_AMBUSH) // Special flag for rings
 				z -= 24*FRACUNIT;
@@ -8171,7 +8919,11 @@ void P_SpawnMapThing(mapthing_t *mthing)
 		}
 		else
 		{
-			z = ss->sector->floorheight;
+			z = (
+#ifdef ESLOPE
+			ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) :
+#endif
+			ss->sector->floorheight);
 
 			if (mthing->options & MTF_AMBUSH) // Special flag for rings
 				z += 24*FRACUNIT;
@@ -8191,9 +8943,17 @@ void P_SpawnMapThing(mapthing_t *mthing)
 
 		// base positions
 		if (flip)
-			z = ss->sector->ceilingheight - mobjinfo[i].height;
+			z = (
+#ifdef ESLOPE
+			ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) :
+#endif
+			ss->sector->ceilingheight) - mobjinfo[i].height;
 		else
-			z = ss->sector->floorheight;
+			z = (
+#ifdef ESLOPE
+			ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) :
+#endif
+			ss->sector->floorheight);
 
 		// offsetting
 		if (mthing->options >> ZSHIFT)
@@ -8707,7 +9467,11 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
 		// Screw these damn hoops, I need this thinker.
 		//hoopcenter->flags |= MF_NOTHINK;
 
-		z += sec->floorheight;
+		z +=
+#ifdef ESLOPE
+			sec->f_slope ? P_GetZAt(sec->f_slope, x, y) :
+#endif
+			sec->floorheight;
 
 		hoopcenter->z = z - hoopcenter->height/2;
 
@@ -8840,7 +9604,11 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
 		hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER);
 		hoopcenter->spawnpoint = mthing;
 
-		z += sec->floorheight;
+		z +=
+#ifdef ESLOPE
+			sec->f_slope ? P_GetZAt(sec->f_slope, x, y) :
+#endif
+			sec->floorheight;
 		hoopcenter->z = z - hoopcenter->height/2;
 
 		P_UnsetThingPosition(hoopcenter);
@@ -8952,7 +9720,11 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
 	// Wing logo item.
 	else if (mthing->type == mobjinfo[MT_NIGHTSWING].doomednum)
 	{
-		z = sec->floorheight;
+		z =
+#ifdef ESLOPE
+			sec->f_slope ? P_GetZAt(sec->f_slope, x, y) :
+#endif
+			sec->floorheight;
 		if (mthing->options >> ZSHIFT)
 			z += ((mthing->options >> ZSHIFT) << FRACBITS);
 
@@ -9004,13 +9776,21 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
 		// Set proper height
 		if (mthing->options & MTF_OBJECTFLIP)
 		{
-			z = sec->ceilingheight - mobjinfo[ringthing].height;
+			z = (
+#ifdef ESLOPE
+			sec->c_slope ? P_GetZAt(sec->c_slope, x, y) :
+#endif
+			sec->ceilingheight) - mobjinfo[ringthing].height;
 			if (mthing->options >> ZSHIFT)
 				z -= ((mthing->options >> ZSHIFT) << FRACBITS);
 		}
 		else
 		{
-			z = sec->floorheight;
+			z =
+#ifdef ESLOPE
+			sec->f_slope ? P_GetZAt(sec->f_slope, x, y) :
+#endif
+			sec->floorheight;
 			if (mthing->options >> ZSHIFT)
 				z += ((mthing->options >> ZSHIFT) << FRACBITS);
 		}
@@ -9064,13 +9844,21 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
 		{
 			if (mthing->options & MTF_OBJECTFLIP)
 			{
-				z = sec->ceilingheight - mobjinfo[ringthing].height - dist*r;
+				z = (
+#ifdef ESLOPE
+					sec->c_slope ? P_GetZAt(sec->c_slope, x, y) :
+#endif
+					sec->ceilingheight) - mobjinfo[ringthing].height - dist*r;
 				if (mthing->options >> ZSHIFT)
 					z -= ((mthing->options >> ZSHIFT) << FRACBITS);
 			}
 			else
 			{
-				z = sec->floorheight + dist*r;
+				z = (
+#ifdef ESLOPE
+					sec->f_slope ? P_GetZAt(sec->f_slope, x, y) :
+#endif
+					sec->floorheight) + dist*r;
 				if (mthing->options >> ZSHIFT)
 					z += ((mthing->options >> ZSHIFT) << FRACBITS);
 			}
@@ -9091,7 +9879,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
 	// Diagonal rings (handles both types)
 	else if (mthing->type == 602 || mthing->type == 603) // Diagonal rings (5)
 	{
-		angle_t angle = ANGLE_45 * (mthing->angle/45);
+		angle_t angle = FixedAngle(mthing->angle*FRACUNIT);
 		mobjtype_t ringthing = MT_RING;
 		INT32 iterations = 5;
 		if (mthing->type == 603)
@@ -9116,13 +9904,21 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
 
 			if (mthing->options & MTF_OBJECTFLIP)
 			{
-				z = sec->ceilingheight - mobjinfo[ringthing].height - 64*FRACUNIT*r;
+				z = (
+#ifdef ESLOPE
+					sec->c_slope ? P_GetZAt(sec->c_slope, x, y) :
+#endif
+					sec->ceilingheight) - mobjinfo[ringthing].height - 64*FRACUNIT*r;
 				if (mthing->options >> ZSHIFT)
 					z -= ((mthing->options >> ZSHIFT) << FRACBITS);
 			}
 			else
 			{
-				z = sec->floorheight + 64*FRACUNIT*r;
+				z = (
+#ifdef ESLOPE
+					sec->f_slope ? P_GetZAt(sec->f_slope, x, y) :
+#endif
+					sec->floorheight) + 64*FRACUNIT*r;
 				if (mthing->options >> ZSHIFT)
 					z += ((mthing->options >> ZSHIFT) << FRACBITS);
 			}
@@ -9153,7 +9949,11 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
 			size = 192*FRACUNIT;
 		}
 
-		z = sec->floorheight;
+		z =
+#ifdef ESLOPE
+			sec->f_slope ? P_GetZAt(sec->f_slope, x, y) :
+#endif
+			sec->floorheight;
 		if (mthing->options >> ZSHIFT)
 			z += ((mthing->options >> ZSHIFT) << FRACBITS);
 
diff --git a/src/p_mobj.h b/src/p_mobj.h
index 3cec49fad5a98a2d1cb7d3fb9a17ccd95d6152df..9df696b17eee6a038a7f771656d83c274ca39c85 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -235,6 +235,8 @@ typedef enum
 	MFE_PUSHED            = 1<<7,
 	// Mobj was already sprung this tic
 	MFE_SPRUNG            = 1<<8,
+	// Platform movement
+	MFE_APPLYPMOMZ        = 1<<9,
 	// free: to and including 1<<15
 } mobjeflag_t;
 
@@ -356,6 +358,10 @@ typedef struct mobj_s
 	INT32 cusval;
 	INT32 cvmem;
 
+#ifdef ESLOPE
+	struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
+#endif
+
 	// WARNING: New fields must be added separately to savegame and Lua.
 } mobj_t;
 
diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 102c03b7a38ab2d15be238f9ce2fb07463f274de..41616e587f33b4e9961187b353cf27a72e5abd28 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -442,6 +442,8 @@ newseg:
 	// seg's ending vertex.
 	for (i = 0; i < numsegs; ++i)
 	{
+		if (segs[i].side != 0) // needs to be frontfacing
+			continue;
 		if (segs[i].v1->x == seg->v2->x && segs[i].v1->y == seg->v2->y)
 		{
 			// Make sure you didn't already add this seg...
@@ -610,14 +612,17 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
 		INT32 poflags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES;
 		INT32 parentID = 0, potrans = 0;
 
+		if (seg->side != 0) // needs to be frontfacing
+			continue;
+
 		if (seg->linedef->special != POLYOBJ_START_LINE)
 			continue;
-		
+
 		if (seg->linedef->tag != po->id)
 			continue;
 
 		Polyobj_GetInfo(po->id, &poflags, &parentID, &potrans); // apply extra settings if they exist!
-		
+
 		// save original flags and translucency to reference later for netgames!
 		po->spawnflags = po->flags = poflags;
 		po->spawntrans = po->translucency = potrans;
@@ -657,6 +662,14 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id)
 		// TODO: sound sequence is in args[3]
 	}*/
 
+	// make sure array isn't empty
+	// since Polyobj_findExplicit is disabled currently, we have to do things here instead now!
+	if (po->segCount == 0)
+	{
+		po->isBad = true;
+		CONS_Debug(DBG_POLYOBJ, "Polyobject %d is empty\n", po->id);
+		return;
+	}
 
 	// set the polyobject's spawn spot
 	po->spawnSpot.x = spawnSpot->x;
@@ -848,10 +861,10 @@ static void Polyobj_linkToBlockmap(polyobj_t *po)
 		M_AddToBox(blockbox, po->vertices[i]->x, po->vertices[i]->y);
 
 	// adjust bounding box relative to blockmap
-	blockbox[BOXRIGHT]  = (blockbox[BOXRIGHT]  - bmaporgx) >> MAPBLOCKSHIFT;
-	blockbox[BOXLEFT]   = (blockbox[BOXLEFT]   - bmaporgx) >> MAPBLOCKSHIFT;
-	blockbox[BOXTOP]    = (blockbox[BOXTOP]    - bmaporgy) >> MAPBLOCKSHIFT;
-	blockbox[BOXBOTTOM] = (blockbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT;
+	blockbox[BOXRIGHT]  = (unsigned)(blockbox[BOXRIGHT]  - bmaporgx) >> MAPBLOCKSHIFT;
+	blockbox[BOXLEFT]   = (unsigned)(blockbox[BOXLEFT]   - bmaporgx) >> MAPBLOCKSHIFT;
+	blockbox[BOXTOP]    = (unsigned)(blockbox[BOXTOP]    - bmaporgy) >> MAPBLOCKSHIFT;
+	blockbox[BOXBOTTOM] = (unsigned)(blockbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT;
 
 	// link polyobject to every block its bounding box intersects
 	for (y = blockbox[BOXBOTTOM]; y <= blockbox[BOXTOP]; ++y)
@@ -1040,9 +1053,10 @@ static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy)
 
 				mo->lastlook = pomovecount;
 
-				// always push players even if not solid
-				if (!((mo->flags & MF_SOLID) || mo->player))
+				// Don't scroll objects that aren't affected by gravity
+				if (mo->flags & MF_NOGRAVITY)
 					continue;
+				// (The above check used to only move MF_SOLID objects, but that's inconsistent with conveyor behavior. -Red)
 
 				if (mo->flags & MF_NOCLIP)
 					continue;
@@ -1078,10 +1092,10 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
 		return hitflags;
 
 	// adjust linedef bounding box to blockmap, extend by MAXRADIUS
-	linebox[BOXLEFT]   = (line->bbox[BOXLEFT]   - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT;
-	linebox[BOXRIGHT]  = (line->bbox[BOXRIGHT]  - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT;
-	linebox[BOXBOTTOM] = (line->bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT;
-	linebox[BOXTOP]    = (line->bbox[BOXTOP]    - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT;
+	linebox[BOXLEFT]   = (unsigned)(line->bbox[BOXLEFT]   - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT;
+	linebox[BOXRIGHT]  = (unsigned)(line->bbox[BOXRIGHT]  - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT;
+	linebox[BOXBOTTOM] = (unsigned)(line->bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT;
+	linebox[BOXTOP]    = (unsigned)(line->bbox[BOXTOP]    - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT;
 
 	// check all mobj blockmap cells the line contacts
 	for (y = linebox[BOXBOTTOM]; y <= linebox[BOXTOP]; ++y)
@@ -1094,9 +1108,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
 
 				for (; mo; mo = mo->bnext)
 				{
-					// always push players even if not solid
-					if (!((mo->flags & MF_SOLID) || mo->player))
+
+					// Don't scroll objects that aren't affected by gravity
+					if (mo->flags & MF_NOGRAVITY)
 						continue;
+					// (The above check used to only move MF_SOLID objects, but that's inconsistent with conveyor behavior. -Red)
 
 					if (mo->flags & MF_NOCLIP)
 						continue;
@@ -1256,6 +1272,7 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
 {
 	static INT32 pomovecount = 10000;
 	INT32 x, y;
+	angle_t deltafine = delta >> ANGLETOFINESHIFT;
 
 	pomovecount++;
 
@@ -1280,9 +1297,10 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
 
 				mo->lastlook = pomovecount;
 
-				// always push players even if not solid
-				if (!((mo->flags & MF_SOLID) || mo->player))
+				// Don't scroll objects that aren't affected by gravity
+				if (mo->flags & MF_NOGRAVITY)
 					continue;
+				// (The above check used to only move MF_SOLID objects, but that's inconsistent with conveyor behavior. -Red)
 
 				if (mo->flags & MF_NOCLIP)
 					continue;
@@ -1297,21 +1315,28 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta,
 					continue;
 
 				{
-					fixed_t newxoff, newyoff;
-					angle_t angletoobj = R_PointToAngle2(origin.x, origin.y, mo->x, mo->y);
-					fixed_t disttoobj = R_PointToDist2(origin.x, origin.y, mo->x, mo->y);
+					fixed_t oldxoff, oldyoff, newxoff, newyoff;
+					fixed_t c, s;
+
+					c = FINECOSINE(deltafine);
+					s = FINESINE(deltafine);
+
+					oldxoff = mo->x-origin.x;
+					oldyoff = mo->y-origin.y;
 
 					if (mo->player) // Hack to fix players sliding off of spinning polys -Red
 					{
-						disttoobj = FixedMul(disttoobj, 0xfe40);
+						fixed_t temp;
+
+						temp = FixedMul(oldxoff, c)-FixedMul(oldyoff, s);
+						oldyoff = FixedMul(oldyoff, c)+FixedMul(oldxoff, s);
+						oldxoff = temp;
 					}
 
-					angletoobj += delta;
-					angletoobj >>= ANGLETOFINESHIFT;
-					newxoff = FixedMul(FINECOSINE(angletoobj), disttoobj);
-					newyoff = FixedMul(FINESINE(angletoobj), disttoobj);
+					newxoff = FixedMul(oldxoff, c)-FixedMul(oldyoff, s);
+					newyoff = FixedMul(oldyoff, c)+FixedMul(oldxoff, s);
 
-					Polyobj_slideThing(mo, origin.x+newxoff-mo->x, origin.y+newyoff-mo->y);
+					Polyobj_slideThing(mo, newxoff-oldxoff, newyoff-oldyoff);
 
 					if (turnthings == 2 || (turnthings == 1 && !mo->player)) {
 						mo->angle += delta;
@@ -2488,6 +2513,10 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
 		return 0;
 	}
 
+	// Hotfix to not crash on single-waypoint sequences -Red
+	if (!last)
+		last = first;
+
 	// Set diffx, diffy, diffz
 	// Put these at 0 for now...might not be needed after all.
 	th->diffx = 0;//first->x - po->centerPt.x;
diff --git a/src/p_polyobj.h b/src/p_polyobj.h
index b42f8b98b77641a2c55b7efedbcb982626b0f542..cfcb3b99cf053063e7071d66d8e382cbe911619c 100644
--- a/src/p_polyobj.h
+++ b/src/p_polyobj.h
@@ -100,6 +100,8 @@ typedef struct polyobj_s
 	UINT8 isBad;         // a bad polyobject: should not be rendered/manipulated
 	INT32 translucency; // index to translucency tables
 
+	struct visplane_s *visplane; // polyobject's visplane, for ease of putting into the list later
+
 	// these are saved for netgames, so do not let Lua touch these!
 	INT32 spawnflags; // Flags the polyobject originally spawned with
 	INT32 spawntrans; // Translucency the polyobject originally spawned with
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 45cc5bad355ad5f3fbbe3d926288164d5171b3ab..f329ab75804c8f51015d363befcf69a007ee54b6 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -30,6 +30,9 @@
 #include "r_sky.h"
 #include "p_polyobj.h"
 #include "lua_script.h"
+#ifdef ESLOPE
+#include "p_slopes.h"
+#endif
 
 savedata_t savedata;
 UINT8 *save_p;
@@ -633,7 +636,7 @@ static void P_NetArchiveWorld(void)
 		if (li->special != SHORT(mld->special))
 			diff |= LD_SPECIAL;
 
-		if (mld->special == 321 || mld->special == 322) // only reason li->callcount would be non-zero is if either of these are involved
+		if (SHORT(mld->special) == 321 || SHORT(mld->special) == 322) // only reason li->callcount would be non-zero is if either of these are involved
 			diff |= LD_CLLCOUNT;
 
 		if (li->sidenum[0] != 0xffff)
@@ -921,7 +924,8 @@ typedef enum
 	MD2_EXTVAL1     = 1<<5,
 	MD2_EXTVAL2     = 1<<6,
 	MD2_HNEXT       = 1<<7,
-	MD2_HPREV       = 1<<8
+	MD2_HPREV       = 1<<8,
+	MD2_SLOPE       = 1<<9
 } mobj_diff2_t;
 
 typedef enum
@@ -1052,6 +1056,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 		diff |= MD_TICS;
 	if (mobj->sprite != mobj->state->sprite)
 		diff |= MD_SPRITE;
+	if (mobj->sprite == SPR_PLAY && mobj->sprite2 != 0)
+		diff |= MD_SPRITE;
 	if (mobj->frame != mobj->state->frame)
 		diff |= MD_FRAME;
 	if (mobj->eflags)
@@ -1109,6 +1115,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 		diff2 |= MD2_HNEXT;
 	if (mobj->hprev)
 		diff2 |= MD2_HPREV;
+	if (mobj->standingslope)
+		diff2 |= MD2_SLOPE;
 	if (diff2 != 0)
 		diff |= MD_MORE;
 
@@ -1224,6 +1232,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 		WRITEUINT32(save_p, mobj->hnext->mobjnum);
 	if (diff2 & MD2_HPREV)
 		WRITEUINT32(save_p, mobj->hprev->mobjnum);
+	if (diff2 & MD2_SLOPE)
+		WRITEUINT16(save_p, mobj->standingslope->id);
 
 	WRITEUINT32(save_p, mobj->mobjnum);
 }
@@ -2077,6 +2087,9 @@ static void LoadMobjThinker(actionf_p1 thinker)
 		mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p);
 	if (diff2 & MD2_HPREV)
 		mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p);
+	if (diff2 & MD2_SLOPE)
+		mobj->standingslope = P_SlopeById(READUINT16(save_p));
+
 
 	if (diff & MD_REDFLAG)
 	{
diff --git a/src/p_setup.c b/src/p_setup.c
index f2b0c49d84c3a1222308e130a539eff55a8cd670..3491669c7d9b1ab9ac7f39a9648eabf11f166fdc 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -72,6 +72,10 @@
 #include "hardware/hw_light.h"
 #endif
 
+#ifdef ESLOPE
+#include "p_slopes.h"
+#endif
+
 //
 // Map MD5, calculated on level load.
 // Sent to clients in PT_SERVERINFO.
@@ -846,7 +850,7 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum)
 //
 // P_LoadThings
 //
-static void P_LoadThings(lumpnum_t lumpnum)
+static void P_PrepareThings(lumpnum_t lumpnum)
 {
 	size_t i;
 	mapthing_t *mt;
@@ -884,13 +888,27 @@ static void P_LoadThings(lumpnum_t lumpnum)
 	}
 	Z_Free(datastart);
 
+}
+
+static void P_LoadThings(void)
+{
+	size_t i;
+	mapthing_t *mt;
+
+	// Loading the things lump itself into memory is now handled in P_PrepareThings, above
+
 	mt = mapthings;
 	numhuntemeralds = 0;
 	for (i = 0; i < nummapthings; i++, mt++)
 	{
+		sector_t *mtsector = R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector;
+
 		// Z for objects
-		mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)
-			->sector->floorheight>>FRACBITS);
+		mt->z = (INT16)(
+#ifdef ESLOPE
+				mtsector->f_slope ? P_GetZAt(mtsector->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) :
+#endif
+				mtsector->floorheight)>>FRACBITS;
 
 		if (mt->type == 1700 // MT_AXIS
 			|| mt->type == 1701 // MT_AXISTRANSFER
@@ -2114,7 +2132,8 @@ void P_LoadThingsOnly(void)
 
 	P_LevelInitStuff();
 
-	P_LoadThings(lastloadedmaplumpnum + ML_THINGS);
+	P_PrepareThings(lastloadedmaplumpnum + ML_THINGS);
+	P_LoadThings();
 
 	P_SpawnSecretItems(true);
 }
@@ -2531,7 +2550,13 @@ boolean P_SetupLevel(boolean skipprecip)
 
 	P_MapStart();
 
-	P_LoadThings(lastloadedmaplumpnum + ML_THINGS);
+	P_PrepareThings(lastloadedmaplumpnum + ML_THINGS);
+
+#ifdef ESLOPE
+	P_ResetDynamicSlopes();
+#endif
+
+	P_LoadThings();
 
 	P_SpawnSecretItems(loademblems);
 
diff --git a/src/p_slopes.c b/src/p_slopes.c
new file mode 100644
index 0000000000000000000000000000000000000000..2d55cf19451f25458f61fa5c01c9608e7f13e3b0
--- /dev/null
+++ b/src/p_slopes.c
@@ -0,0 +1,1139 @@
+// Emacs style mode select   -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2004 Stephen McGranahan
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+//--------------------------------------------------------------------------
+//
+// DESCRIPTION:
+//      Slopes
+//      SoM created 05/10/09
+//      ZDoom + Eternity Engine Slopes, ported and enhanced by Kalaron
+//
+//-----------------------------------------------------------------------------
+
+
+#include "doomdef.h"
+#include "r_defs.h"
+#include "r_state.h"
+#include "m_bbox.h"
+#include "z_zone.h"
+#include "p_local.h"
+#include "p_spec.h"
+#include "p_slopes.h"
+#include "p_setup.h"
+#include "r_main.h"
+#include "p_maputl.h"
+#include "w_wad.h"
+
+#ifdef ESLOPE
+
+static pslope_t *slopelist = NULL;
+static UINT16 slopecount = 0;
+
+// Calculate line normal
+static void P_CalculateSlopeNormal(pslope_t *slope) {
+	slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT);
+	slope->normal.x = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x);
+	slope->normal.y = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y);
+}
+
+// With a vertex slope that has its vertices set, configure relevant slope info
+static void P_ReconfigureVertexSlope(pslope_t *slope)
+{
+	vector3_t vec1, vec2;
+
+	// Set slope normal
+	vec1.x = (slope->vertices[1]->x - slope->vertices[0]->x) << FRACBITS;
+	vec1.y = (slope->vertices[1]->y - slope->vertices[0]->y) << FRACBITS;
+	vec1.z = (slope->vertices[1]->z - slope->vertices[0]->z) << FRACBITS;
+
+	vec2.x = (slope->vertices[2]->x - slope->vertices[0]->x) << FRACBITS;
+	vec2.y = (slope->vertices[2]->y - slope->vertices[0]->y) << FRACBITS;
+	vec2.z = (slope->vertices[2]->z - slope->vertices[0]->z) << FRACBITS;
+
+	// ugggggggh fixed-point maaaaaaath
+	slope->extent = max(
+		max(max(abs(vec1.x), abs(vec1.y)), abs(vec1.z)),
+		max(max(abs(vec2.x), abs(vec2.y)), abs(vec2.z))
+	) >> (FRACBITS+5);
+	vec1.x /= slope->extent;
+	vec1.y /= slope->extent;
+	vec1.z /= slope->extent;
+	vec2.x /= slope->extent;
+	vec2.y /= slope->extent;
+	vec2.z /= slope->extent;
+
+	FV3_Cross(&vec1, &vec2, &slope->normal);
+
+	slope->extent = R_PointToDist2(0, 0, R_PointToDist2(0, 0, slope->normal.x, slope->normal.y), slope->normal.z);
+	if (slope->normal.z < 0)
+		slope->extent = -slope->extent;
+
+	slope->normal.x = FixedDiv(slope->normal.x, slope->extent);
+	slope->normal.y = FixedDiv(slope->normal.y, slope->extent);
+	slope->normal.z = FixedDiv(slope->normal.z, slope->extent);
+
+	// Set origin
+	slope->o.x = slope->vertices[0]->x << FRACBITS;
+	slope->o.y = slope->vertices[0]->y << FRACBITS;
+	slope->o.z = slope->vertices[0]->z << FRACBITS;
+
+	if (slope->normal.x == 0 && slope->normal.y == 0) { // Set some defaults for a non-sloped "slope"
+		slope->zangle = slope->xydirection = 0;
+		slope->zdelta = slope->d.x = slope->d.y = 0;
+	} else {
+		// Get direction vector
+		slope->extent = R_PointToDist2(0, 0, slope->normal.x, slope->normal.y);
+		slope->d.x = -FixedDiv(slope->normal.x, slope->extent);
+		slope->d.y = -FixedDiv(slope->normal.y, slope->extent);
+
+		// Z delta
+		slope->zdelta = FixedDiv(slope->extent, slope->normal.z);
+
+		// Get angles
+		slope->xydirection = R_PointToAngle2(0, 0, slope->d.x, slope->d.y)+ANGLE_180;
+		slope->zangle = -R_PointToAngle2(0, 0, FRACUNIT, slope->zdelta);
+	}
+}
+
+// Recalculate dynamic slopes
+void P_RunDynamicSlopes(void) {
+	pslope_t *slope;
+
+	for (slope = slopelist; slope; slope = slope->next) {
+		fixed_t zdelta;
+
+		if (slope->flags & SL_NODYNAMIC)
+			continue;
+
+		switch(slope->refpos) {
+		case 1: // front floor
+			zdelta = slope->sourceline->backsector->floorheight - slope->sourceline->frontsector->floorheight;
+			slope->o.z = slope->sourceline->frontsector->floorheight;
+			break;
+		case 2: // front ceiling
+			zdelta = slope->sourceline->backsector->ceilingheight - slope->sourceline->frontsector->ceilingheight;
+			slope->o.z = slope->sourceline->frontsector->ceilingheight;
+			break;
+		case 3: // back floor
+			zdelta = slope->sourceline->frontsector->floorheight - slope->sourceline->backsector->floorheight;
+			slope->o.z = slope->sourceline->backsector->floorheight;
+			break;
+		case 4: // back ceiling
+			zdelta = slope->sourceline->frontsector->ceilingheight - slope->sourceline->backsector->ceilingheight;
+			slope->o.z = slope->sourceline->backsector->ceilingheight;
+			break;
+		case 5: // vertices
+			{
+				mapthing_t *mt;
+				size_t i;
+				INT32 l;
+				line_t *line;
+
+				for (i = 0; i < 3; i++) {
+					mt = slope->vertices[i];
+					l = P_FindSpecialLineFromTag(799, mt->angle, -1);
+					if (l != -1) {
+						line = &lines[l];
+						mt->z = line->frontsector->floorheight >> FRACBITS;
+					}
+				}
+
+				P_ReconfigureVertexSlope(slope);
+			}
+			continue; // TODO
+
+		default:
+			I_Error("P_RunDynamicSlopes: slope has invalid type!");
+		}
+
+		if (slope->zdelta != FixedDiv(zdelta, slope->extent)) {
+			slope->zdelta = FixedDiv(zdelta, slope->extent);
+			slope->zangle = R_PointToAngle2(0, 0, slope->extent, -zdelta);
+			P_CalculateSlopeNormal(slope);
+		}
+	}
+}
+
+//
+// P_MakeSlope
+//
+// Alocates and fill the contents of a slope structure.
+//
+static pslope_t *P_MakeSlope(const vector3_t *o, const vector2_t *d,
+                             const fixed_t zdelta, UINT8 flags)
+{
+	pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
+	memset(ret, 0, sizeof(*ret));
+
+	ret->o.x = o->x;
+	ret->o.y = o->y;
+	ret->o.z = o->z;
+
+	ret->d.x = d->x;
+	ret->d.y = d->y;
+
+	ret->zdelta = zdelta;
+
+	ret->flags = flags;
+
+	// Add to the slope list
+	ret->next = slopelist;
+	slopelist = ret;
+
+	slopecount++;
+	ret->id = slopecount;
+
+	return ret;
+}
+
+//
+// P_GetExtent
+//
+// Returns the distance to the first line within the sector that
+// is intersected by a line parallel to the plane normal with the point (ox, oy)
+//
+static fixed_t P_GetExtent(sector_t *sector, line_t *line)
+{
+	// ZDoom code reference: v3float_t = vertex_t
+	fixed_t fardist = -FRACUNIT;
+	size_t i;
+
+	// Find furthest vertex from the reference line. It, along with the two ends
+	// of the line, will define the plane.
+	// SRB2CBTODO: Use a formula to get the slope to slide objects depending on how steep
+	for(i = 0; i < sector->linecount; i++)
+	{
+		line_t *li = sector->lines[i];
+		vertex_t tempv;
+		fixed_t dist;
+
+		// Don't compare to the slope line.
+		if(li == line)
+			continue;
+
+		P_ClosestPointOnLine(li->v1->x, li->v1->y, line, &tempv);
+		dist = R_PointToDist2(tempv.x, tempv.y, li->v1->x, li->v1->y);
+		if(dist > fardist)
+			fardist = dist;
+
+		// Okay, maybe do it for v2 as well?
+		P_ClosestPointOnLine(li->v2->x, li->v2->y, line, &tempv);
+		dist = R_PointToDist2(tempv.x, tempv.y, li->v2->x, li->v2->y);
+		if(dist > fardist)
+			fardist = dist;
+	}
+
+	return fardist;
+}
+
+
+//
+// P_SpawnSlope_Line
+//
+// Creates one or more slopes based on the given line type and front/back
+// sectors.
+// Kalaron: Check if dynamic slopes need recalculation
+//
+void P_SpawnSlope_Line(int linenum)
+{
+	// With dynamic slopes, it's fine to just leave this function as normal,
+	// because checking to see if a slope had changed will waste more memory than
+	// if the slope was just updated when called
+	line_t *line = lines + linenum;
+	INT16 special = line->special;
+	pslope_t *fslope = NULL, *cslope = NULL;
+	vector3_t origin, point;
+	vector2_t direction;
+	fixed_t nx, ny, dz, extent;
+
+	boolean frontfloor = (special == 700 || special == 702 || special == 703);
+	boolean backfloor  = (special == 710 || special == 712 || special == 713);
+	boolean frontceil  = (special == 701 || special == 702 || special == 713);
+	boolean backceil   = (special == 711 || special == 712 || special == 703);
+
+	UINT8 flags = 0; // Slope flags
+	if (line->flags & ML_NOSONIC)
+		flags |= SL_NOPHYSICS;
+	if (line->flags & ML_NOTAILS)
+		flags |= SL_NODYNAMIC;
+	if (line->flags & ML_NOKNUX)
+		flags |= SL_ANCHORVERTEX;
+
+	if(!frontfloor && !backfloor && !frontceil && !backceil)
+	{
+		CONS_Printf("P_SpawnSlope_Line called with non-slope line special.\n");
+		return;
+	}
+
+	if(!line->frontsector || !line->backsector)
+	{
+		CONS_Printf("P_SpawnSlope_Line used on a line without two sides.\n");
+		return;
+	}
+
+	{
+		fixed_t len = R_PointToDist2(0, 0, line->dx, line->dy);
+		nx = FixedDiv(line->dy, len);
+		ny = -FixedDiv(line->dx, len);
+	}
+
+	// SRB2CBTODO: Transform origin relative to the bounds of an individual FOF
+	origin.x = line->v1->x + (line->v2->x - line->v1->x)/2;
+	origin.y = line->v1->y + (line->v2->y - line->v1->y)/2;
+
+	// For FOF slopes, make a special function to copy to the xy origin & direction relative to the position of the FOF on the map!
+	if(frontfloor || frontceil)
+	{
+		line->frontsector->hasslope = true; // Tell the software renderer that we're sloped
+
+		origin.z = line->backsector->floorheight;
+		direction.x = nx;
+		direction.y = ny;
+
+		extent = P_GetExtent(line->frontsector, line);
+
+		if(extent < 0)
+		{
+			CONS_Printf("P_SpawnSlope_Line failed to get frontsector extent on line number %i\n", linenum);
+			return;
+		}
+
+		// reposition the origin according to the extent
+		point.x = origin.x + FixedMul(direction.x, extent);
+		point.y = origin.y + FixedMul(direction.y, extent);
+		direction.x = -direction.x;
+		direction.y = -direction.y;
+
+		// TODO: We take origin and point 's xy values and translate them to the center of an FOF!
+
+		if(frontfloor)
+		{
+			fixed_t highest, lowest;
+			size_t l;
+			point.z = line->frontsector->floorheight; // Startz
+			dz = FixedDiv(origin.z - point.z, extent); // Destinationz
+
+			// In P_SpawnSlopeLine the origin is the centerpoint of the sourcelinedef
+
+			fslope = line->frontsector->f_slope =
+            P_MakeSlope(&point, &direction, dz, flags);
+
+            // Set up some shit
+            fslope->extent = extent;
+            fslope->refpos = 1;
+
+			// Now remember that f_slope IS a vector
+			// fslope->o = origin      3D point 1 of the vector
+			// fslope->d = destination 3D point 2 of the vector
+			// fslope->normal is a 3D line perpendicular to the 3D vector
+
+			// Sync the linedata of the line that started this slope
+			// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
+			fslope->sourceline = line;
+
+			// To find the real highz/lowz of a slope, you need to check all the vertexes
+			// in the slope's sector with P_GetZAt to get the REAL lowz & highz
+			// Although these slopes are set by floorheights the ANGLE is what a slope is,
+			// so technically any slope can extend on forever (they are just bound by sectors)
+			// *You can use sourceline as a reference to see if two slopes really are the same
+
+			// Default points for high and low
+			highest = point.z > origin.z ? point.z : origin.z;
+			lowest = point.z < origin.z ? point.z : origin.z;
+
+			// Now check to see what the REAL high and low points of the slope inside the sector
+			// TODO: Is this really needed outside of FOFs? -Red
+
+			for (l = 0; l < line->frontsector->linecount; l++)
+			{
+				fixed_t height = P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
+
+				if (height > highest)
+					highest = height;
+
+				if (height < lowest)
+					lowest = height;
+			}
+
+			// Sets extra clipping data for the frontsector's slope
+			fslope->highz = highest;
+			fslope->lowz = lowest;
+
+			fslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
+			fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
+
+			P_CalculateSlopeNormal(fslope);
+		}
+		if(frontceil)
+		{
+			fixed_t highest, lowest;
+			size_t l;
+			origin.z = line->backsector->ceilingheight;
+			point.z = line->frontsector->ceilingheight;
+			dz = FixedDiv(origin.z - point.z, extent);
+
+			cslope = line->frontsector->c_slope =
+            P_MakeSlope(&point, &direction, dz, flags);
+
+            // Set up some shit
+            cslope->extent = extent;
+            cslope->refpos = 2;
+
+			// Sync the linedata of the line that started this slope
+			// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
+			cslope->sourceline = line;
+
+			// Remember the way the slope is formed
+			highest = point.z > origin.z ? point.z : origin.z;
+			lowest = point.z < origin.z ? point.z : origin.z;
+
+			for (l = 0; l < line->frontsector->linecount; l++)
+			{
+				fixed_t height = P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
+
+				if (height > highest)
+					highest = height;
+
+				if (height < lowest)
+					lowest = height;
+			}
+
+			// This line special sets extra clipping data for the frontsector's slope
+			cslope->highz = highest;
+			cslope->lowz = lowest;
+
+			cslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
+			cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
+
+			P_CalculateSlopeNormal(cslope);
+		}
+	}
+	if(backfloor || backceil)
+	{
+		line->backsector->hasslope = true; // Tell the software renderer that we're sloped
+
+		origin.z = line->frontsector->floorheight;
+		// Backsector
+		direction.x = -nx;
+		direction.y = -ny;
+
+		extent = P_GetExtent(line->backsector, line);
+
+		if(extent < 0)
+		{
+			CONS_Printf("P_SpawnSlope_Line failed to get backsector extent on line number %i\n", linenum);
+			return;
+		}
+
+		// reposition the origin according to the extent
+		point.x = origin.x + FixedMul(direction.x, extent);
+		point.y = origin.y + FixedMul(direction.y, extent);
+		direction.x = -direction.x;
+		direction.y = -direction.y;
+
+		if(backfloor)
+		{
+			fixed_t highest, lowest;
+			size_t l;
+			point.z = line->backsector->floorheight;
+			dz = FixedDiv(origin.z - point.z, extent);
+
+			fslope = line->backsector->f_slope =
+            P_MakeSlope(&point, &direction, dz, flags);
+
+            // Set up some shit
+            fslope->extent = extent;
+            fslope->refpos = 3;
+
+			// Sync the linedata of the line that started this slope
+			// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
+			fslope->sourceline = line;
+
+			// Remember the way the slope is formed
+			highest = point.z > origin.z ? point.z : origin.z;
+			lowest = point.z < origin.z ? point.z : origin.z;
+
+			for (l = 0; l < line->backsector->linecount; l++)
+			{
+				fixed_t height = P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
+
+				if (height > highest)
+					highest = height;
+
+				if (height < lowest)
+					lowest = height;
+			}
+
+			// This line special sets extra clipping data for the frontsector's slope
+			fslope->highz = highest;
+			fslope->lowz = lowest;
+
+			fslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
+			fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
+
+			P_CalculateSlopeNormal(fslope);
+		}
+		if(backceil)
+		{
+			fixed_t highest, lowest;
+			size_t l;
+			origin.z = line->frontsector->ceilingheight;
+			point.z = line->backsector->ceilingheight;
+			dz = FixedDiv(origin.z - point.z, extent);
+
+			cslope = line->backsector->c_slope =
+            P_MakeSlope(&point, &direction, dz, flags);
+
+            // Set up some shit
+            cslope->extent = extent;
+            cslope->refpos = 4;
+
+			// Sync the linedata of the line that started this slope
+			// SRB2CBTODO: Anything special for remote(control sector)-based slopes later?
+			cslope->sourceline = line;
+
+			// Remember the way the slope is formed
+			highest = point.z > origin.z ? point.z : origin.z;
+			lowest = point.z < origin.z ? point.z : origin.z;
+
+			for (l = 0; l < line->backsector->linecount; l++)
+			{
+				fixed_t height = P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
+
+				if (height > highest)
+					highest = height;
+
+				if (height < lowest)
+					lowest = height;
+			}
+
+			// This line special sets extra clipping data for the backsector's slope
+			cslope->highz = highest;
+			cslope->lowz = lowest;
+
+			cslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
+			cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
+
+			P_CalculateSlopeNormal(cslope);
+		}
+	}
+
+	if(!line->tag)
+		return;
+}
+
+//
+// P_NewVertexSlope
+//
+// Creates a new slope from three vertices with the specified IDs
+//
+static pslope_t *P_NewVertexSlope(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flags)
+{
+	size_t i;
+	mapthing_t *mt = mapthings;
+
+	pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
+	memset(ret, 0, sizeof(*ret));
+
+	// Start by setting flags
+	ret->flags = flags;
+
+	// Now set up the vertex list
+	ret->vertices = Z_Malloc(3*sizeof(mapthing_t), PU_LEVEL, NULL);
+	memset(ret->vertices, 0, 3*sizeof(mapthing_t));
+
+	// And... look for the vertices in question.
+	for (i = 0; i < nummapthings; i++, mt++) {
+		if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something!
+			continue;
+
+		if (!ret->vertices[0] && mt->angle == tag1)
+			ret->vertices[0] = mt;
+		else if (!ret->vertices[1] && mt->angle == tag2)
+			ret->vertices[1] = mt;
+		else if (!ret->vertices[2] && mt->angle == tag3)
+			ret->vertices[2] = mt;
+	}
+
+	if (!ret->vertices[0])
+		CONS_Printf("PANIC 0\n");
+	if (!ret->vertices[1])
+		CONS_Printf("PANIC 1\n");
+	if (!ret->vertices[2])
+		CONS_Printf("PANIC 2\n");
+
+	// Now set heights for each vertex, because they haven't been set yet
+	for (i = 0; i < 3; i++) {
+		mt = ret->vertices[i];
+		if (mt->extrainfo)
+			mt->z = mt->options;
+		else
+			mt->z = (R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector->floorheight >> FRACBITS) + (mt->options >> ZSHIFT);
+	}
+
+	P_ReconfigureVertexSlope(ret);
+	ret->refpos = 5;
+
+	// Add to the slope list
+	ret->next = slopelist;
+	slopelist = ret;
+
+	slopecount++;
+	ret->id = slopecount;
+
+	return ret;
+}
+
+
+
+//
+// P_CopySectorSlope
+//
+// Searches through tagged sectors and copies
+//
+void P_CopySectorSlope(line_t *line)
+{
+   sector_t *fsec = line->frontsector;
+   int i, special = line->special;
+
+   // Check for copy linedefs
+   for(i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;)
+   {
+      sector_t *srcsec = sectors + i;
+
+      if((special - 719) & 1 && !fsec->f_slope && srcsec->f_slope)
+         fsec->f_slope = srcsec->f_slope; //P_CopySlope(srcsec->f_slope);
+      if((special - 719) & 2 && !fsec->c_slope && srcsec->c_slope)
+         fsec->c_slope = srcsec->c_slope; //P_CopySlope(srcsec->c_slope);
+   }
+
+   fsec->hasslope = true;
+
+   line->special = 0; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef
+}
+
+//
+// P_SlopeById
+//
+// Looks in the slope list for a slope with a specified ID. Mostly useful for netgame sync
+//
+pslope_t *P_SlopeById(UINT16 id)
+{
+	pslope_t *ret;
+	for (ret = slopelist; ret && ret->id != id; ret = ret->next);
+	return ret;
+}
+
+#ifdef SPRINGCLEAN
+#include "byteptr.h"
+
+#include "p_setup.h"
+#include "p_local.h"
+
+//==========================================================================
+//
+//	P_SetSlopesFromVertexHeights
+//
+//==========================================================================
+void P_SetSlopesFromVertexHeights(lumpnum_t lumpnum)
+{
+	mapthing_t *mt;
+	boolean vt_found = false;
+	size_t i, j, k, l, q;
+
+	//size_t i;
+	//mapthing_t *mt;
+	char *data;
+	char *datastart;
+
+	// SRB2CBTODO: WHAT IS (5 * sizeof (short))?! It = 10
+	// anything else seems to make a map not load properly,
+	// but this hard-coded value MUST have some reason for being what it is
+	size_t snummapthings = W_LumpLength(lumpnum) / (5 * sizeof (short));
+	mapthing_t *smapthings = Z_Calloc(snummapthings * sizeof (*smapthings), PU_LEVEL, NULL);
+	fixed_t x, y;
+	sector_t *sector;
+	// Spawn axis points first so they are
+	// at the front of the list for fast searching.
+	data = datastart = W_CacheLumpNum(lumpnum, PU_LEVEL);
+	mt = smapthings;
+	for (i = 0; i < snummapthings; i++, mt++)
+	{
+		mt->x = READINT16(data);
+		mt->y = READINT16(data);
+		mt->angle = READINT16(data);
+		mt->type = READINT16(data);
+		mt->options = READINT16(data);
+		// mt->z hasn't been set yet!
+		//mt->extrainfo = (byte)(mt->type >> 12); // slope things are special, they have a bigger range of types
+
+		//mt->type &= 4095; // SRB2CBTODO: WHAT IS THIS???? Mobj type limits?!!!!
+		x = mt->x*FRACUNIT;
+		y = mt->y*FRACUNIT;
+		sector = R_PointInSubsector(x, y)->sector;
+		// Z for objects
+#ifdef ESLOPE
+		if (sector->f_slope)
+			mt->z = (short)(P_GetZAt(sector->f_slope, x, y)>>FRACBITS);
+		else
+#endif
+			mt->z = (short)(sector->floorheight>>FRACBITS);
+
+		mt->z = mt->z + (mt->options >> ZSHIFT);
+
+		if (mt->type == THING_VertexFloorZ || mt->type == THING_VertexCeilingZ) // THING_VertexFloorZ
+		{
+			for(l = 0; l < numvertexes; l++)
+			{
+				if (vertexes[l].x == mt->x*FRACUNIT && vertexes[l].y == mt->y*FRACUNIT)
+				{
+					if (mt->type == THING_VertexFloorZ)
+					{
+						vertexes[l].z = mt->z*FRACUNIT;
+						//I_Error("Z value: %i", vertexes[l].z/FRACUNIT);
+
+					}
+					else
+					{
+						vertexes[l].z = mt->z*FRACUNIT; // celing floor
+					}
+					vt_found = true;
+				}
+			}
+			//mt->type = 0; // VPHYSICS: Dynamic slopes
+
+
+
+
+
+
+			if (vt_found)
+			{
+				for (k = 0; k < numsectors; k++)
+				{
+					sector_t *sec = &sectors[k];
+					if (sec->linecount != 3) continue;	// only works with triangular sectors
+
+					v3float_t vt1, vt2, vt3; // cross = ret->normalf
+					v3float_t vec1, vec2;
+
+					int vi1, vi2, vi3;
+
+					vi1 = (int)(sec->lines[0]->v1 - vertexes);
+					vi2 = (int)(sec->lines[0]->v2 - vertexes);
+					vi3 = (sec->lines[1]->v1 == sec->lines[0]->v1 || sec->lines[1]->v1 == sec->lines[0]->v2)?
+					(int)(sec->lines[1]->v2 - vertexes) : (int)(sec->lines[1]->v1 - vertexes);
+
+					//if (vertexes[vi1].z)
+					//	I_Error("OSNAP %i", vertexes[vi1].z/FRACUNIT);
+					//if (vertexes[vi2].z)
+					//	I_Error("OSNAP %i", vertexes[vi2].z/FRACUNIT);
+					//if (vertexes[vi3].z)
+					//	I_Error("OSNAP %i", vertexes[vi3].z/FRACUNIT);
+
+					//I_Error("%i, %i", mt->z*FRACUNIT, vertexes[vi1].z);
+
+					//I_Error("%i, %i, %i", mt->x, mt->y, mt->z);
+					//P_SpawnMobj(mt->x*FRACUNIT, mt->y*FRACUNIT, mt->z*FRACUNIT, MT_RING);
+
+					// TODO: Make sure not to spawn in the same place 2x! (we need an object in every vertex of the
+					// triangle sector to setup the real vertex slopes
+					// Check for the vertexes of all sectors
+					for(q = 0; q < numvertexes; q++)
+					{
+						if (vertexes[q].x == mt->x*FRACUNIT && vertexes[q].y == mt->y*FRACUNIT)
+						{
+							//I_Error("yeah %i", vertexes[q].z);
+							P_SpawnMobj(vertexes[q].x, vertexes[q].y, vertexes[q].z, MT_RING);
+#if 0
+					if ((mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z))
+						P_SpawnMobj(vertexes[vi1].x, vertexes[vi1].y, vertexes[vi1].z, MT_RING);
+					else if ((mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z))
+						P_SpawnMobj(vertexes[vi2].x, vertexes[vi2].y, vertexes[vi2].z, MT_BOUNCETV);
+					else if ((mt->y*FRACUNIT == vertexes[vi3].y && mt->x*FRACUNIT == vertexes[vi3].x && mt->z*FRACUNIT == vertexes[vi3].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi2].y && mt->x*FRACUNIT == vertexes[vi2].x && mt->z*FRACUNIT == vertexes[vi2].z)
+						&& !(mt->y*FRACUNIT == vertexes[vi1].y && mt->x*FRACUNIT == vertexes[vi1].x && mt->z*FRACUNIT == vertexes[vi1].z))
+						P_SpawnMobj(vertexes[vi3].x, vertexes[vi3].y, vertexes[vi3].z, MT_GFZFLOWER1);
+					else
+#endif
+						continue;
+						}
+					}
+
+					vt1.x = FIXED_TO_FLOAT(vertexes[vi1].x);
+					vt1.y = FIXED_TO_FLOAT(vertexes[vi1].y);
+					vt2.x = FIXED_TO_FLOAT(vertexes[vi2].x);
+					vt2.y = FIXED_TO_FLOAT(vertexes[vi2].y);
+					vt3.x = FIXED_TO_FLOAT(vertexes[vi3].x);
+					vt3.y = FIXED_TO_FLOAT(vertexes[vi3].y);
+
+					for(j = 0; j < 2; j++)
+					{
+
+						fixed_t z3;
+						//I_Error("Lo hicimos");
+
+						vt1.z = mt->z;//FIXED_TO_FLOAT(j==0 ? sec->floorheight : sec->ceilingheight);
+						vt2.z = mt->z;//FIXED_TO_FLOAT(j==0? sec->floorheight : sec->ceilingheight);
+						z3 = mt->z;//j==0? sec->floorheight : sec->ceilingheight; // Destination height
+						vt3.z = FIXED_TO_FLOAT(z3);
+
+						if (P_PointOnLineSide(vertexes[vi3].x, vertexes[vi3].y, sec->lines[0]) == 0)
+						{
+							vec1.x = vt2.x - vt3.x;
+							vec1.y = vt2.y - vt3.y;
+							vec1.z = vt2.z - vt3.z;
+
+							vec2.x = vt1.x - vt3.x;
+							vec2.y = vt1.y - vt3.y;
+							vec2.z = vt1.z - vt3.z;
+						}
+						else
+						{
+							vec1.x = vt1.x - vt3.x;
+							vec1.y = vt1.y - vt3.y;
+							vec1.z = vt1.z - vt3.z;
+
+							vec2.x = vt2.x - vt3.x;
+							vec2.y = vt2.y - vt3.y;
+							vec2.z = vt2.z - vt3.z;
+						}
+
+
+						pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
+						memset(ret, 0, sizeof(*ret));
+
+						{
+							M_CrossProduct3f(&ret->normalf, &vec1, &vec2);
+
+							// Cross product length
+							float len = (float)sqrt(ret->normalf.x * ret->normalf.x +
+													ret->normalf.y * ret->normalf.y +
+													ret->normalf.z * ret->normalf.z);
+
+							if (len == 0)
+							{
+								// Only happens when all vertices in this sector are on the same line.
+								// Let's just ignore this case.
+								//CONS_Printf("Slope thing at (%d,%d) lies directly on its target line.\n", (int)(x>>16), (int)(y>>16));
+								return;
+							}
+							// cross/len
+							ret->normalf.x /= len;
+							ret->normalf.y /= len;
+							ret->normalf.z /= len;
+
+							// ZDoom cross = ret->normalf
+							// Fix backward normals
+							if ((ret->normalf.z < 0 && j == 0) || (ret->normalf.z > 0 && j == 1))
+							{
+								// cross = -cross
+								ret->normalf.x = -ret->normalf.x;
+								ret->normalf.y = -ret->normalf.x;
+								ret->normalf.z = -ret->normalf.x;
+							}
+						}
+
+						secplane_t *srcplane = Z_Calloc(sizeof(*srcplane), PU_LEVEL, NULL);
+
+						srcplane->a = FLOAT_TO_FIXED (ret->normalf.x);
+						srcplane->b = FLOAT_TO_FIXED (ret->normalf.y);
+						srcplane->c = FLOAT_TO_FIXED (ret->normalf.z);
+						//srcplane->ic = FixedDiv(FRACUNIT, srcplane->c);
+						srcplane->d = -TMulScale16 (srcplane->a, vertexes[vi3].x,
+													srcplane->b, vertexes[vi3].y,
+													srcplane->c, z3);
+
+						if (j == 0)
+						{
+							sec->f_slope = ret;
+							sec->f_slope->secplane = *srcplane;
+						}
+						else if (j == 1)
+						{
+							sec->c_slope = ret;
+							sec->c_slope->secplane = *srcplane;
+						}
+					}
+				}
+			}
+
+
+
+
+
+
+
+
+		}
+	}
+	Z_Free(datastart);
+
+
+
+
+}
+#endif
+
+// Reset the dynamic slopes pointer, and read all of the fancy schmancy slopes
+void P_ResetDynamicSlopes(void) {
+	size_t i;
+#if 1 // Rewrite old specials to new ones, and give a console warning
+	boolean warned = false;
+#endif
+
+	slopelist = NULL;
+	slopecount = 0;
+
+	// We'll handle copy slopes later, after all the tag lists have been made.
+	// Yes, this means copied slopes won't affect things' spawning heights. Too bad for you.
+	for (i = 0; i < numlines; i++)
+	{
+		switch (lines[i].special)
+		{
+#if 1 // Rewrite old specials to new ones, and give a console warning
+#define WARNME if (!warned) {warned = true; CONS_Alert(CONS_WARNING, "This level uses old slope specials.\nA conversion will be needed before 2.2's release.\n");}
+			case 386:
+			case 387:
+			case 388:
+				lines[i].special += 700-386;
+				WARNME
+				P_SpawnSlope_Line(i);
+				break;
+
+			case 389:
+			case 390:
+			case 391:
+			case 392:
+				lines[i].special += 710-389;
+				WARNME
+				P_SpawnSlope_Line(i);
+				break;
+
+			case 393:
+				lines[i].special = 703;
+				WARNME
+				P_SpawnSlope_Line(i);
+				break;
+
+			case 394:
+			case 395:
+			case 396:
+				lines[i].special += 720-394;
+				WARNME
+				break;
+
+#endif
+
+			case 700:
+			case 701:
+			case 702:
+			case 703:
+			case 710:
+			case 711:
+			case 712:
+			case 713:
+				P_SpawnSlope_Line(i);
+				break;
+
+			case 704:
+			case 705:
+			case 714:
+			case 715:
+				{
+					pslope_t **slopetoset;
+					size_t which = lines[i].special;
+
+					UINT8 flags = SL_VERTEXSLOPE;
+					if (lines[i].flags & ML_NOSONIC)
+						flags |= SL_NOPHYSICS;
+					if (!(lines[i].flags & ML_NOTAILS))
+						flags |= SL_NODYNAMIC;
+
+					if (which == 704)
+					{
+						slopetoset = &lines[i].frontsector->f_slope;
+						which = 0;
+					}
+					else if (which == 705)
+					{
+						slopetoset = &lines[i].frontsector->c_slope;
+						which = 0;
+					}
+					else if (which == 714)
+					{
+						slopetoset = &lines[i].backsector->f_slope;
+						which = 1;
+					}
+					else // 715
+					{
+						slopetoset = &lines[i].backsector->c_slope;
+						which = 1;
+					}
+
+					if (lines[i].flags & ML_NOKNUX)
+						*slopetoset = P_NewVertexSlope(lines[i].tag, sides[lines[i].sidenum[which]].textureoffset >> FRACBITS,
+																			sides[lines[i].sidenum[which]].rowoffset >> FRACBITS, flags);
+					else
+						*slopetoset = P_NewVertexSlope(lines[i].tag, lines[i].tag, lines[i].tag, flags);
+
+					sides[lines[i].sidenum[which]].sector->hasslope = true;
+				}
+				break;
+
+			default:
+				break;
+		}
+	}
+}
+
+
+
+
+// ============================================================================
+//
+// Various utilities related to slopes
+//
+
+//
+// P_GetZAt
+//
+// Returns the height of the sloped plane at (x, y) as a fixed_t
+//
+fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y)
+{
+   fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) +
+                  FixedMul(y - slope->o.y, slope->d.y);
+
+   return slope->o.z + FixedMul(dist, slope->zdelta);
+}
+
+
+//
+// P_QuantizeMomentumToSlope
+//
+// When given a vector, rotates it and aligns it to a slope
+void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope)
+{
+	vector3_t axis;
+	axis.x = -slope->d.y;
+	axis.y = slope->d.x;
+	axis.z = 0;
+
+	FV3_Rotate(momentum, &axis, slope->zangle >> ANGLETOFINESHIFT);
+}
+
+//
+// P_SlopeLaunch
+//
+// Handles slope ejection for objects
+void P_SlopeLaunch(mobj_t *mo)
+{
+	// Double the pre-rotation Z, then halve the post-rotation Z. This reduces the
+	// vertical launch given from slopes while increasing the horizontal launch
+	// given. Good for SRB2's gravity and horizontal speeds.
+	vector3_t slopemom;
+	slopemom.x = mo->momx;
+	slopemom.y = mo->momy;
+	slopemom.z = mo->momz*2;
+	P_QuantizeMomentumToSlope(&slopemom, mo->standingslope);
+
+	mo->momx = slopemom.x;
+	mo->momy = slopemom.y;
+	mo->momz = slopemom.z/2;
+
+	//CONS_Printf("Launched off of slope.\n");
+	mo->standingslope = NULL;
+}
+
+// Function to help handle landing on slopes
+void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope)
+{
+	vector3_t mom;
+	mom.x = thing->momx;
+	mom.y = thing->momy;
+	mom.z = thing->momz*2;
+
+	//CONS_Printf("langing on slope\n");
+
+	// Reverse quantizing might could use its own function later
+	slope->zangle = ANGLE_MAX-slope->zangle;
+	P_QuantizeMomentumToSlope(&mom, slope);
+	slope->zangle = ANGLE_MAX-slope->zangle;
+
+	if (P_MobjFlip(thing)*mom.z < 0) { // falling, land on slope
+		thing->momx = mom.x;
+		thing->momy = mom.y;
+		thing->momz = -P_MobjFlip(thing);
+
+		thing->standingslope = slope;
+	}
+}
+
+// https://yourlogicalfallacyis.com/slippery-slope
+// Handles sliding down slopes, like if they were made of butter :)
+void P_ButteredSlope(mobj_t *mo)
+{
+	fixed_t thrust;
+
+	if (!mo->standingslope)
+		return;
+
+	if (mo->player) {
+		if (abs(mo->standingslope->zdelta) < FRACUNIT/4 && !(mo->player->pflags & PF_SPINNING))
+			return; // Don't slide on non-steep slopes unless spinning
+
+		if (abs(mo->standingslope->zdelta) < FRACUNIT/2 && !(mo->player->rmomx || mo->player->rmomy))
+			return; // Allow the player to stand still on slopes below a certain steepness
+	}
+
+	thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 3 / 2 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1);
+
+	if (mo->player && (mo->player->pflags & PF_SPINNING)) {
+		fixed_t mult = 0;
+		if (mo->momx || mo->momy) {
+			angle_t angle = R_PointToAngle2(0, 0, mo->momx, mo->momy) - mo->standingslope->xydirection;
+
+			if (P_MobjFlip(mo) * mo->standingslope->zdelta < 0)
+				angle ^= ANGLE_180;
+
+			mult = FINECOSINE(angle >> ANGLETOFINESHIFT);
+		}
+
+		//CONS_Printf("%d\n", mult);
+
+		thrust = FixedMul(thrust, FRACUNIT*2/3 + mult/8);
+	}
+
+	if (mo->momx || mo->momy) // Slightly increase thrust based on the object's speed
+		thrust = FixedMul(thrust, FRACUNIT+P_AproxDistance(mo->momx, mo->momy)/16);
+	// This makes it harder to zigzag up steep slopes, as well as allows greater top speed when rolling down
+
+	// Multiply by gravity
+	thrust = FixedMul(thrust, FRACUNIT/2); // TODO actually get this
+
+	P_Thrust(mo, mo->standingslope->xydirection, thrust);
+}
+
+// EOF
+#endif // #ifdef ESLOPE
diff --git a/src/p_slopes.h b/src/p_slopes.h
new file mode 100644
index 0000000000000000000000000000000000000000..8d82632ff31a02d64ad34437863ee9351a421896
--- /dev/null
+++ b/src/p_slopes.h
@@ -0,0 +1,80 @@
+// Emacs style mode select   -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2004 Stephen McGranahan
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+//--------------------------------------------------------------------------
+//
+// DESCRIPTION:
+//      Slopes
+//      SoM created 05/10/09
+//
+//-----------------------------------------------------------------------------
+
+#ifndef P_SLOPES_H__
+#define P_SLOPES_H__
+
+#ifdef ESLOPE
+void P_ResetDynamicSlopes(void);
+void P_RunDynamicSlopes(void);
+// P_SpawnSlope_Line
+// Creates one or more slopes based on the given line type and front/back
+// sectors.
+void P_SpawnSlope_Line(int linenum);
+
+#ifdef SPRINGCLEAN
+// Loads just map objects that make slopes,
+// terrain affecting objects have to be spawned first
+void P_SetSlopesFromVertexHeights(lumpnum_t lumpnum);
+
+typedef enum
+{
+	THING_SlopeFloorPointLine = 9500,
+	THING_SlopeCeilingPointLine = 9501,
+	THING_SetFloorSlope = 9502,
+	THING_SetCeilingSlope = 9503,
+	THING_CopyFloorPlane = 9510,
+	THING_CopyCeilingPlane = 9511,
+	THING_VavoomFloor=1500,
+	THING_VavoomCeiling=1501,
+	THING_VertexFloorZ=1504,
+	THING_VertexCeilingZ=1505,
+} slopething_e;
+#endif
+
+//
+// P_CopySectorSlope
+//
+// Searches through tagged sectors and copies
+//
+void P_CopySectorSlope(line_t *line);
+
+pslope_t *P_SlopeById(UINT16 id);
+
+// Returns the height of the sloped plane at (x, y) as a fixed_t
+fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y);
+
+// Lots of physics-based bullshit
+void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope);
+void P_SlopeLaunch(mobj_t *mo);
+void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope);
+void P_ButteredSlope(mobj_t *mo);
+
+#endif
+
+// EOF
+#endif // #ifdef ESLOPE
diff --git a/src/p_spec.c b/src/p_spec.c
index 9800c5d1c741c4b1af1cec666bb6fdba860402c3..187a4149d59e2013f7053dabdfa7e7e693d211e6 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -29,6 +29,7 @@
 #include "r_main.h" //Two extra includes.
 #include "r_sky.h"
 #include "p_polyobj.h"
+#include "p_slopes.h"
 #include "hu_stuff.h"
 #include "m_misc.h"
 #include "m_cond.h" //unlock triggers
@@ -3365,6 +3366,7 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n
 static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *targetsec)
 {
 	ffloor_t *rover;
+	fixed_t top, bottom;
 
 	if (!mo->player) // should NEVER happen
 		return false;
@@ -3381,6 +3383,9 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar
 		//if (!(rover->flags & FF_EXISTS))
 		//	return false;
 
+		top = P_GetSpecialTopZ(mo, sector, targetsec);
+		bottom = P_GetSpecialBottomZ(mo, sector, targetsec);
+
 		// Check the 3D floor's type...
 		if (rover->flags & FF_BLOCKPLAYER)
 		{
@@ -3388,27 +3393,27 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar
 			if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
 				&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
 			{
-				if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != *rover->topheight)
+				if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != top)
 					return false;
 			}
 			else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
 				&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
 			{
 				if (!(mo->eflags & MFE_VERTICALFLIP)
-					|| mo->z + mo->height != *rover->bottomheight)
+					|| mo->z + mo->height != bottom)
 					return false;
 			}
 			else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
 			{
-				if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == *rover->bottomheight)
-					|| (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == *rover->topheight)))
+				if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottom)
+					|| (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == top)))
 					return false;
 			}
 		}
 		else
 		{
 			// Water and intangible FOFs
-			if (mo->z > *rover->topheight || (mo->z + mo->height) < *rover->bottomheight)
+			if (mo->z > top || (mo->z + mo->height) < bottom)
 				return false;
 		}
 
@@ -3426,9 +3431,9 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar
 static inline boolean P_MobjReadyToTrigger(mobj_t *mo, sector_t *sec)
 {
 	if (mo->eflags & MFE_VERTICALFLIP)
-		return (mo->z+mo->height == sec->ceilingheight && sec->flags & SF_FLIPSPECIAL_CEILING);
+		return (mo->z+mo->height == P_GetSpecialTopZ(mo, sec, sec) && sec->flags & SF_FLIPSPECIAL_CEILING);
 	else
-		return (mo->z == sec->floorheight && sec->flags & SF_FLIPSPECIAL_FLOOR);
+		return (mo->z == P_GetSpecialBottomZ(mo, sec, sec) && sec->flags & SF_FLIPSPECIAL_FLOOR);
 }
 
 /** Applies a sector special to a player.
@@ -4389,27 +4394,27 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector)
 			if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
 				&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
 			{
-				if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != *rover->topheight)
+				if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != P_GetSpecialTopZ(player->mo, sectors + rover->secnum, sector))
 					continue;
 			}
 			else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
 				&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
 			{
 				if (!(player->mo->eflags & MFE_VERTICALFLIP)
-					|| player->mo->z + player->mo->height != *rover->bottomheight)
+					|| player->mo->z + player->mo->height != P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, sector))
 					continue;
 			}
 			else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
 			{
-				if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == *rover->bottomheight)
-					|| (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == *rover->topheight)))
+				if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, sector))
+					|| (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == P_GetSpecialTopZ(player->mo, sectors + rover->secnum, sector))))
 					continue;
 			}
 		}
 		else
 		{
 			// Water and DEATH FOG!!! heh
-			if (player->mo->z > *rover->topheight || (player->mo->z + player->mo->height) < *rover->bottomheight)
+			if (player->mo->z > P_GetSpecialTopZ(player->mo, sectors + rover->secnum, sector) || (player->mo->z + player->mo->height) < P_GetSpecialBottomZ(player->mo, sectors + rover->secnum, sector))
 				continue;
 		}
 
@@ -4519,6 +4524,7 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector)
 static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector)
 {
 	boolean nofloorneeded = false;
+	fixed_t f_affectpoint, c_affectpoint;
 
 	if (!sector->special) // nothing special, exit
 		return;
@@ -4581,16 +4587,19 @@ static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector)
 		return;
 	}
 
+	f_affectpoint = P_GetSpecialBottomZ(player->mo, sector, sector);
+	c_affectpoint = P_GetSpecialTopZ(player->mo, sector, sector);
+
 	// Only go further if on the ground
-	if ((sector->flags & SF_FLIPSPECIAL_FLOOR) && !(sector->flags & SF_FLIPSPECIAL_CEILING) && player->mo->z != sector->floorheight)
+	if ((sector->flags & SF_FLIPSPECIAL_FLOOR) && !(sector->flags & SF_FLIPSPECIAL_CEILING) && player->mo->z != f_affectpoint)
 		return;
 
-	if ((sector->flags & SF_FLIPSPECIAL_CEILING) && !(sector->flags & SF_FLIPSPECIAL_FLOOR) && player->mo->z + player->mo->height != sector->ceilingheight)
+	if ((sector->flags & SF_FLIPSPECIAL_CEILING) && !(sector->flags & SF_FLIPSPECIAL_FLOOR) && player->mo->z + player->mo->height != c_affectpoint)
 		return;
 
 	if ((sector->flags & SF_FLIPSPECIAL_BOTH)
-		&& player->mo->z != sector->floorheight
-		&& player->mo->z + player->mo->height != sector->ceilingheight)
+		&& player->mo->z != f_affectpoint
+		&& player->mo->z + player->mo->height != c_affectpoint)
 		return;
 
 	P_ProcessSpecialSector(player, sector, NULL);
@@ -4639,126 +4648,34 @@ void P_PlayerInSpecialSector(player_t *player)
 
 /** Animate planes, scroll walls, etc. and keeps track of level timelimit and exits if time is up.
   *
-  * \sa cv_timelimit, P_CheckPointLimit
+  * \sa P_CheckTimeLimit, P_CheckPointLimit
   */
 void P_UpdateSpecials(void)
 {
 	anim_t *anim;
-	INT32 i, k;
+	INT32 i;
 	INT32 pic;
 	size_t j;
 
 	levelflat_t *foundflats; // for flat animation
 
 	// LEVEL TIMER
-	// Exit if the timer is equal to or greater the timelimit, unless you are
-	// in overtime. In which case leveltime may stretch out beyond timelimitintics
-	// and overtime's status will be checked here each tick.
-	if (cv_timelimit.value && timelimitintics <= leveltime && (multiplayer || netgame)
-		&& G_RingSlingerGametype() && (gameaction != ga_completed))
-	{
-		boolean pexit = false;
-
-		//Tagmode round end but only on the tic before the
-		//XD_EXITLEVEL packet is recieved by all players.
-		if (G_TagGametype())
-		{
-			if (leveltime == (timelimitintics + 1))
-			{
-				for (i = 0; i < MAXPLAYERS; i++)
-				{
-					if (!playeringame[i] || players[i].spectator
-					 || (players[i].pflags & PF_TAGGED) || (players[i].pflags & PF_TAGIT))
-						continue;
-
-					CONS_Printf(M_GetText("%s recieved double points for surviving the round.\n"), player_names[i]);
-					P_AddPlayerScore(&players[i], players[i].score);
-				}
-			}
-
-			pexit = true;
-		}
-
-		//Optional tie-breaker for Match/CTF
-		else if (G_RingSlingerGametype() && cv_overtime.value)
-		{
-			INT32 playerarray[MAXPLAYERS];
-			INT32 tempplayer = 0;
-			INT32 spectators = 0;
-			INT32 playercount = 0;
-
-			//Figure out if we have enough participating players to care.
-			for (i = 0; i < MAXPLAYERS; i++)
-			{
-				if (playeringame[i] && players[i].spectator)
-					spectators++;
-			}
-
-			if ((D_NumPlayers() - spectators) > 1)
-			{
-				// Play the starpost sfx after the first second of overtime.
-				if (gamestate == GS_LEVEL && (leveltime == (timelimitintics + TICRATE)))
-					S_StartSound(NULL, sfx_strpst);
-
-				// Normal Match
-				if (!G_GametypeHasTeams())
-				{
-					//Store the nodes of participating players in an array.
-					for (i = 0; i < MAXPLAYERS; i++)
-					{
-						if (playeringame[i] && !players[i].spectator)
-						{
-							playerarray[playercount] = i;
-							playercount++;
-						}
-					}
-
-					//Sort 'em.
-					for (i = 1; i < playercount; i++)
-					{
-						for (k = i; k < playercount; k++)
-						{
-							if (players[playerarray[i-1]].score < players[playerarray[k]].score)
-							{
-								tempplayer = playerarray[i-1];
-								playerarray[i-1] = playerarray[k];
-								playerarray[k] = tempplayer;
-							}
-						}
-					}
-
-					//End the round if the top players aren't tied.
-					if (!(players[playerarray[0]].score == players[playerarray[1]].score))
-						pexit = true;
-				}
-				else
-				{
-					//In team match and CTF, determining a tie is much simpler. =P
-					if (!(redscore == bluescore))
-						pexit = true;
-				}
-			}
-			else
-				pexit = true;
-		}
-		else
-			pexit = true;
-
-		if (server && pexit)
-			SendNetXCmd(XD_EXITLEVEL, NULL, 0);
-	}
+	P_CheckTimeLimit();
 
 	// POINT LIMIT
 	P_CheckPointLimit();
 
+	// Dynamic slopeness
+	P_RunDynamicSlopes();
+
 	// ANIMATE TEXTURES
 	for (anim = anims; anim < lastanim; anim++)
 	{
-		for (i = anim->basepic; i < anim->basepic + anim->numpics; i++)
+		for (i = 0; i < anim->numpics; i++)
 		{
 			pic = anim->basepic + ((leveltime/anim->speed + i) % anim->numpics);
 			if (anim->istexture)
-				texturetranslation[i] = pic;
+				texturetranslation[anim->basepic+i] = pic;
 		}
 	}
 
@@ -4894,6 +4811,12 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
 	ffloor->topyoffs = &sec2->ceiling_yoffs;
 	ffloor->topangle = &sec2->ceilingpic_angle;
 
+#ifdef ESLOPE
+	// Add slopes
+	ffloor->t_slope = &sec2->c_slope;
+	ffloor->b_slope = &sec2->f_slope;
+#endif
+
 	if ((flags & FF_SOLID) && (master->flags & ML_EFFECT1)) // Block player only
 		flags &= ~FF_BLOCKOTHERS;
 
@@ -5327,6 +5250,7 @@ void T_LaserFlash(laserthink_t *flash)
 	sector_t *sourcesec;
 	ffloor_t *ffloor = flash->ffloor;
 	sector_t *sector = flash->sector;
+	fixed_t top, bottom;
 
 	if (!ffloor || !(ffloor->flags & FF_EXISTS))
 		return;
@@ -5350,8 +5274,11 @@ void T_LaserFlash(laserthink_t *flash)
 			&& thing->flags & MF_BOSS)
 			continue; // Don't hurt bosses
 
-		if (thing->z >= sourcesec->ceilingheight
-		|| thing->z + thing->height <= sourcesec->floorheight)
+		top = P_GetSpecialTopZ(thing, sourcesec, sector);
+		bottom = P_GetSpecialBottomZ(thing, sourcesec, sector);
+
+		if (thing->z >= top
+		|| thing->z + thing->height <= bottom)
 			continue;
 
 		if (thing->flags & MF_SHOOTABLE)
@@ -6430,6 +6357,14 @@ void P_SpawnSpecials(INT32 fromnetsave)
 					sectors[s].midmap = lines[i].frontsector->midmap;
 				break;
 
+#ifdef ESLOPE // Slope copy specials. Handled here for sanity.
+			case 720:
+			case 721:
+			case 722:
+				P_CopySectorSlope(&lines[i]);
+				break;
+#endif
+
 			default:
 				break;
 		}
@@ -6634,6 +6569,8 @@ void T_Scroll(scroll_t *s)
 						if (thing->eflags & MFE_PUSHED) // Already pushed this tic by an exclusive pusher.
 							continue;
 
+						height = P_GetSpecialBottomZ(thing, sec, psec);
+
 						if (!(thing->flags & MF_NOCLIP)) // Thing must be clipped
 						if (!(thing->flags & MF_NOGRAVITY || thing->z+thing->height != height)) // Thing must a) be non-floating and have z+height == height
 						{
@@ -6654,6 +6591,8 @@ void T_Scroll(scroll_t *s)
 					if (thing->eflags & MFE_PUSHED)
 						continue;
 
+					height = P_GetSpecialBottomZ(thing, sec, sec);
+
 					if (!(thing->flags & MF_NOCLIP) &&
 						(!(thing->flags & MF_NOGRAVITY || thing->z > height)))
 					{
@@ -6693,6 +6632,8 @@ void T_Scroll(scroll_t *s)
 						if (thing->eflags & MFE_PUSHED)
 							continue;
 
+						height = P_GetSpecialTopZ(thing, sec, psec);
+
 						if (!(thing->flags & MF_NOCLIP)) // Thing must be clipped
 						if (!(thing->flags & MF_NOGRAVITY || thing->z != height))// Thing must a) be non-floating and have z == height
 						{
@@ -6713,6 +6654,8 @@ void T_Scroll(scroll_t *s)
 					if (thing->eflags & MFE_PUSHED)
 						continue;
 
+					height = P_GetSpecialTopZ(thing, sec, sec);
+
 					if (!(thing->flags & MF_NOCLIP) &&
 						(!(thing->flags & MF_NOGRAVITY || thing->z+thing->height < height)))
 					{
@@ -7006,7 +6949,7 @@ static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32
   */
 void T_Friction(friction_t *f)
 {
-	sector_t *sec;
+	sector_t *sec, *referrer = NULL;
 	mobj_t *thing;
 	msecnode_t *node;
 
@@ -7015,7 +6958,7 @@ void T_Friction(friction_t *f)
 	// Make sure the sector type hasn't changed
 	if (f->roverfriction)
 	{
-		sector_t *referrer = sectors + f->referrer;
+		referrer = sectors + f->referrer;
 
 		if (!(GETSECSPECIAL(referrer->special, 3) == 1
 			|| GETSECSPECIAL(referrer->special, 3) == 3))
@@ -7047,9 +6990,7 @@ void T_Friction(friction_t *f)
 		{
 			if (f->roverfriction)
 			{
-				sector_t *referrer = &sectors[f->referrer];
-
-				if (thing->floorz != referrer->ceilingheight)
+				if (thing->floorz != P_GetSpecialTopZ(thing, referrer, sec))
 				{
 					node = node->m_snext;
 					continue;
@@ -7062,7 +7003,7 @@ void T_Friction(friction_t *f)
 					thing->movefactor = f->movefactor;
 				}
 			}
-			else if (sec->floorheight == thing->floorz && (thing->friction == ORIG_FRICTION // normal friction?
+			else if (P_GetSpecialBottomZ(thing, sec, sec) == thing->floorz && (thing->friction == ORIG_FRICTION // normal friction?
 				|| f->friction < thing->friction))
 			{
 				thing->friction = f->friction;
@@ -7336,7 +7277,7 @@ static inline boolean PIT_PushThing(mobj_t *thing)
   */
 void T_Pusher(pusher_t *p)
 {
-	sector_t *sec;
+	sector_t *sec, *referrer = NULL;
 	mobj_t *thing;
 	msecnode_t *node;
 	INT32 xspeed = 0,yspeed = 0;
@@ -7345,7 +7286,6 @@ void T_Pusher(pusher_t *p)
 	//INT32 ht = 0;
 	boolean inFOF;
 	boolean touching;
-	boolean foundfloor = false;
 	boolean moved;
 
 	xspeed = yspeed = 0;
@@ -7357,19 +7297,16 @@ void T_Pusher(pusher_t *p)
 
 	if (p->roverpusher)
 	{
-		sector_t *referrer = &sectors[p->referrer];
+		referrer = &sectors[p->referrer];
 
-		if (GETSECSPECIAL(referrer->special, 3) == 2
-			|| GETSECSPECIAL(referrer->special, 3) == 3)
-			foundfloor = true;
+		if (!(GETSECSPECIAL(referrer->special, 3) == 2
+			|| GETSECSPECIAL(referrer->special, 3) == 3))
+			return;
 	}
 	else if (!(GETSECSPECIAL(sec->special, 3) == 2
 			|| GETSECSPECIAL(sec->special, 3) == 3))
 		return;
 
-	if (p->roverpusher && foundfloor == false) // Not even a 3d floor has the PUSH_MASK.
-		return;
-
 	// For constant pushers (wind/current) there are 3 situations:
 	//
 	// 1) Affected Thing is above the floor.
@@ -7401,10 +7338,10 @@ void T_Pusher(pusher_t *p)
 		tmbbox[BOXRIGHT]  = p->x + radius;
 		tmbbox[BOXLEFT]   = p->x - radius;
 
-		xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
-		xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
-		yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
-		yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
+		xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
+		xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
+		yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
+		yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
 		for (bx = xl; bx <= xh; bx++)
 			for (by = yl; by <= yh; by++)
 				P_BlockThingsIterator(bx,by, PIT_PushThing);
@@ -7444,41 +7381,38 @@ void T_Pusher(pusher_t *p)
 		// Find the area that the 'thing' is in
 		if (p->roverpusher)
 		{
-			sector_t *referrer = &sectors[p->referrer];
-			INT32 special;
+			fixed_t top, bottom;
 
-			special = GETSECSPECIAL(referrer->special, 3);
-
-			if (!(special == 2 || special == 3))
-				return;
+			top = P_GetSpecialTopZ(thing, referrer, sec);
+			bottom = P_GetSpecialBottomZ(thing, referrer, sec);
 
 			if (thing->eflags & MFE_VERTICALFLIP)
 			{
-				if (referrer->floorheight > thing->z + thing->height
-					|| referrer->ceilingheight < (thing->z + (thing->height >> 1)))
+				if (bottom > thing->z + thing->height
+					|| top < (thing->z + (thing->height >> 1)))
 					continue;
 
-				if (thing->z < referrer->floorheight)
+				if (thing->z < bottom)
 					touching = true;
 
-				if (thing->z + (thing->height >> 1) > referrer->floorheight)
+				if (thing->z + (thing->height >> 1) > bottom)
 					inFOF = true;
 
 			}
 			else
 			{
-				if (referrer->ceilingheight < thing->z || referrer->floorheight > (thing->z + (thing->height >> 1)))
+				if (top < thing->z || referrer->floorheight > (thing->z + (thing->height >> 1)))
 					continue;
-				if (thing->z + thing->height > referrer->ceilingheight)
+				if (thing->z + thing->height > top)
 					touching = true;
 
-				if (thing->z + (thing->height >> 1) < referrer->ceilingheight)
+				if (thing->z + (thing->height >> 1) < top)
 					inFOF = true;
 			}
 		}
 		else // Treat the entire sector as one big FOF
 		{
-			if (thing->z == thing->subsector->sector->floorheight)
+			if (thing->z == P_GetSpecialBottomZ(thing, sec, sec))
 				touching = true;
 			else if (p->type != p_current)
 				inFOF = true;
diff --git a/src/p_user.c b/src/p_user.c
index d60de97a871ed16c8a9b3d2110ad3a452367ed9f..88bbca52332c235b6540ebb4cd2499b6d9d333b3 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -29,6 +29,7 @@
 #include "m_random.h"
 #include "m_misc.h"
 #include "i_video.h"
+#include "p_slopes.h"
 #include "p_spec.h"
 #include "r_splats.h"
 #include "z_zone.h"
@@ -51,9 +52,6 @@
 #include "hardware/hw_main.h"
 #endif
 
-// Index of the special effects (INVUL inverse) map.
-#define INVERSECOLORMAP 32
-
 #if 0
 static void P_NukeAllPlayers(player_t *player);
 #endif
@@ -1212,7 +1210,7 @@ boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec)
 	if (mo->eflags & MFE_VERTICALFLIP)
 	{
 		// Detect if the player is on the ceiling.
-		if (mo->z+mo->height >= sec->ceilingheight)
+		if (mo->z+mo->height >= P_GetSpecialTopZ(mo, sec, sec))
 			return true;
 		// Otherwise, detect if the player is on the bottom of a FOF.
 		else
@@ -1236,7 +1234,7 @@ boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec)
 					continue;
 
 				// Actually check if the player is on the suitable FOF.
-				if (mo->z+mo->height == *rover->bottomheight)
+				if (mo->z+mo->height == P_GetSpecialBottomZ(mo, sectors + rover->secnum, sec))
 					return true;
 			}
 		}
@@ -1245,7 +1243,7 @@ boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec)
 	else
 	{
 		// Detect if the player is on the floor.
-		if (mo->z <= sec->floorheight)
+		if (mo->z <= P_GetSpecialBottomZ(mo, sec, sec))
 			return true;
 		// Otherwise, detect if the player is on the top of a FOF.
 		else
@@ -1269,7 +1267,7 @@ boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec)
 					continue;
 
 				// Actually check if the player is on the suitable FOF.
-				if (mo->z == *rover->topheight)
+				if (mo->z == P_GetSpecialTopZ(mo, sectors + rover->secnum, sec))
 					return true;
 			}
 		}
@@ -1597,7 +1595,7 @@ void P_DoPlayerExit(player_t *player)
 	{
 		player->climbing = 0;
 		player->pflags |= PF_JUMPED;
-		P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+		P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 	}
 	player->powers[pw_underwater] = 0;
 	player->powers[pw_spacetime] = 0;
@@ -1790,6 +1788,9 @@ static void P_CheckBouncySectors(player_t *player)
 	fixed_t oldx;
 	fixed_t oldy;
 	fixed_t oldz;
+#ifdef ESLOPE
+	vector3_t momentum;
+#endif
 
 	oldx = player->mo->x;
 	oldy = player->mo->y;
@@ -1810,16 +1811,21 @@ static void P_CheckBouncySectors(player_t *player)
 		{
 			ffloor_t *rover;
 			boolean top = true;
+			fixed_t topheight, bottomheight;
 
 			for (rover = node->m_sector->ffloors; rover; rover = rover->next)
 			{
-				if (player->mo->z > *rover->topheight)
+				topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
+				bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL);
+
+				if (player->mo->z > topheight)
 					continue;
 
-				if (player->mo->z + player->mo->height < *rover->bottomheight)
+				if (player->mo->z + player->mo->height < bottomheight)
 					continue;
 
-				if (oldz < *rover->topheight && oldz > *rover->bottomheight)
+				if (oldz < P_GetFOFTopZ(player->mo, node->m_sector, rover, oldx, oldy, NULL)
+						&& oldz + player->mo->height > P_GetFOFBottomZ(player->mo, node->m_sector, rover, oldx, oldy, NULL))
 					top = false;
 
 				if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 15)
@@ -1834,7 +1840,29 @@ static void P_CheckBouncySectors(player_t *player)
 					{
 						fixed_t newmom;
 
+#ifdef ESLOPE
+						pslope_t *slope;
+						if (abs(oldz - topheight) < abs(oldz + player->mo->height - bottomheight)) { // Hit top
+							slope = *rover->t_slope;
+						} else { // Hit bottom
+							slope = *rover->b_slope;
+						}
+
+						momentum.x = player->mo->momx;
+						momentum.y = player->mo->momy;
+						momentum.z = player->mo->momz*2;
+
+						if (slope) {
+							// Reverse quantizing might could use its own function later
+							slope->zangle = ANGLE_MAX-slope->zangle;
+							P_QuantizeMomentumToSlope(&momentum, slope);
+							slope->zangle = ANGLE_MAX-slope->zangle;
+						}
+
+						newmom = momentum.z = -FixedMul(momentum.z,linedist)/2;
+#else
 						newmom = -FixedMul(player->mo->momz,linedist);
+#endif
 
 						if (abs(newmom) < (linedist*2))
 						{
@@ -1857,7 +1885,18 @@ static void P_CheckBouncySectors(player_t *player)
 						else if (newmom < -P_GetPlayerHeight(player)/2)
 							newmom = -P_GetPlayerHeight(player)/2;
 
+#ifdef ESLOPE
+						momentum.z = newmom*2;
+
+						if (slope)
+							P_QuantizeMomentumToSlope(&momentum, slope);
+
+						player->mo->momx = momentum.x;
+						player->mo->momy = momentum.y;
+						player->mo->momz = momentum.z/2;
+#else
 						player->mo->momz = newmom;
+#endif
 
 						if (player->pflags & PF_SPINNING)
 						{
@@ -2073,30 +2112,7 @@ static void P_CheckInvincibilityTimer(player_t *player)
 		player->mo->color = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1)));
 	else if (leveltime % (TICRATE/7) == 0)
 	{
-		fixed_t destx, desty;
-		mobj_t *sparkle;
-
-		if (!splitscreen && rendermode != render_soft)
-		{
-			angle_t viewingangle;
-
-			if (players[displayplayer].awayviewtics)
-				viewingangle = R_PointToAngle2(player->mo->x, player->mo->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y);
-			else if (!camera.chase && players[displayplayer].mo)
-				viewingangle = R_PointToAngle2(player->mo->x, player->mo->y, players[displayplayer].mo->x, players[displayplayer].mo->y);
-			else
-				viewingangle = R_PointToAngle2(player->mo->x, player->mo->y, camera.x, camera.y);
-
-			destx = player->mo->x + P_ReturnThrustX(player->mo, viewingangle, FixedMul(FRACUNIT, player->mo->scale));
-			desty = player->mo->y + P_ReturnThrustY(player->mo, viewingangle, FixedMul(FRACUNIT, player->mo->scale));
-		}
-		else
-		{
-			destx = player->mo->x;
-			desty = player->mo->y;
-		}
-
-		sparkle = P_SpawnMobj(destx, desty, player->mo->z, MT_IVSP);
+		mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_IVSP);
 		sparkle->destscale = player->mo->scale;
 		P_SetScale(sparkle, player->mo->scale);
 	}
@@ -2271,14 +2287,27 @@ static void P_DoClimbing(player_t *player)
 		boolean thrust;
 		boolean boostup;
 		boolean skyclimber;
+		fixed_t floorheight, ceilingheight; // ESLOPE
 		thrust = false;
 		floorclimb = false;
 		boostup = false;
 		skyclimber = false;
 
+#ifdef ESLOPE
+		floorheight = glidesector->sector->f_slope ? P_GetZAt(glidesector->sector->f_slope, player->mo->x, player->mo->y)
+		                                           : glidesector->sector->floorheight;
+		ceilingheight = glidesector->sector->c_slope ? P_GetZAt(glidesector->sector->c_slope, player->mo->x, player->mo->y)
+		                                             : glidesector->sector->ceilingheight;
+#else
+		floorheight = glidesector->sector->floorheight;
+		ceilingheight = glidesector->sector->ceilingheight;
+#endif
+
 		if (glidesector->sector->ffloors)
 		{
 			ffloor_t *rover;
+			fixed_t topheight, bottomheight; // ESLOPE
+
 			for (rover = glidesector->sector->ffloors; rover; rover = rover->next)
 			{
 				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
@@ -2286,13 +2315,21 @@ static void P_DoClimbing(player_t *player)
 
 				floorclimb = true;
 
+#ifdef ESLOPE
+				bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight;
+				topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight;
+#else
+				bottomheight = *rover->bottomheight;
+				topheight = *rover->topheight;
+#endif
+
 				// Only supports rovers that are moving like an 'elevator', not just the top or bottom.
 				if (rover->master->frontsector->floorspeed && rover->master->frontsector->ceilspeed == 42)
 				{
-					if ((!(player->mo->eflags & MFE_VERTICALFLIP) && (*rover->bottomheight < player->mo->z+player->mo->height)
-						&& (*rover->topheight >= player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale)))
-					|| ((player->mo->eflags & MFE_VERTICALFLIP) && (*rover->topheight > player->mo->z)
-						&& (*rover->bottomheight <= player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale))))
+					if ((!(player->mo->eflags & MFE_VERTICALFLIP) && (bottomheight < player->mo->z+player->mo->height)
+						&& (topheight >= player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale)))
+					|| ((player->mo->eflags & MFE_VERTICALFLIP) && (topheight > player->mo->z)
+						&& (bottomheight <= player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale))))
 					{
 						if (cmd->forwardmove != 0)
 							player->mo->momz += rover->master->frontsector->floorspeed;
@@ -2308,8 +2345,9 @@ static void P_DoClimbing(player_t *player)
 				if (player->mo->eflags & MFE_VERTICALFLIP)
 				{
 					// Trying to climb down past the bottom of the FOF
-					if ((*rover->topheight >= player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) >= *rover->topheight))
+					if ((topheight >= player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) >= topheight))
 					{
+						fixed_t bottomheight2;
 						ffloor_t *roverbelow;
 						boolean foundfof = false;
 						floorclimb = true;
@@ -2324,7 +2362,13 @@ static void P_DoClimbing(player_t *player)
 							if (roverbelow == rover)
 								continue;
 
-							if (*roverbelow->bottomheight < *rover->topheight + FixedMul(16*FRACUNIT, player->mo->scale))
+#ifdef ESLOPE
+							bottomheight2 = *roverbelow->b_slope ? P_GetZAt(*roverbelow->b_slope, player->mo->x, player->mo->y) : *roverbelow->bottomheight;
+#else
+							bottomheight2 = *roverbelow->bottomheight;
+#endif
+
+							if (bottomheight2 < topheight + FixedMul(16*FRACUNIT, player->mo->scale))
 								foundfof = true;
 						}
 
@@ -2333,7 +2377,7 @@ static void P_DoClimbing(player_t *player)
 					}
 
 					// Below the FOF
-					if (*rover->topheight <= player->mo->z)
+					if (topheight <= player->mo->z)
 					{
 						floorclimb = false;
 						boostup = false;
@@ -2341,7 +2385,7 @@ static void P_DoClimbing(player_t *player)
 					}
 
 					// Above the FOF
-					if (*rover->bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale))
+					if (bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale))
 					{
 						floorclimb = false;
 						thrust = true;
@@ -2351,8 +2395,9 @@ static void P_DoClimbing(player_t *player)
 				else
 				{
 					// Trying to climb down past the bottom of a FOF
-					if ((*rover->bottomheight <= player->mo->z) && ((player->mo->z + player->mo->momz) <= *rover->bottomheight))
+					if ((bottomheight <= player->mo->z) && ((player->mo->z + player->mo->momz) <= bottomheight))
 					{
+						fixed_t topheight2;
 						ffloor_t *roverbelow;
 						boolean foundfof = false;
 						floorclimb = true;
@@ -2367,7 +2412,13 @@ static void P_DoClimbing(player_t *player)
 							if (roverbelow == rover)
 								continue;
 
-							if (*roverbelow->topheight > *rover->bottomheight - FixedMul(16*FRACUNIT, player->mo->scale))
+#ifdef ESLOPE
+							topheight2 = *roverbelow->t_slope ? P_GetZAt(*roverbelow->t_slope, player->mo->x, player->mo->y) : *roverbelow->topheight;
+#else
+							topheight2 = *roverbelow->topheight;
+#endif
+
+							if (topheight2 > bottomheight - FixedMul(16*FRACUNIT, player->mo->scale))
 								foundfof = true;
 						}
 
@@ -2376,7 +2427,7 @@ static void P_DoClimbing(player_t *player)
 					}
 
 					// Below the FOF
-					if (*rover->bottomheight >= player->mo->z + player->mo->height)
+					if (bottomheight >= player->mo->z + player->mo->height)
 					{
 						floorclimb = false;
 						boostup = false;
@@ -2384,7 +2435,7 @@ static void P_DoClimbing(player_t *player)
 					}
 
 					// Above the FOF
-					if (*rover->topheight < player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale))
+					if (topheight < player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale))
 					{
 						floorclimb = false;
 						thrust = true;
@@ -2405,7 +2456,7 @@ static void P_DoClimbing(player_t *player)
 		if (player->mo->eflags & MFE_VERTICALFLIP)
 		{
 			// Trying to climb down past the upper texture area
-			if ((glidesector->sector->floorheight >= player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) >= glidesector->sector->floorheight))
+			if ((floorheight >= player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) >= floorheight))
 			{
 				boolean foundfof = false;
 				floorclimb = true;
@@ -2413,13 +2464,20 @@ static void P_DoClimbing(player_t *player)
 				// Is there a FOF directly below that we can move onto?
 				if (glidesector->sector->ffloors)
 				{
+					fixed_t bottomheight;
 					ffloor_t *rover;
 					for (rover = glidesector->sector->ffloors; rover; rover = rover->next)
 					{
 						if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
 							continue;
 
-						if (*rover->bottomheight < glidesector->sector->floorheight + FixedMul(16*FRACUNIT, player->mo->scale))
+#ifdef ESLOPE
+						bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight;
+#else
+						bottomheight = *rover->bottomheight;
+#endif
+
+						if (bottomheight < floorheight + FixedMul(16*FRACUNIT, player->mo->scale))
 						{
 							foundfof = true;
 							break;
@@ -2432,8 +2490,8 @@ static void P_DoClimbing(player_t *player)
 			}
 
 			// Reached the top of the lower texture area
-			if (!floorclimb && glidesector->sector->ceilingheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale)
-				&& (glidesector->sector->ceilingpic == skyflatnum || glidesector->sector->floorheight < (player->mo->z - FixedMul(8*FRACUNIT, player->mo->scale))))
+			if (!floorclimb && ceilingheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale)
+				&& (glidesector->sector->ceilingpic == skyflatnum || floorheight < (player->mo->z - FixedMul(8*FRACUNIT, player->mo->scale))))
 			{
 				thrust = true;
 				boostup = true;
@@ -2443,7 +2501,7 @@ static void P_DoClimbing(player_t *player)
 		else
 		{
 			// Trying to climb down past the upper texture area
-			if ((glidesector->sector->ceilingheight <= player->mo->z) && ((player->mo->z + player->mo->momz) <= glidesector->sector->ceilingheight))
+			if ((ceilingheight <= player->mo->z) && ((player->mo->z + player->mo->momz) <= ceilingheight))
 			{
 				boolean foundfof = false;
 				floorclimb = true;
@@ -2457,7 +2515,7 @@ static void P_DoClimbing(player_t *player)
 						if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP))
 							continue;
 
-						if (*rover->topheight > glidesector->sector->ceilingheight - FixedMul(16*FRACUNIT, player->mo->scale))
+						if (*rover->topheight > ceilingheight - FixedMul(16*FRACUNIT, player->mo->scale))
 						{
 							foundfof = true;
 							break;
@@ -2470,7 +2528,7 @@ static void P_DoClimbing(player_t *player)
 			}
 
 			// Allow climbing from a FOF or lower texture onto the upper texture and vice versa.
-			if (player->mo->z > glidesector->sector->ceilingheight - FixedMul(16*FRACUNIT, player->mo->scale))
+			if (player->mo->z > ceilingheight - FixedMul(16*FRACUNIT, player->mo->scale))
 			{
 				floorclimb = true;
 				thrust = false;
@@ -2478,8 +2536,8 @@ static void P_DoClimbing(player_t *player)
 			}
 
 			// Reached the top of the lower texture area
-			if (!floorclimb && glidesector->sector->floorheight < player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale)
-				&& (glidesector->sector->ceilingpic == skyflatnum || glidesector->sector->ceilingheight > (player->mo->z + player->mo->height + FixedMul(8*FRACUNIT, player->mo->scale))))
+			if (!floorclimb && floorheight < player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale)
+				&& (glidesector->sector->ceilingpic == skyflatnum || ceilingheight > (player->mo->z + player->mo->height + FixedMul(8*FRACUNIT, player->mo->scale))))
 			{
 				thrust = true;
 				boostup = true;
@@ -2488,14 +2546,14 @@ static void P_DoClimbing(player_t *player)
 		}
 
 		// Trying to climb on the sky
-		if ((glidesector->sector->ceilingheight < player->mo->z) && glidesector->sector->ceilingpic == skyflatnum)
+		if ((ceilingheight < player->mo->z) && glidesector->sector->ceilingpic == skyflatnum)
 		{
 			skyclimber = true;
 		}
 
 		// Climbing on the lower texture area?
-		if ((!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale) < glidesector->sector->floorheight)
-			|| ((player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z + player->mo->height <= glidesector->sector->floorheight))
+		if ((!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale) < floorheight)
+			|| ((player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z + player->mo->height <= floorheight))
 		{
 			floorclimb = true;
 
@@ -2511,8 +2569,8 @@ static void P_DoClimbing(player_t *player)
 			}
 		}
 		// Climbing on the upper texture area?
-		else if ((!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z >= glidesector->sector->ceilingheight)
-			|| ((player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale) > glidesector->sector->ceilingheight))
+		else if ((!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z >= ceilingheight)
+			|| ((player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale) > ceilingheight))
 		{
 			floorclimb = true;
 
@@ -2605,21 +2663,21 @@ static void P_DoClimbing(player_t *player)
 
 			player->climbing = 0;
 			player->pflags |= PF_JUMPED;
-			P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+			P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 		}
 
 		if (skyclimber)
 		{
 			player->climbing = 0;
 			player->pflags |= PF_JUMPED;
-			P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+			P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 		}
 	}
 	else
 	{
 		player->climbing = 0;
 		player->pflags |= PF_JUMPED;
-		P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+		P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 	}
 
 	if (cmd->sidemove != 0 || cmd->forwardmove != 0)
@@ -2637,7 +2695,7 @@ static void P_DoClimbing(player_t *player)
 	{
 		player->climbing = 0;
 		player->pflags |= PF_JUMPED;
-		P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+		P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 		P_SetObjectMomZ(player->mo, 4*FRACUNIT, false);
 		P_InstaThrust(player->mo, player->mo->angle, FixedMul(-4*FRACUNIT, player->mo->scale));
 	}
@@ -2648,7 +2706,7 @@ static void P_DoClimbing(player_t *player)
 		localangle2 = player->mo->angle;
 
 	if (player->climbing == 0)
-		P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+		P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 
 	if (player->climbing && P_IsObjectOnGround(player->mo))
 	{
@@ -2953,10 +3011,12 @@ static void P_DoTeeter(player_t *player)
 	{
 		INT32 bx, by, xl, xh, yl, yh;
 
-		yh = (player->mo->y + player->mo->radius - bmaporgy)>>MAPBLOCKSHIFT;
-		yl = (player->mo->y - player->mo->radius - bmaporgy)>>MAPBLOCKSHIFT;
-		xh = (player->mo->x + player->mo->radius - bmaporgx)>>MAPBLOCKSHIFT;
-		xl = (player->mo->x - player->mo->radius - bmaporgx)>>MAPBLOCKSHIFT;
+		yh = (unsigned)(player->mo->y + player->mo->radius - bmaporgy)>>MAPBLOCKSHIFT;
+		yl = (unsigned)(player->mo->y - player->mo->radius - bmaporgy)>>MAPBLOCKSHIFT;
+		xh = (unsigned)(player->mo->x + player->mo->radius - bmaporgx)>>MAPBLOCKSHIFT;
+		xl = (unsigned)(player->mo->x - player->mo->radius - bmaporgx)>>MAPBLOCKSHIFT;
+
+		BMBOUNDFIX(xl, xh, yl, yh);
 
 	// Polyobjects
 #ifdef POLYOBJECTS
@@ -3076,10 +3136,10 @@ teeterdone:
 	}
 	if (teeter)
 	{
-		if (player->panim == PA_IDLE && player->mo->state-states != S_PLAY_EDGE)
+		if (player->panim == PA_IDLE)
 			P_SetPlayerMobjState(player->mo, S_PLAY_EDGE);
 	}
-	else if (checkedforteeter && (player->mo->state-states == S_PLAY_EDGE || player->mo->state-states == S_PLAY_SUPER_EDGE))
+	else if (checkedforteeter && player->panim == PA_EDGE)
 		P_SetPlayerMobjState(player->mo, S_PLAY_STND);
 }
 
@@ -3434,14 +3494,36 @@ static void P_DoSuperStuff(player_t *player)
 
 			if (player->mo->health > 0)
 			{
-				if ((player->pflags & PF_JUMPED) || (player->pflags & PF_SPINNING))
+				if (player->pflags & PF_JUMPED)
+					P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
+				else if (player->pflags & PF_SPINNING && player->mo->state-states != S_PLAY_DASH)
 					P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
-				else if (player->panim == PA_RUN)
-					P_SetPlayerMobjState(player->mo, S_PLAY_RUN);
-				else if (player->panim == PA_WALK)
-					P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
-				else
+				else switch (player->mo->state-states)
+				{
+				default:
 					P_SetPlayerMobjState(player->mo, S_PLAY_STND);
+					break;
+				case S_PLAY_DASH:
+					break;
+				case S_PLAY_SUPER_WALK:
+					P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
+					break;
+				case S_PLAY_SUPER_RUN:
+					P_SetPlayerMobjState(player->mo, S_PLAY_RUN);
+					break;
+				case S_PLAY_SUPER_PAIN:
+					P_SetPlayerMobjState(player->mo, S_PLAY_PAIN);
+					break;
+				case S_PLAY_SUPER_SPRING:
+					P_SetPlayerMobjState(player->mo, S_PLAY_SPRING);
+					break;
+				case S_PLAY_SUPER_FALL:
+					P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
+					break;
+				case S_PLAY_SUPER_RIDE:
+					P_SetPlayerMobjState(player->mo, S_PLAY_RIDE);
+					break;
+				}
 
 				if (!player->exiting)
 				{
@@ -3628,11 +3710,22 @@ void P_DoJump(player_t *player, boolean soundandstate)
 
 	// set just an eensy above the ground
 	if (player->mo->eflags & MFE_VERTICALFLIP)
+	{
 		player->mo->z--;
+		if (player->mo->pmomz < 0)
+			player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump.
+		else
+			player->mo->pmomz = 0;
+	}
 	else
+	{
 		player->mo->z++;
-
-	player->mo->z += player->mo->pmomz; // Solves problem of 'hitting around again after jumping on a moving platform'.
+		if (player->mo->pmomz > 0)
+			player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump.
+		else
+			player->mo->pmomz = 0;
+	}
+	player->mo->eflags &= ~MFE_APPLYPMOMZ;
 
 	player->pflags |= PF_JUMPED;
 
@@ -3642,9 +3735,9 @@ void P_DoJump(player_t *player, boolean soundandstate)
 			S_StartSound(player->mo, sfx_jump); // Play jump sound!
 
 		if (!(player->charability2 == CA2_SPINDASH))
-			P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
+			P_SetPlayerMobjState(player->mo, S_PLAY_SPRING);
 		else
-			P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+			P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 	}
 }
 
@@ -3670,14 +3763,18 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
 	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))
+		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 || 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 = FixedMul(FRACUNIT, player->mo->scale);
 			player->dashtime = 0;
-			P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+			P_SetPlayerMobjState(player->mo, S_PLAY_DASH);
 			player->pflags |= PF_USEDOWN;
 		}
 		else if ((cmd->buttons & BT_USE) && (player->pflags & PF_STARTDASH))
@@ -3690,16 +3787,23 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
 					S_StartSound(player->mo, sfx_spndsh); // Make the rev sound!
 
 				// Now spawn the color thok circle.
-				P_SpawnSpinMobj(player, player->revitem);
-				if (demorecording)
-					G_GhostAddRev();
+				if (player->mo->sprite2 != SPR2_DASH)
+				{
+					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) && !(player->pflags & PF_USEDOWN) && !(player->pflags & PF_SPINNING))
+			&& !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<<FRACBITS, player->mo->scale)
+#ifdef ESLOPE
+			|| (player->mo->standingslope && 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);
@@ -3711,7 +3815,11 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
 
 	// Rolling normally
 	if (onground && player->pflags & PF_SPINNING && !(player->pflags & PF_STARTDASH)
-		&& player->speed < FixedMul(5*FRACUNIT,player->mo->scale))
+		&& player->speed < FixedMul(5*FRACUNIT,player->mo->scale)
+#ifdef ESLOPE
+			&& (!player->mo->standingslope || abs(player->mo->standingslope->zdelta) < FRACUNIT/2)
+#endif
+			)
 	{
 		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));
@@ -3734,6 +3842,7 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
 		player->pflags &= ~PF_STARTDASH;
 		if (!((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE))
 		{
+			P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
 			P_InstaThrust(player->mo, player->mo->angle, player->dashspeed); // catapult forward ho!!
 			if (!player->spectator)
 				S_StartSound(player->mo, sfx_zoom);
@@ -3741,7 +3850,9 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
 		player->dashspeed = 0;
 	}
 
-	if (onground && (player->pflags & PF_SPINNING) && !(player->panim == PA_ROLL))
+	if (onground && player->pflags & PF_STARTDASH && player->mo->state-states != S_PLAY_DASH)
+		P_SetPlayerMobjState(player->mo, S_PLAY_DASH);
+	else if (onground && player->pflags & PF_SPINNING && !(player->panim == PA_ROLL))
 		P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
 }
 
@@ -4415,12 +4526,16 @@ static void P_3dMovement(player_t *player)
 	angle_t dangle; // replaces old quadrants bits
 	fixed_t normalspd = FixedMul(player->normalspeed, player->mo->scale);
 	boolean analogmove = false;
-#ifndef OLD_MOVEMENT_CODE
 	fixed_t oldMagnitude, newMagnitude;
+#ifdef ESLOPE
+	vector3_t totalthrust;
+
+	totalthrust.x = totalthrust.y = 0; // I forget if this is needed
+	totalthrust.z = FRACUNIT*P_MobjFlip(player->mo)/3; // A bit of extra push-back on slopes
+#endif // ESLOPE
 
 	// Get the old momentum; this will be needed at the end of the function! -SH
 	oldMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
-#endif
 
 	analogmove = P_AnalogMove(player);
 
@@ -4597,17 +4712,10 @@ static void P_3dMovement(player_t *player)
 		}
 
 		movepushforward = FixedMul(movepushforward, player->mo->scale);
-#ifdef OLD_MOVEMENT_CODE
-		if (player->speed < topspeed && mforward && cmd->forwardmove > 0) // Sonic's Speed
-			P_Thrust(player->mo, movepushangle, movepushforward);
-		else if (mforward && cmd->forwardmove < 0)
-			P_Thrust(player->mo, movepushangle, movepushforward);
-		else if (player->speed < topspeed && mbackward && cmd->forwardmove < 0)
-			P_Thrust(player->mo, movepushangle, movepushforward);
-		else if (mbackward && cmd->forwardmove > 0)
-			P_Thrust(player->mo, movepushangle, movepushforward);
-		else if (!mforward && !mbackward)
-			P_Thrust(player->mo, movepushangle, movepushforward);
+
+#ifdef ESLOPE
+		totalthrust.x += P_ReturnThrustX(player->mo, movepushangle, movepushforward);
+		totalthrust.y += P_ReturnThrustY(player->mo, movepushangle, movepushforward);
 #else
 		P_Thrust(player->mo, movepushangle, movepushforward);
 #endif
@@ -4626,33 +4734,12 @@ static void P_3dMovement(player_t *player)
 		if (!(player->pflags & PF_GLIDING || player->exiting || P_PlayerInPain(player)))
 		{
 			angle_t controldirection;
-#ifdef OLD_MOVEMENT_CODE
-			angle_t controlplayerdirection;
-			boolean cforward; // controls pointing forward from the player
-			boolean cbackward; // controls pointing backward from the player
-			angle_t dangle;
 
-			cforward = cbackward = false;
-#endif
 			// Calculate the angle at which the controls are pointing
 			// to figure out the proper mforward and mbackward.
 			// (Why was it so complicated before? ~Red)
 			controldirection = R_PointToAngle2(0, 0, cmd->forwardmove*FRACUNIT, -cmd->sidemove*FRACUNIT)+movepushangle;
 
-#ifdef OLD_MOVEMENT_CODE
-			controlplayerdirection = player->mo->angle;
-
-			dangle = controldirection - controlplayerdirection;
-
-			if (dangle > ANGLE_180) //flip to keep to one side
-				dangle = InvAngle(dangle);
-
-			if (dangle > ANGLE_90)
-				cbackward = true; // Controls pointing backwards from player
-			else
-				cforward = true; // Controls pointing in player's general direction
-#endif
-
 			movepushforward = max(abs(cmd->sidemove), abs(cmd->forwardmove)) * (thrustfactor * acceleration);
 
 			// allow very small movement while in air for gameplay
@@ -4675,13 +4762,10 @@ static void P_3dMovement(player_t *player)
 			movepushsideangle = controldirection;
 
 			movepushforward = FixedMul(movepushforward, player->mo->scale);
-#ifdef OLD_MOVEMENT_CODE
-			if (player->speed < topspeed)
-				P_Thrust(player->mo, controldirection, movepushforward);
-			else if ((mforward) && (cbackward))
-				P_Thrust(player->mo, controldirection, movepushforward);
-			else if ((mbackward) && (cforward))
-				P_Thrust(player->mo, controldirection, movepushforward);
+
+#ifdef ESLOPE
+			totalthrust.x += P_ReturnThrustX(player->mo, controldirection, movepushforward);
+			totalthrust.y += P_ReturnThrustY(player->mo, controldirection, movepushforward);
 #else
 			P_Thrust(player->mo, controldirection, movepushforward);
 #endif
@@ -4689,29 +4773,6 @@ static void P_3dMovement(player_t *player)
 	}
 	else if (cmd->sidemove && !(player->pflags & PF_GLIDING) && !player->exiting && !P_PlayerInPain(player))
 	{
-#ifdef OLD_MOVEMENT_CODE
-		boolean mright = 0;
-		boolean mleft = 0;
-		angle_t sideangle;
-
-		sideangle = player->mo->angle - ANGLE_90;
-
-		// Monster Iestyn - 04-11-13
-		// Quadrants are stupid, excessive and broken, let's do this a much simpler way!
-		// Get delta angle from rmom angle and player angle first
-		dangle = R_PointToAngle2(0,0, player->rmomx, player->rmomy) - sideangle;
-		if (dangle > ANGLE_180)
-			dangle = InvAngle(dangle);
-
-		// now use it to determine direction!
-		if (dangle <= ANGLE_45) // angles 0-45 or 315-360
-			mright = 1; // going right
-		else if (dangle >= ANGLE_135) // angles 135-225
-			mleft = 1; // going left
-
-		// anything else will leave both at 0, so no need to do anything else
-#endif
-
 		movepushside = cmd->sidemove * (thrustfactor * acceleration);
 
 		if (!onground)
@@ -4734,19 +4795,37 @@ static void P_3dMovement(player_t *player)
 
 		// Finally move the player now that his speed/direction has been decided.
 		movepushside = FixedMul(movepushside, player->mo->scale);
-#ifdef OLD_MOVEMENT_CODE
-		if (player->speed < topspeed)
-			P_Thrust(player->mo, movepushsideangle, movepushside);
-		else if (mright && cmd->sidemove < 0)
-			P_Thrust(player->mo, movepushsideangle, movepushside);
-		else if (mleft && cmd->sidemove > 0)
-			P_Thrust(player->mo, movepushsideangle, movepushside);
+
+#ifdef ESLOPE
+		totalthrust.x += P_ReturnThrustX(player->mo, movepushsideangle, movepushside);
+		totalthrust.y += P_ReturnThrustY(player->mo, movepushsideangle, movepushside);
 #else
 		P_Thrust(player->mo, movepushsideangle, movepushside);
 #endif
 	}
 
-#ifndef OLD_MOVEMENT_CODE
+#ifdef ESLOPE
+	if ((totalthrust.x || totalthrust.y)
+		&& player->mo->standingslope && abs(player->mo->standingslope->zdelta) > FRACUNIT/2) {
+		// Factor thrust to slope, but only for the part pushing up it!
+		// The rest is unaffected.
+		angle_t thrustangle = R_PointToAngle2(0, 0, totalthrust.x, totalthrust.y)-player->mo->standingslope->xydirection;
+
+		if (player->mo->standingslope->zdelta < 0) { // Direction goes down, so thrustangle needs to face toward
+			if (thrustangle < ANGLE_90 || thrustangle > ANGLE_270) {
+				P_QuantizeMomentumToSlope(&totalthrust, player->mo->standingslope);
+			}
+		} else { // Direction goes up, so thrustangle needs to face away
+			if (thrustangle > ANGLE_90 && thrustangle < ANGLE_270) {
+				P_QuantizeMomentumToSlope(&totalthrust, player->mo->standingslope);
+			}
+		}
+	}
+
+	player->mo->momx += totalthrust.x;
+	player->mo->momy += totalthrust.y;
+#endif
+
 	// Time to ask three questions:
 	// 1) Are we over topspeed?
 	// 2) If "yes" to 1, were we moving over topspeed to begin with?
@@ -4780,7 +4859,6 @@ static void P_3dMovement(player_t *player)
 			player->mo->momy = tempmomy + player->cmomy;
 		}
 	}
-#endif
 }
 
 //
@@ -6409,13 +6487,17 @@ static void P_MovePlayer(player_t *player)
 	// MOVEMENT ANIMATIONS //
 	/////////////////////////
 
-	if ((cmd->forwardmove != 0 || cmd->sidemove != 0) || (player->powers[pw_super] && player->mo->z > player->mo->floorz))
+	if ((cmd->forwardmove != 0 || cmd->sidemove != 0) || (player->powers[pw_super] && !onground))
 	{
 		// If the player is moving fast enough,
 		// break into a run!
 		if (player->speed >= runspd && player->panim == PA_WALK && !player->skidtime && (onground || player->powers[pw_super]))
 			P_SetPlayerMobjState (player->mo, S_PLAY_RUN);
 
+		// Super floating at slow speeds has its own special animation.
+		else if (player->powers[pw_super] && player->panim == PA_IDLE && !onground)
+			P_SetPlayerMobjState (player->mo, S_PLAY_SUPER_FLOAT);
+
 		// Otherwise, just walk.
 		else if ((player->rmomx || player->rmomy) && player->panim == PA_IDLE)
 			P_SetPlayerMobjState (player->mo, S_PLAY_WALK);
@@ -6424,13 +6506,18 @@ static void P_MovePlayer(player_t *player)
 	// If your running animation is playing, and you're
 	// going too slow, switch back to the walking frames.
 	if (player->panim == PA_RUN && player->speed < runspd)
-		P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
+	{
+		if (!onground && player->powers[pw_super])
+			P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_FLOAT);
+		else
+			P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
+	}
 
 	// If Springing, but travelling DOWNWARD, change back!
-	if (player->mo->state == &states[S_PLAY_JUMP] && P_MobjFlip(player->mo)*player->mo->momz < 0)
+	if (player->panim == PA_SPRING && P_MobjFlip(player->mo)*player->mo->momz < 0)
 		P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
 	// If Springing but on the ground, change back!
-	else if (onground && (player->mo->state == &states[S_PLAY_JUMP] || player->panim == PA_FALL || player->mo->state == &states[S_PLAY_RIDE]) && !player->mo->momz)
+	else if (onground && (player->panim == PA_SPRING || player->panim == PA_FALL || player->panim == PA_RIDE) && !player->mo->momz)
 		P_SetPlayerMobjState(player->mo, S_PLAY_STND);
 
 	// If you are stopped and are still walking, stand still!
@@ -6469,7 +6556,7 @@ static void P_MovePlayer(player_t *player)
 			else
 			{
 				player->pflags |= PF_JUMPED;
-				P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+				P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 			}
 		}
 		player->pflags &= ~PF_GLIDING;
@@ -6527,7 +6614,7 @@ static void P_MovePlayer(player_t *player)
 				|| (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]) && player->charability == CA_GLIDEANDCLIMB))
 			{
 				player->pflags |= PF_JUMPED;
-				P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+				P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 			}
 			else
 			{
@@ -6597,7 +6684,7 @@ static void P_MovePlayer(player_t *player)
 			else
 			{
 				player->pflags |= PF_JUMPED;
-				P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+				P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 			}
 		}
 		player->powers[pw_tailsfly] = 0;
@@ -6795,8 +6882,8 @@ static void P_MovePlayer(player_t *player)
 			if (player->charflags & SF_SUPER && player->powers[pw_super] && player->speed > FixedMul(5<<FRACBITS, player->mo->scale)
 			&& P_MobjFlip(player->mo)*player->mo->momz <= 0)
 			{
-				if (player->panim == PA_ROLL || player->mo->state-states == S_PLAY_PAIN)
-					P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_WALK);
+				if (player->panim == PA_ROLL || 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;
@@ -6855,7 +6942,7 @@ static void P_MovePlayer(player_t *player)
 	}
 
 	// Make sure you're not teetering when you shouldn't be.
-	if ((player->mo->state-states == S_PLAY_EDGE || player->mo->state-states == S_PLAY_SUPER_EDGE)
+	if (player->panim == PA_EDGE
 	&& (player->mo->momx || player->mo->momy || player->mo->momz))
 		P_SetPlayerMobjState(player->mo, S_PLAY_STND);
 
@@ -7177,7 +7264,7 @@ static void P_DoRopeHang(player_t *player)
 
 		if (!(player->pflags & PF_SLIDING) && (player->pflags & PF_JUMPED)
 		&& !(player->panim == PA_ROLL) && player->charability2 == CA2_SPINDASH)
-			P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+			P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 		return;
 	}
 
@@ -7294,7 +7381,7 @@ static void P_DoRopeHang(player_t *player)
 
 				if (!(player->pflags & PF_SLIDING) && (player->pflags & PF_JUMPED)
 				&& !(player->panim == PA_ROLL) && player->charability2 == CA2_SPINDASH)
-					P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+					P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 			}
 
 			P_SetTarget(&player->mo->tracer, NULL);
@@ -8084,10 +8171,12 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
 		INT32 xl, xh, yl, yh, bx, by;
 		validcount++;
 
-		xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
-		xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
-		yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
-		yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
+		xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
+		xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
+		yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
+		yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
+
+		BMBOUNDFIX(xl, xh, yl, yh);
 
 		for (by = yl; by <= yh; by++)
 			for (bx = xl; bx <= xh; bx++)
@@ -8608,7 +8697,7 @@ void P_PlayerThink(player_t *player)
 			P_SetPlayerMobjState(player->mo, S_PLAY_GLIDE);
 	}
 	else if ((player->pflags & PF_JUMPED) && !player->powers[pw_super] && player->panim != PA_ROLL && player->charability2 == CA2_SPINDASH)
-		P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+		P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 
 	if (player->flashcount)
 		player->flashcount--;
@@ -9032,7 +9121,6 @@ void P_PlayerThink(player_t *player)
 			player->mo->tracer->flags2 &= ~MF2_DONTDRAW;
 	}
 
-	player->mo->pmomz = 0;
 	player->pflags &= ~PF_SLIDING;
 
 /*
@@ -9237,7 +9325,7 @@ void P_PlayerAfterThink(player_t *player)
 	&& ((!player->powers[pw_super] && player->panim != PA_ROLL)
 	|| player->mo->state == &states[player->mo->info->painstate])
 	&& player->charability2 == CA2_SPINDASH)
-		P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+		P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
 
 	if (player->pflags & PF_CARRIED && player->mo->tracer)
 	{
@@ -9383,4 +9471,7 @@ void P_PlayerAfterThink(player_t *player)
 		player->mo->flags2 |= MF2_DONTDRAW;
 		player->mo->flags |= MF_NOGRAVITY;
 	}
+
+	if (P_IsObjectOnGround(player->mo))
+		player->mo->pmomz = 0;
 }
diff --git a/src/r_bsp.c b/src/r_bsp.c
index e967e28cef3e194ebb5e43dcf652f9e2f91061e5..c87d8baa716328e567ce5978a1ffc0baf21b9ad3 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -18,6 +18,7 @@
 
 #include "r_splats.h"
 #include "p_local.h" // camera
+#include "p_slopes.h"
 #include "z_zone.h" // Check R_Prep3DFloors
 
 seg_t *curline;
@@ -31,7 +32,6 @@ sector_t *backsector;
 // 896 drawsegs! So too bad here's a limit removal a-la-Boom
 drawseg_t *drawsegs = NULL;
 drawseg_t *ds_p = NULL;
-drawseg_t *firstnewseg = NULL;
 
 // indicates doors closed wrt automap bugfix:
 INT32 doorclosed;
@@ -459,6 +459,11 @@ static void R_AddLine(seg_t *line)
 	doorclosed = 0;
 
 	// Closed door.
+#ifdef ESLOPE
+	// Just don't bother checking this if one side is sloped. This is probably inefficient, but it's better than
+	// random renderer stopping around slopes...
+	if (!(frontsector->f_slope || frontsector->c_slope || backsector->f_slope || backsector->c_slope))
+#endif
 	if (backsector->ceilingheight <= frontsector->floorheight
 		|| backsector->floorheight >= frontsector->ceilingheight)
 	{
@@ -487,6 +492,10 @@ static void R_AddLine(seg_t *line)
 #endif
 		backsector->ceilingpic == frontsector->ceilingpic
 		&& backsector->floorpic == frontsector->floorpic
+#ifdef ESLOPE
+		&& backsector->f_slope == frontsector->f_slope
+		&& backsector->c_slope == frontsector->c_slope
+#endif
 		&& backsector->lightlevel == frontsector->lightlevel
 		&& !curline->sidedef->midtexture
 		// Check offsets too!
@@ -842,11 +851,19 @@ static void R_Subsector(size_t num)
 			sub->sector->moved = frontsector->moved = false;
 		}
 
-		light = R_GetPlaneLight(frontsector, frontsector->floorheight, 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);
 		if (frontsector->floorlightsec == -1)
 			floorlightlevel = *frontsector->lightlist[light].lightlevel;
 		floorcolormap = frontsector->lightlist[light].extra_colormap;
-		light = R_GetPlaneLight(frontsector, frontsector->ceilingheight, false);
+		light = R_GetPlaneLight(frontsector,
+#ifdef ESLOPE
+								frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
+#endif
+								frontsector->ceilingheight, false);
 		if (frontsector->ceilinglightsec == -1)
 			ceilinglightlevel = *frontsector->lightlist[light].lightlevel;
 		ceilingcolormap = frontsector->lightlist[light].extra_colormap;
@@ -854,32 +871,52 @@ static void R_Subsector(size_t num)
 
 	sub->sector->extra_colormap = frontsector->extra_colormap;
 
-	if ((frontsector->floorheight < viewz || (frontsector->heightsec != -1
+	if (((
+#ifdef ESLOPE
+			frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) :
+#endif
+		frontsector->floorheight) < viewz || (frontsector->heightsec != -1
 		&& sectors[frontsector->heightsec].ceilingpic == skyflatnum)))
 	{
 		floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel,
-			frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL);
+			frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL
+#ifdef ESLOPE
+			, frontsector->f_slope
+#endif
+			);
 	}
 	else
 		floorplane = NULL;
 
-	if ((frontsector->ceilingheight > viewz || frontsector->ceilingpic == skyflatnum
+	if (((
+#ifdef ESLOPE
+			frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) :
+#endif
+		frontsector->ceilingheight) > viewz || frontsector->ceilingpic == skyflatnum
 		|| (frontsector->heightsec != -1
 		&& sectors[frontsector->heightsec].floorpic == skyflatnum)))
 	{
 		ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic,
 			ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle,
-			ceilingcolormap, NULL);
+			ceilingcolormap, NULL
+#ifdef ESLOPE
+			, frontsector->c_slope
+#endif
+			);
 	}
 	else
 		ceilingplane = NULL;
 
 	numffloors = 0;
+#ifdef ESLOPE
+	ffloor[numffloors].slope = NULL;
+#endif
 	ffloor[numffloors].plane = NULL;
 	ffloor[numffloors].polyobj = NULL;
 	if (frontsector->ffloors)
 	{
 		ffloor_t *rover;
+		fixed_t heightcheck, planecenterz, floorcenterz, ceilingcenterz;
 
 		for (rover = frontsector->ffloors; rover && numffloors < MAXFFLOORS; rover = rover->next)
 		{
@@ -897,18 +934,60 @@ static void R_Subsector(size_t num)
 
 			ffloor[numffloors].plane = NULL;
 			ffloor[numffloors].polyobj = NULL;
-			if (*rover->bottomheight <= frontsector->ceilingheight
-				&& *rover->bottomheight >= frontsector->floorheight
-				&& ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES))
-				|| (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES))))
+
+			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) :
+#endif
+				*rover->bottomheight;
+
+			planecenterz =
+#ifdef ESLOPE
+				*rover->b_slope ? P_GetZAt(*rover->b_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
+#endif
+				*rover->bottomheight;
+			if (planecenterz <= ceilingcenterz
+				&& planecenterz >= floorcenterz
+				&& ((viewz < heightcheck && !(rover->flags & FF_INVERTPLANES))
+				|| (viewz > heightcheck && (rover->flags & FF_BOTHPLANES))))
 			{
-				light = R_GetPlaneLight(frontsector, *rover->bottomheight,
+				light = R_GetPlaneLight(frontsector, planecenterz,
 					viewz < *rover->bottomheight);
+
 				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);
+					*rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover
+#ifdef ESLOPE
+					, *rover->b_slope
+#endif
+					);
+
+#ifdef ESLOPE
+				ffloor[numffloors].slope = *rover->b_slope;
+
+				// Tell the renderer this sector has slopes in it.
+				if (ffloor[numffloors].slope)
+					frontsector->hasslope = true;
+#endif
+
+				ffloor[numffloors].height =
+#ifdef ESLOPE
+				*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) :
+#endif
+				*rover->bottomheight;
 
-				ffloor[numffloors].height = *rover->bottomheight;
 				ffloor[numffloors].ffloor = rover;
 				numffloors++;
 			}
@@ -916,16 +995,47 @@ static void R_Subsector(size_t num)
 				break;
 			ffloor[numffloors].plane = NULL;
 			ffloor[numffloors].polyobj = NULL;
-			if (*rover->topheight >= frontsector->floorheight
-				&& *rover->topheight <= frontsector->ceilingheight
-				&& ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES))
-				|| (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES))))
+
+			heightcheck =
+#ifdef ESLOPE
+				*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) :
+#endif
+				*rover->topheight;
+
+			planecenterz =
+#ifdef ESLOPE
+				*rover->t_slope ? P_GetZAt(*rover->t_slope, frontsector->soundorg.x, frontsector->soundorg.y) :
+#endif
+				*rover->topheight;
+			if (planecenterz >= floorcenterz
+				&& planecenterz <= ceilingcenterz
+				&& ((viewz > heightcheck && !(rover->flags & FF_INVERTPLANES))
+				|| (viewz < heightcheck && (rover->flags & FF_BOTHPLANES))))
 			{
-				light = R_GetPlaneLight(frontsector, *rover->topheight, viewz < *rover->topheight);
+				light = R_GetPlaneLight(frontsector, planecenterz, viewz < *rover->topheight);
+
 				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);
-				ffloor[numffloors].height = *rover->topheight;
+					frontsector->lightlist[light].extra_colormap, rover
+#ifdef ESLOPE
+					, *rover->t_slope
+#endif
+					);
+
+#ifdef ESLOPE
+				ffloor[numffloors].slope = *rover->t_slope;
+
+				// Tell the renderer this sector has slopes in it.
+				if (ffloor[numffloors].slope)
+					frontsector->hasslope = true;
+#endif
+
+				ffloor[numffloors].height =
+#ifdef ESLOPE
+				*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) :
+#endif
+				*rover->topheight;
+
 				ffloor[numffloors].ffloor = rover;
 				numffloors++;
 			}
@@ -977,12 +1087,20 @@ static void R_Subsector(size_t num)
 						polysec->lightlevel, xoff, yoff,
 						polysec->floorpic_angle-po->angle,
 						NULL,
-						NULL);
-				ffloor[numffloors].plane->polyobj = po;
+						NULL
+#ifdef ESLOPE
+					, NULL // will ffloors be slopable eventually?
+#endif
+					);
+				//ffloor[numffloors].plane->polyobj = po;
 
 				ffloor[numffloors].height = polysec->floorheight;
 				ffloor[numffloors].polyobj = po;
+#ifdef ESLOPE
+				ffloor[numffloors].slope = NULL;
+#endif
 //				ffloor[numffloors].ffloor = rover;
+				po->visplane = ffloor[numffloors].plane;
 				numffloors++;
 			}
 
@@ -1013,12 +1131,20 @@ static void R_Subsector(size_t num)
 				light = 0;
 				ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
 					polysec->lightlevel, xoff, yoff, polysec->ceilingpic_angle-po->angle,
-					NULL, NULL);
-				ffloor[numffloors].plane->polyobj = po;
+					NULL, NULL
+#ifdef ESLOPE
+					, NULL // will ffloors be slopable eventually?
+#endif
+					);
+				//ffloor[numffloors].plane->polyobj = po;
 
 				ffloor[numffloors].polyobj = po;
 				ffloor[numffloors].height = polysec->ceilingheight;
+#ifdef ESLOPE
+				ffloor[numffloors].slope = NULL;
+#endif
 //				ffloor[numffloors].ffloor = rover;
+				po->visplane = ffloor[numffloors].plane;
 				numffloors++;
 			}
 
@@ -1075,6 +1201,11 @@ void R_Prep3DFloors(sector_t *sector)
 	fixed_t bestheight, maxheight;
 	INT32 count, i, mapnum;
 	sector_t *sec;
+#ifdef ESLOPE
+	pslope_t *bestslope;
+	fixed_t heighttest; // I think it's better to check the Z height at the sector's center
+	                    // than assume unsloped heights are accurate indicators of order in sloped sectors. -Red
+#endif
 
 	count = 1;
 	for (rover = sector->ffloors; rover; rover = rover->next)
@@ -1097,7 +1228,14 @@ void R_Prep3DFloors(sector_t *sector)
 	else
 		memset(sector->lightlist, 0, sizeof (lightlist_t) * count);
 
+#ifdef ESLOPE
+	heighttest = sector->c_slope ? P_GetZAt(sector->c_slope, sector->soundorg.x, sector->soundorg.y) : sector->ceilingheight;
+
+	sector->lightlist[0].height = heighttest + 1;
+	sector->lightlist[0].slope = sector->c_slope;
+#else
 	sector->lightlist[0].height = sector->ceilingheight + 1;
+#endif
 	sector->lightlist[0].lightlevel = &sector->lightlevel;
 	sector->lightlist[0].caster = NULL;
 	sector->lightlist[0].extra_colormap = sector->extra_colormap;
@@ -1115,6 +1253,29 @@ void R_Prep3DFloors(sector_t *sector)
 				&& !(rover->flags & FF_CUTLEVEL) && !(rover->flags & FF_CUTSPRITES)))
 			continue;
 
+#ifdef ESLOPE
+			heighttest = *rover->t_slope ? P_GetZAt(*rover->t_slope, sector->soundorg.x, sector->soundorg.y) : *rover->topheight;
+
+			if (heighttest > bestheight && heighttest < maxheight)
+			{
+				best = rover;
+				bestheight = heighttest;
+				bestslope = *rover->t_slope;
+				continue;
+			}
+			if (rover->flags & FF_DOUBLESHADOW) {
+				heighttest = *rover->b_slope ? P_GetZAt(*rover->b_slope, sector->soundorg.x, sector->soundorg.y) : *rover->bottomheight;
+
+				if (heighttest > bestheight
+					&& heighttest < maxheight)
+				{
+					best = rover;
+					bestheight = heighttest;
+					bestslope = *rover->b_slope;
+					continue;
+				}
+			}
+#else
 			if (*rover->topheight > bestheight && *rover->topheight < maxheight)
 			{
 				best = rover;
@@ -1128,6 +1289,7 @@ void R_Prep3DFloors(sector_t *sector)
 				bestheight = *rover->bottomheight;
 				continue;
 			}
+#endif
 		}
 		if (!best)
 		{
@@ -1138,6 +1300,9 @@ void R_Prep3DFloors(sector_t *sector)
 		sector->lightlist[i].height = maxheight = bestheight;
 		sector->lightlist[i].caster = best;
 		sector->lightlist[i].flags = best->flags;
+#ifdef ESLOPE
+		sector->lightlist[i].slope = bestslope;
+#endif
 		sec = &sectors[best->secnum];
 		mapnum = sec->midmap;
 		if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps)
@@ -1163,7 +1328,12 @@ void R_Prep3DFloors(sector_t *sector)
 
 		if (best->flags & FF_DOUBLESHADOW)
 		{
+#ifdef ESLOPE
+			heighttest = *best->b_slope ? P_GetZAt(*best->b_slope, sector->soundorg.x, sector->soundorg.y) : *best->bottomheight;
+			if (bestheight == heighttest) ///TODO: do this in a more efficient way -Red
+#else
 			if (bestheight == *best->bottomheight)
+#endif
 			{
 				sector->lightlist[i].lightlevel = sector->lightlist[best->lastlight].lightlevel;
 				sector->lightlist[i].extra_colormap =
diff --git a/src/r_bsp.h b/src/r_bsp.h
index 20a80d89ab44a00a5125ce4f46d8cbe65ac38f91..14b11ea77bc0dff35f8abf318c5dc1d31e42e857 100644
--- a/src/r_bsp.h
+++ b/src/r_bsp.h
@@ -30,7 +30,6 @@ extern INT32 checkcoord[12][4];
 
 extern drawseg_t *drawsegs;
 extern drawseg_t *ds_p;
-extern drawseg_t *firstnewseg;
 extern INT32 doorclosed;
 
 typedef void (*drawfunc_t)(INT32 start, INT32 stop);
diff --git a/src/r_defs.h b/src/r_defs.h
index 7f8bd7e1d1ee6f99a7542adf8eb9aec392a7e3fe..f18410fe88139cfd52827ae90bf3d18880fbc20b 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -155,6 +155,12 @@ typedef struct ffloor_s
 	fixed_t *bottomyoffs;
 	angle_t *bottomangle;
 
+#ifdef ESLOPE
+	// Pointers to pointers. Yup.
+	struct pslope_s **t_slope;
+	struct pslope_s **b_slope;
+#endif
+
 	size_t secnum;
 	ffloortype_e flags;
 	struct line_s *master;
@@ -184,6 +190,9 @@ typedef struct lightlist_s
 	extracolormap_t *extra_colormap;
 	INT32 flags;
 	ffloor_t *caster;
+#ifdef ESLOPE
+	struct pslope_s *slope; // FF_DOUBLESHADOW makes me have to store this pointer here. Bluh bluh.
+#endif
 } lightlist_t;
 
 
@@ -224,6 +233,52 @@ typedef struct secplane_t
 	fixed_t a, b, c, d, ic;
 } secplane_t;
 
+// Slopes
+#ifdef ESLOPE
+typedef enum {
+	SL_NOPHYSICS = 1, // Don't do momentum adjustment with this slope
+	SL_NODYNAMIC = 1<<1, // Slope will never need to move during the level, so don't fuss with recalculating it
+	SL_ANCHORVERTEX = 1<<2, // Slope is using a Slope Vertex Thing to anchor its position
+	SL_VERTEXSLOPE = 1<<3, // Slope is built from three Slope Vertex Things
+} slopeflags_t;
+
+typedef struct pslope_s
+{
+	UINT16 id; // The number of the slope, mostly used for netgame syncing purposes
+
+	// --- Information used in clipping/projection ---
+	// Origin vector for the plane
+	vector3_t o;
+
+	// 2-Dimentional vector (x, y) normalized. Used to determine distance from
+	// the origin in 2d mapspace. (Basically a thrust of FRACUNIT in xydirection angle)
+	vector2_t d;
+
+	// The rate at which z changes based on distance from the origin plane.
+	fixed_t zdelta;
+
+	// The normal of the slope; will always point upward, and thus be inverted on ceilings. I think it's only needed for physics? -Red
+	vector3_t normal;
+
+	// For comparing when a slope should be rendered
+	fixed_t lowz;
+	fixed_t highz;
+
+	// This values only check and must be updated if the slope itself is modified
+	angle_t zangle; // Angle of the plane going up from the ground (not mesured in degrees)
+	angle_t xydirection; // The direction the slope is facing (north, west, south, etc.)
+
+	struct line_s *sourceline; // The line that generated the slope
+	fixed_t extent; // Distance value used for recalculating zdelta
+	UINT8 refpos; // 1=front floor 2=front ceiling 3=back floor 4=back ceiling (used for dynamic sloping)
+
+	UINT8 flags; // Slope options
+	mapthing_t **vertices; // List should be three long for slopes made by vertex things, or one long for slopes using one vertex thing to anchor
+
+	struct pslope_s *next; // Make a linked list of dynamic slopes, for easy reference later
+} pslope_t;
+#endif
+
 typedef enum
 {
 	SF_FLIPSPECIAL_FLOOR    =  1,
@@ -337,6 +392,13 @@ typedef struct sector_s
 	precipmobj_t *preciplist;
 	struct mprecipsecnode_s *touching_preciplist;
 
+#ifdef ESLOPE
+	// Eternity engine slope
+	pslope_t *f_slope; // floor slope
+	pslope_t *c_slope; // ceiling slope
+	boolean hasslope; // The sector, or one of its visible FOFs, contains a slope
+#endif
+
 	// these are saved for netgames, so do not let Lua touch these!
 
 	// offsets sector spawned with (via linedef type 7)
@@ -612,6 +674,12 @@ typedef struct drawseg_s
 	INT16 *thicksidecol;
 	INT32 numthicksides;
 	fixed_t frontscale[MAXVIDWIDTH];
+
+#ifdef ESLOPE
+	fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures
+
+	vertex_t leftpos, rightpos; // Used for rendering FOF walls with slopes
+#endif
 } drawseg_t;
 
 typedef enum
diff --git a/src/r_draw.c b/src/r_draw.c
index cd219c15f624cf9726148ac6d42124f2f40eef99..d1673c9a67e1727ecd7b698eb819d7b8e73f7f52 100644
--- a/src/r_draw.c
+++ b/src/r_draw.c
@@ -103,6 +103,12 @@ fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
 UINT8 *ds_source; // start of a 64*64 tile image
 UINT8 *ds_transmap; // one of the translucency tables
 
+#ifdef ESLOPE
+pslope_t *ds_slope; // Current slope being used
+floatv3_t ds_su, ds_sv, ds_sz; // Vectors for... stuff?
+float focallengthf, zeroheight;
+#endif
+
 /**	\brief Variable flat sizes
 */
 
@@ -121,7 +127,7 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask;
 #define METALSONIC_TT_CACHE_INDEX (MAXSKINS + 2)
 #define ALLWHITE_TT_CACHE_INDEX (MAXSKINS + 3)
 #define SKIN_RAMP_LENGTH 16
-#define DEFAULT_STARTTRANSCOLOR 160
+#define DEFAULT_STARTTRANSCOLOR 96
 #define NUM_PALETTE_ENTRIES 256
 
 static UINT8** translationtablecache[MAXSKINS + 4] = {NULL};
@@ -131,62 +137,70 @@ static UINT8** translationtablecache[MAXSKINS + 4] = {NULL};
 // TODO Callum: Can this be translated?
 const char *Color_Names[MAXSKINCOLORS] =
 {
-	"None",      // SKINCOLOR_NONE
-	"White",     // SKINCOLOR_WHITE
-	"Silver",    // SKINCOLOR_SILVER
-	"Grey",      // SKINCOLOR_GREY
-	"Black",     // SKINCOLOR_BLACK
-	"Cyan",      // SKINCOLOR_CYAN
-	"Teal",      // SKINCOLOR_TEAL
-	"Steel_Blue",// SKINCOLOR_STEELBLUE
-	"Blue",      // SKINCOLOR_BLUE
-	"Peach",     // SKINCOLOR_PEACH
-	"Tan",       // SKINCOLOR_TAN
-	"Pink",      // SKINCOLOR_PINK
-	"Lavender",  // SKINCOLOR_LAVENDER
-	"Purple",    // SKINCOLOR_PURPLE
-	"Orange",    // SKINCOLOR_ORANGE
-	"Rosewood",  // SKINCOLOR_ROSEWOOD
-	"Beige",     // SKINCOLOR_BEIGE
-	"Brown",     // SKINCOLOR_BROWN
-	"Red",       // SKINCOLOR_RED
-	"Dark_Red",  // SKINCOLOR_DARKRED
-	"Neon_Green",// SKINCOLOR_NEONGREEN
-	"Green",     // SKINCOLOR_GREEN
-	"Zim",       // SKINCOLOR_ZIM
-	"Olive",     // SKINCOLOR_OLIVE
-	"Yellow",    // SKINCOLOR_YELLOW
-	"Gold"       // SKINCOLOR_GOLD
+	"None",     	// SKINCOLOR_NONE
+	"White",    	// SKINCOLOR_WHITE
+	"Silver",   	// SKINCOLOR_SILVER
+	"Grey",	    	// SKINCOLOR_GREY
+	"Black",    	// SKINCOLOR_BLACK
+	"Beige",    	// SKINCOLOR_BEIGE
+	"Peach",    	// SKINCOLOR_PEACH
+	"Brown",    	// SKINCOLOR_BROWN
+	"Red",      	// SKINCOLOR_RED
+	"Crimson",     	// SKINCOLOR_CRIMSON
+	"Orange",   	// SKINCOLOR_ORANGE
+	"Rust",     	// SKINCOLOR_RUST
+	"Gold",      	// SKINCOLOR_GOLD
+	"Yellow",   	// SKINCOLOR_YELLOW
+	"Tan",      	// SKINCOLOR_TAN
+	"Moss",      	// SKINCOLOR_MOSS
+	"Peridot",    	// SKINCOLOR_PERIDOT
+	"Green",    	// SKINCOLOR_GREEN
+	"Emerald",  	// SKINCOLOR_EMERALD
+	"Aqua",     	// SKINCOLOR_AQUA
+	"Teal",     	// SKINCOLOR_TEAL
+	"Cyan",     	// SKINCOLOR_CYAN
+	"Blue",     	// SKINCOLOR_BLUE
+	"Azure",    	// SKINCOLOR_AZURE
+	"Pastel",		// SKINCOLOR_PASTEL
+	"Purple",   	// SKINCOLOR_PURPLE
+	"Lavender", 	// SKINCOLOR_LAVENDER
+	"Magenta",   	// SKINCOLOR_MAGENTA
+	"Pink",     	// SKINCOLOR_PINK
+	"Rosy"     	// SKINCOLOR_ROSY
 };
 
 const UINT8 Color_Opposite[MAXSKINCOLORS*2] =
 {
-	SKINCOLOR_NONE,8,   // SKINCOLOR_NONE
-	SKINCOLOR_BLACK,10, // SKINCOLOR_WHITE
-	SKINCOLOR_GREY,4,   // SKINCOLOR_SILVER
-	SKINCOLOR_SILVER,12,// SKINCOLOR_GREY
-	SKINCOLOR_WHITE,8,  // SKINCOLOR_BLACK
-	SKINCOLOR_NONE,8,   // SKINCOLOR_CYAN
-	SKINCOLOR_NONE,8,   // SKINCOLOR_TEAL
-	SKINCOLOR_NONE,8,   // SKINCOLOR_STEELBLUE
-	SKINCOLOR_ORANGE,9, // SKINCOLOR_BLUE
-	SKINCOLOR_NONE,8,   // SKINCOLOR_PEACH
-	SKINCOLOR_NONE,8,   // SKINCOLOR_TAN
-	SKINCOLOR_NONE,8,   // SKINCOLOR_PINK
-	SKINCOLOR_NONE,8,   // SKINCOLOR_LAVENDER
-	SKINCOLOR_NONE,8,   // SKINCOLOR_PURPLE
-	SKINCOLOR_BLUE,12,  // SKINCOLOR_ORANGE
-	SKINCOLOR_NONE,8,   // SKINCOLOR_ROSEWOOD
-	SKINCOLOR_NONE,8,   // SKINCOLOR_BEIGE
-	SKINCOLOR_NONE,8,   // SKINCOLOR_BROWN
-	SKINCOLOR_GREEN,5,  // SKINCOLOR_RED
-	SKINCOLOR_NONE,8,   // SKINCOLOR_DARKRED
-	SKINCOLOR_NONE,8,   // SKINCOLOR_NEONGREEN
-	SKINCOLOR_RED,11,   // SKINCOLOR_GREEN
-	SKINCOLOR_PURPLE,3, // SKINCOLOR_ZIM
-	SKINCOLOR_NONE,8,   // SKINCOLOR_OLIVE
-	SKINCOLOR_NONE,8,   // SKINCOLOR_YELLOW
-	SKINCOLOR_NONE,8    // SKINCOLOR_GOLD
+	SKINCOLOR_NONE,8,   	// SKINCOLOR_NONE
+	SKINCOLOR_BLACK,10, 	// SKINCOLOR_WHITE
+	SKINCOLOR_GREY,4,   	// SKINCOLOR_SILVER
+	SKINCOLOR_SILVER,12,	// SKINCOLOR_GREY
+	SKINCOLOR_WHITE,8,  	// SKINCOLOR_BLACK
+	SKINCOLOR_BEIGE,8,   	// SKINCOLOR_BEIGE - needs new offset
+	SKINCOLOR_BROWN,8,   	// SKINCOLOR_PEACH - ditto
+	SKINCOLOR_PEACH,8,   	// SKINCOLOR_BROWN - ditto
+	SKINCOLOR_GREEN,5,  	// SKINCOLOR_RED
+	SKINCOLOR_CYAN,8,   	// SKINCOLOR_CRIMSON - ditto
+	SKINCOLOR_BLUE,12,  	// SKINCOLOR_ORANGE
+	SKINCOLOR_TAN,8,   		// SKINCOLOR_RUST - ditto
+	SKINCOLOR_LAVENDER,8,    // SKINCOLOR_GOLD - ditto
+	SKINCOLOR_TEAL,8,   	// SKINCOLOR_YELLOW - ditto
+	SKINCOLOR_RUST,8,   	// SKINCOLOR_TAN - ditto
+	SKINCOLOR_MAGENTA,3, 	// SKINCOLOR_MOSS
+	SKINCOLOR_PURPLE,8,   	// SKINCOLOR_PERIDOT - ditto
+	SKINCOLOR_RED,11,   	// SKINCOLOR_GREEN
+	SKINCOLOR_PASTEL,8,   	// SKINCOLOR_EMERALD - ditto
+	SKINCOLOR_ROSY,8,   	// SKINCOLOR_AQUA - ditto
+	SKINCOLOR_YELLOW,8,   	// SKINCOLOR_TEAL - ditto
+	SKINCOLOR_CRIMSON,8,   	// SKINCOLOR_CYAN - ditto
+	SKINCOLOR_ORANGE,9, 	// SKINCOLOR_BLUE
+	SKINCOLOR_PINK,8,   	// SKINCOLOR_AZURE - ditto
+	SKINCOLOR_EMERALD,8,   	// SKINCOLOR_PASTEL - ditto
+	SKINCOLOR_PERIDOT,8,   	// SKINCOLOR_PURPLE - ditto
+	SKINCOLOR_GOLD,8,   	// SKINCOLOR_LAVENDER - ditto
+	SKINCOLOR_MOSS,8,   	// SKINCOLOR_MAGENTA - ditto
+	SKINCOLOR_AZURE,8,   	// SKINCOLOR_PINK - ditto
+	SKINCOLOR_AQUA,8   	// SKINCOLOR_ROSY - ditto
 };
 
 CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1];
@@ -236,27 +250,31 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
 		0x03, // SKINCOLOR_SILVER
 		0x08, // SKINCOLOR_GREY
 		0x18, // SKINCOLOR_BLACK
-		0xd0, // SKINCOLOR_CYAN
-		0xdc, // SKINCOLOR_TEAL
-		0xc8, // SKINCOLOR_STEELBLUE
-		0xe2, // SKINCOLOR_BLUE
-		0x40, // SKINCOLOR_PEACH
-		0x48, // SKINCOLOR_TAN
-		0x90, // SKINCOLOR_PINK
-		0xf8, // SKINCOLOR_LAVENDER
-		0xc0, // SKINCOLOR_PURPLE
-		0x52, // SKINCOLOR_ORANGE
-		0x5c, // SKINCOLOR_ROSEWOOD
-		0x20, // SKINCOLOR_BEIGE
-		0x30, // SKINCOLOR_BROWN
-		0x7d, // SKINCOLOR_RED
-		0x85, // SKINCOLOR_DARKRED
-		0xb8, // SKINCOLOR_NEONGREEN
-		0xa0, // SKINCOLOR_GREEN
-		0xb0, // SKINCOLOR_ZIM
-		0x69, // SKINCOLOR_OLIVE
-		0x67, // SKINCOLOR_YELLOW
-		0x70, // SKINCOLOR_GOLD
+		0xf0, // SKINCOLOR_BEIGE
+		0xd8, // SKINCOLOR_PEACH
+		0xe0, // SKINCOLOR_BROWN
+		0x21, // SKINCOLOR_RED
+		0x28, // SKINCOLOR_CRIMSON
+		0x31, // SKINCOLOR_ORANGE
+		0x3a, // SKINCOLOR_RUST
+		0x40, // SKINCOLOR_GOLD
+		0x48, // SKINCOLOR_YELLOW
+		0x54, // SKINCOLOR_TAN
+		0x58, // SKINCOLOR_MOSS
+		0xbc, // SKINCOLOR_PERIDOT
+		0x60, // SKINCOLOR_GREEN
+		0x70, // SKINCOLOR_EMERALD
+		0x78, // SKINCOLOR_AQUA
+		0x8c, // SKINCOLOR_TEAL
+		0x80, // SKINCOLOR_CYAN
+		0x92, // SKINCOLOR_BLUE
+		0xaa, // SKINCOLOR_AZURE
+		0xa0, // SKINCOLOR_PASTEL
+		0xa0, // SKINCOLOR_PURPLE
+		0xc0, // SKINCOLOR_LAVENDER
+		0xb3, // SKINCOLOR_MAGENTA
+		0xd0, // SKINCOLOR_PINK
+		0xc8, // SKINCOLOR_ROSY
 	};
 	INT32 i;
 	INT32 starttranscolor;
@@ -274,7 +292,7 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
 		if (skinnum == TC_BOSS)
 			dest_colormap[31] = 0;
 		else if (skinnum == TC_METALSONIC)
-			dest_colormap[239] = 0;
+			dest_colormap[159] = 0;
 
 		return;
 	}
@@ -293,196 +311,339 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U
 	{
 	case SKINCOLOR_SILVER:
 	case SKINCOLOR_GREY:
-	case SKINCOLOR_PEACH:
-	case SKINCOLOR_BEIGE:
 	case SKINCOLOR_BROWN:
-	case SKINCOLOR_RED:
 	case SKINCOLOR_GREEN:
-	case SKINCOLOR_BLUE:
 		// 16 color ramp
 		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
 			dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i);
 		break;
 
-	case SKINCOLOR_ORANGE:
-		// 14 colors of orange + brown
-		for (i = 0; i < SKIN_RAMP_LENGTH-2; i++)
-			dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i);
-		for (i = 0; i < 2; i++)
-			dest_colormap[starttranscolor + (i+SKIN_RAMP_LENGTH-2)] = (UINT8)(152 + i);
-		break;
-
+	case SKINCOLOR_WHITE:
 	case SKINCOLOR_CYAN:
 		// 12 color ramp
 		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
 			dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (12*i/SKIN_RAMP_LENGTH));
 		break;
 
-	case SKINCOLOR_WHITE:
 	case SKINCOLOR_BLACK:
-	case SKINCOLOR_STEELBLUE:
-	case SKINCOLOR_PINK:
+	case SKINCOLOR_MOSS:
+	case SKINCOLOR_EMERALD:
 	case SKINCOLOR_LAVENDER:
-	case SKINCOLOR_PURPLE:
-	case SKINCOLOR_DARKRED:
-	case SKINCOLOR_ZIM:
-	case SKINCOLOR_YELLOW:
-	case SKINCOLOR_GOLD:
+	case SKINCOLOR_PINK:
 		// 8 color ramp
 		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
 			dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1));
 		break;
 
-	case SKINCOLOR_TEAL:
-		// 5 color ramp
+	case SKINCOLOR_BEIGE:
+		// 13 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i == 15)
+				dest_colormap[starttranscolor + i] = 0xed; // Darkest
+			else if (i <= 6)
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + ((i + 1) >> 1)); // Brightest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 3);
+		}
+		break;
+
+	case SKINCOLOR_PEACH:
+		// 11 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i == 0)
+				dest_colormap[starttranscolor + i] = 0xD0; // Lightest 1
+			else if (i == 1)
+				dest_colormap[starttranscolor + i] = 0x30; // Lightest 2
+			else if (i <= 11)
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1);
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 7); // Darkest
+		}
+		break;
+
+	case SKINCOLOR_RED:
+		// 16 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i == 13)
+				dest_colormap[starttranscolor + i] = 0x47; // Semidark
+			else if (i > 13)
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 1); // Darkest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i);
+		}
+		break;
+
+	case SKINCOLOR_CRIMSON:
+		// 9 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i/2 == 6)
+				dest_colormap[starttranscolor + i] = 0x47; // Semidark
+			else if (i/2 == 7)
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 8); // Darkest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1));
+		}
+		break;
+
+	case SKINCOLOR_ORANGE:
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i == 15)
+				dest_colormap[starttranscolor + i] = 0x2c; // Darkest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i);
+		}
+		break;
+
+	case SKINCOLOR_RUST:
+		// 10 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i <= 11)
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1));
+			else if (i == 12)
+				dest_colormap[starttranscolor + i] = 0x2c; // Darkest 4
+			else if (i == 13)
+				dest_colormap[starttranscolor + i] = 0xfe; // Darkest 3
+			else
+				dest_colormap[starttranscolor + i] = 0x2d + i - 14; // Darkest 2 and 1
+		}
+		break;
+
+	case SKINCOLOR_GOLD:
+		// 10 colors
 		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
 		{
-			if (5*i/16 == 0)
-				dest_colormap[starttranscolor + i] = 0xf7;
+			if (i == 0)
+				dest_colormap[starttranscolor + i] = 0x50; // Lightest 1
+			else if (i == 1)
+				dest_colormap[starttranscolor + i] = 0x53; // Lightest 2
+			else if (i/2 == 7)
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 8); //Darkest
 			else
-				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (5*i/SKIN_RAMP_LENGTH) - 1);
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1);
 		}
 		break;
 
-	case SKINCOLOR_OLIVE:
-		// 7 color ramp
+	case SKINCOLOR_YELLOW:
+		// 10 colors
 		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
-			dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (7*i/SKIN_RAMP_LENGTH));
+		{
+			if (i == 0)
+				dest_colormap[starttranscolor + i] = 0x53; // Lightest
+			else if (i == 15)
+				dest_colormap[starttranscolor + i] = 0xed; // Darkest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1));
+		}
 		break;
 
 	case SKINCOLOR_TAN:
-		// 16 color ramp, from two color ranges
-		for (i = 0; i < SKIN_RAMP_LENGTH/2; i++) // Peach half
-			dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i);
-		for (i = 0; i < SKIN_RAMP_LENGTH/2; i++) // Brown half
-			dest_colormap[starttranscolor + (i+8)] = (UINT8)(48 + i);
+		// 8 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i/2 == 0)
+				dest_colormap[starttranscolor + i] = 0x51; // Lightest
+			else if (i/2 == 5)
+				dest_colormap[starttranscolor + i] = 0xf5; // Darkest 1
+			else if (i/2 == 6)
+				dest_colormap[starttranscolor + i] = 0xf9; // Darkest 2
+			else if (i/2 == 7)
+				dest_colormap[starttranscolor + i] = 0xed; // Darkest 3
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1);
+		}
 		break;
 
-	case SKINCOLOR_ROSEWOOD:
-		// 12 color ramp, from two color ranges!
-		for (i = 0; i < 6; i++) // Orange ...third?
-			dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (12*i/SKIN_RAMP_LENGTH));
-		for (i = 0; i < 10; i++) // Rosewood two-thirds-ish
-			dest_colormap[starttranscolor + (i+6)] = (UINT8)(152 + (12*i/SKIN_RAMP_LENGTH));
+	case SKINCOLOR_PERIDOT:
+		// 8 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i/2 == 0)
+				dest_colormap[starttranscolor + i] = 0x58; // Lightest
+			else if (i/2 == 7)
+				dest_colormap[starttranscolor + i] = 0x77; // Darkest
+			else if (i/2 >= 5)
+				dest_colormap[starttranscolor + i] = (UINT8)(0x5e + (i >> 1) - 5); // Semidark
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1);
+		}
+		break;
+
+	case SKINCOLOR_AQUA:
+		// 10 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i == 0)
+				dest_colormap[starttranscolor + i] = 0x78; // Lightest
+			else if (i >= 14)
+				dest_colormap[starttranscolor + i] = (UINT8)(0x76 + i - 14); // Darkest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) + 1);
+		}
+		break;
+
+	case SKINCOLOR_TEAL:
+		// 6 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i <= 1)
+				dest_colormap[starttranscolor + i] = 0x78; // Lightest
+			else if (i >= 13)
+				dest_colormap[starttranscolor + i] = 0x8a; // Darkest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + ((i - 1)/3));
+		}
+		break;
+
+	case SKINCOLOR_AZURE:
+		// 8 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i <= 3)
+				dest_colormap[starttranscolor + i] = (UINT8)(0x90 + i/2); // Lightest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 2);
+		}
+		break;
+
+	case SKINCOLOR_BLUE:
+		// 16 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i == 15)
+				dest_colormap[starttranscolor + i] = 0x1F; //Darkest 1
+			else if (i == 14)
+				dest_colormap[starttranscolor + i] = 0xfd; //Darkest 2
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i);
+		}
+		break;
+
+	case SKINCOLOR_PASTEL:
+		// 10 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i >= 12)
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i - 7); // Darkest
+			else if (i <= 1)
+				dest_colormap[starttranscolor + i] = 0x90; // Lightest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) - 1);
+		}
+		break;
+
+	case SKINCOLOR_PURPLE:
+		// 10 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i <= 3)
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + i); // Lightest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) + 2);
+		}
 		break;
 
-	case SKINCOLOR_NEONGREEN:
-		// Multi-color ramp
-		dest_colormap[starttranscolor] = 0xA0; // Brighter green
-		for (i = 0; i < SKIN_RAMP_LENGTH-1; i++) // Neon Green
-			dest_colormap[starttranscolor + (i+1)] = (UINT8)(skinbasecolors[color - 1] + (6*i/(SKIN_RAMP_LENGTH-1)));
+	case SKINCOLOR_MAGENTA:
+		// 9 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+			if (i == 0)
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1]); // Lightest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + (i >> 1) + 1);
+		break;
+
+	case SKINCOLOR_ROSY:
+		// 9 colors
+		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
+		{
+			if (i == 0)
+				dest_colormap[starttranscolor + i] = 0xfc; // Lightest
+			else
+				dest_colormap[starttranscolor + i] = (UINT8)(skinbasecolors[color - 1] + ((i - 1) >> 1));
+		}
 		break;
 
 	// Super colors, from lightest to darkest!
 	case SKINCOLOR_SUPER1:
 		// Super White
 		for (i = 0; i < 10; i++)
-			dest_colormap[starttranscolor + i] = 120; // True white
-		for (; i < SKIN_RAMP_LENGTH; i++) // White-yellow fade
-			dest_colormap[starttranscolor + i] = (UINT8)(96 + (i-10));
+			dest_colormap[starttranscolor + i] = (UINT8)0; // True white
+		for (; i < 12; i++) // White-yellow fade
+			dest_colormap[starttranscolor + i] = (UINT8)(80);
+		for (; i < 15; i++) // White-yellow fade
+			dest_colormap[starttranscolor + i] = (UINT8)(81 + (i-12));
+		dest_colormap[starttranscolor + 15] = (UINT8)(72);
 		break;
 
 	case SKINCOLOR_SUPER2:
 		// Super Bright
-		for (i = 0; i < 5; i++) // White-yellow fade
-			dest_colormap[starttranscolor + i] = (UINT8)(96 + i);
-		dest_colormap[starttranscolor + 5] = 112; // Golden shine
-		for (i = 0; i < 8; i++) // Yellow
-			dest_colormap[starttranscolor + (i+6)] = (UINT8)(101 + (i>>1));
-		for (i = 0; i < 2; i++) // With a fine golden finish! :3
-			dest_colormap[starttranscolor + (i+14)] = (UINT8)(113 + i);
+		dest_colormap[starttranscolor] = (UINT8)(0);
+		for (i = 1; i < 4; i++) // White-yellow fade
+			dest_colormap[starttranscolor + i] = (UINT8)(80 + (i-1));
+		for (; i < 6; i++) // Yellow
+			dest_colormap[starttranscolor + i] = (UINT8)(83);
+		for (; i < 8; i++) // Yellow
+			dest_colormap[starttranscolor + i] = (UINT8)(72);
+		for (; i < 14; i++) // Yellow
+			dest_colormap[starttranscolor + i] = (UINT8)(73);
+		for (; i < 16; i++) // With a fine golden finish! :3
+			dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-14));
 		break;
 
 	case SKINCOLOR_SUPER3:
 		// Super Yellow
-		for (i = 0; i < 3; i++) // White-yellow fade
-			dest_colormap[starttranscolor + i] = (UINT8)(98 + i);
-		dest_colormap[starttranscolor + 3] = 112; // Golden shine
-		for (i = 0; i < 8; i++) // Yellow
-			dest_colormap[starttranscolor + (i+4)] = (UINT8)(101 + (i>>1));
-		for (i = 0; i < 4; i++) // With a fine golden finish! :3
-			dest_colormap[starttranscolor + (i+12)] = (UINT8)(113 + i);
+		for (i = 0; i < 2; i++) // White-yellow fade
+			dest_colormap[starttranscolor + i] = (UINT8)(81 + i);
+		for (; i < 4; i++)
+			dest_colormap[starttranscolor + i] = (UINT8)(83);
+		for (; i < 6; i++) // Yellow
+			dest_colormap[starttranscolor + i] = (UINT8)(72);
+		for (; i < 12; i++) // Yellow
+			dest_colormap[starttranscolor + i] = (UINT8)(73);
+		for (; i < 16; i++) // With a fine golden finish! :3
+			dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-12));
 		break;
 
 	case SKINCOLOR_SUPER4:
 		// "The SSNTails"
-		dest_colormap[starttranscolor] = 112; // Golden shine
-		for (i = 0; i < 8; i++) // Yellow
-			dest_colormap[starttranscolor + (i+1)] = (UINT8)(101 + (i>>1));
-		for (i = 0; i < 7; i++) // With a fine golden finish! :3
-			dest_colormap[starttranscolor + (i+9)] = (UINT8)(113 + i);
+		dest_colormap[starttranscolor] = 83; // Golden shine
+		for (i = 1; i < 3; i++) // Yellow
+			dest_colormap[starttranscolor + i] = (UINT8)(72);
+		for (; i < 9; i++) // Yellow
+			dest_colormap[starttranscolor + i] = (UINT8)(73);
+		for (; i < 16; i++) // With a fine golden finish! :3
+			dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-9));
 		break;
 
 	case SKINCOLOR_SUPER5:
 		// Golden Delicious
-		for (i = 0; i < 8; i++) // Yellow
-			dest_colormap[starttranscolor + i] = (UINT8)(101 + (i>>1));
-		for (i = 0; i < 7; i++) // With a fine golden finish! :3
-			dest_colormap[starttranscolor + (i+8)] = (UINT8)(113 + i);
-		dest_colormap[starttranscolor + 15] = 155;
+		for (i = 0; i < 2; i++) // Yellow
+			dest_colormap[starttranscolor + i] = (UINT8)(72);
+		for (; i < 8; i++) // Yellow
+			dest_colormap[starttranscolor + i] = (UINT8)(73);
+		for (; i < 15; i++) // With a fine golden finish! :3
+			dest_colormap[starttranscolor + i] = (UINT8)(64 + (i-8));
+		dest_colormap[starttranscolor + 15] = (UINT8)63;
 		break;
 
-	// Super Tails
+	// Super Tails and Knuckles, who really should be dummied out by now
 	case SKINCOLOR_TSUPER1:
-		for (i = 0; i < 10; i++) // white
-			dest_colormap[starttranscolor + i] = 120;
-		for (; i < SKIN_RAMP_LENGTH; i++) // orange
-			dest_colormap[starttranscolor + i] = (UINT8)(80 + (i-10));
-		break;
-
 	case SKINCOLOR_TSUPER2:
-		for (i = 0; i < 4; i++) // white
-			dest_colormap[starttranscolor + i] = 120;
-		for (; i < SKIN_RAMP_LENGTH; i++) // orange
-			dest_colormap[starttranscolor + i] = (UINT8)(80 + ((i-4)>>1));
-		break;
-
 	case SKINCOLOR_TSUPER3:
-		dest_colormap[starttranscolor] = 120; // pure white
-		dest_colormap[starttranscolor+1] = 120;
-		for (i = 2; i < SKIN_RAMP_LENGTH; i++) // orange
-			dest_colormap[starttranscolor + i] = (UINT8)(80 + ((i-2)>>1));
-		break;
-
 	case SKINCOLOR_TSUPER4:
-		dest_colormap[starttranscolor] = 120; // pure white
-		for (i = 1; i < 9; i++) // orange
-			dest_colormap[starttranscolor + i] = (UINT8)(80 + (i-1));
-		for (; i < SKIN_RAMP_LENGTH; i++) // gold
-			dest_colormap[starttranscolor + i] = (UINT8)(115 + (5*(i-9)/7));
-		break;
-
 	case SKINCOLOR_TSUPER5:
-		for (i = 0; i < 8; i++) // orange
-			dest_colormap[starttranscolor + i] = (UINT8)(80 + i);
-		for (; i < SKIN_RAMP_LENGTH; i++) // gold
-			dest_colormap[starttranscolor + i] = (UINT8)(115 + (5*(i-8)/8));
-		break;
-
-	// Super Knuckles
 	case SKINCOLOR_KSUPER1:
-		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
-			dest_colormap[starttranscolor + i] = (UINT8)(120 + (i >> 2));
-		break;
-
 	case SKINCOLOR_KSUPER2:
-		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
-			dest_colormap[starttranscolor + i] = (UINT8)(120 + (6*i/SKIN_RAMP_LENGTH));
-		break;
-
 	case SKINCOLOR_KSUPER3:
-		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
-			dest_colormap[starttranscolor + i] = (UINT8)(120 + (i >> 1));
-		break;
-
 	case SKINCOLOR_KSUPER4:
-		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
-			dest_colormap[starttranscolor + i] = (UINT8)(121 + (i >> 1));
-		break;
-
 	case SKINCOLOR_KSUPER5:
 		for (i = 0; i < SKIN_RAMP_LENGTH; i++)
-			dest_colormap[starttranscolor + i] = (UINT8)(122 + (i >> 1));
+			dest_colormap[starttranscolor + i] = 0xFF;
 		break;
 
 	default:
diff --git a/src/r_draw.h b/src/r_draw.h
index 061a271b15be4d466d108b2b313f9e389a738792..0ece26487cde450c0fea2029d773d021a0e3408b 100644
--- a/src/r_draw.h
+++ b/src/r_draw.h
@@ -60,6 +60,16 @@ extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep;
 extern UINT8 *ds_source; // start of a 64*64 tile image
 extern UINT8 *ds_transmap;
 
+#ifdef ESLOPE
+typedef struct {
+	float x, y, z;
+} floatv3_t;
+
+extern pslope_t *ds_slope; // Current slope being used
+extern floatv3_t ds_su, ds_sv, ds_sz; // Vectors for... stuff?
+extern float focallengthf, zeroheight;
+#endif
+
 // Variable flat sizes
 extern UINT32 nflatxshift;
 extern UINT32 nflatyshift;
@@ -141,6 +151,12 @@ void ASMCALL R_DrawSpan_8_MMX(void);
 void R_DrawTranslatedColumn_8(void);
 void R_DrawTranslatedTranslucentColumn_8(void);
 void R_DrawSpan_8(void);
+#ifdef ESLOPE
+void R_CalcTiltedLighting(fixed_t start, fixed_t end);
+void R_DrawTiltedSpan_8(void);
+void R_DrawTiltedTranslucentSpan_8(void);
+void R_DrawTiltedSplat_8(void);
+#endif
 void R_DrawSplat_8(void);
 void R_DrawTranslucentSplat_8(void);
 void R_DrawTranslucentSpan_8(void);
diff --git a/src/r_draw8.c b/src/r_draw8.c
index e0264ba921a1b2ee3ec7824ba86ffe17a5a86db9..c42f5d869b72d779d1a358e0a267d6074a7d3764 100644
--- a/src/r_draw8.c
+++ b/src/r_draw8.c
@@ -105,7 +105,7 @@ void R_DrawColumn_8(void)
 	}
 }
 
-#define TRANSPARENTPIXEL 247
+#define TRANSPARENTPIXEL 255
 
 void R_Draw2sMultiPatchColumn_8(void)
 {
@@ -526,6 +526,447 @@ void R_DrawSpan_8 (void)
 	}
 }
 
+#ifdef ESLOPE
+// R_CalcTiltedLighting
+// Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly.
+static INT32 tiltlighting[MAXVIDWIDTH];
+void R_CalcTiltedLighting(fixed_t start, fixed_t end)
+{
+	// ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version
+	// of this function. Here's my own.
+	INT32 left = ds_x1, right = ds_x2;
+	fixed_t step = (end-start)/(ds_x2-ds_x1+1);
+	INT32 i;
+
+	// I wanna do some optimizing by checking for out-of-range segments on either side to fill in all at once,
+	// but I'm too bad at coding to not crash the game trying to do that. I guess this is fast enough for now...
+
+	for (i = left; i <= right; i++) {
+		tiltlighting[i] = (start += step) >> FRACBITS;
+		if (tiltlighting[i] < 0)
+			tiltlighting[i] = 0;
+		else if (tiltlighting[i] >= MAXLIGHTSCALE)
+			tiltlighting[i] = MAXLIGHTSCALE-1;
+	}
+}
+
+
+/**	\brief The R_DrawTiltedSpan_8 function
+	Draw slopes! Holy sheit!
+*/
+void R_DrawTiltedSpan_8(void)
+{
+	// x1, x2 = ds_x1, ds_x2
+	int width = ds_x2 - ds_x1;
+	double iz, uz, vz;
+	UINT32 u, v;
+	int i;
+
+	UINT8 *source;
+	UINT8 *colormap;
+	UINT8 *dest;
+
+	double startz, startu, startv;
+	double izstep, uzstep, vzstep;
+	double endz, endu, endv;
+	UINT32 stepu, stepv;
+
+	iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx);
+
+	// Lighting is simple. It's just linear interpolation from start to end
+	{
+		float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f;
+		float lightstart, lightend;
+
+		lightend = (iz + ds_sz.x*width) * planelightfloat;
+		lightstart = iz * planelightfloat;
+
+		R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend));
+		//CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf);
+	}
+
+	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
+	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
+
+	dest = ylookup[ds_y] + columnofs[ds_x1];
+	source = ds_source;
+	//colormap = ds_colormap;
+
+#if 0	// The "perfect" reference version of this routine. Pretty slow.
+		// Use it only to see how things are supposed to look.
+	i = 0;
+	do
+	{
+		double z = 1.f/iz;
+		u = (INT64)(uz*z) + viewx;
+		v = (INT64)(vz*z) + viewy;
+
+		colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+
+		*dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
+		dest++;
+		iz += ds_sz.x;
+		uz += ds_su.x;
+		vz += ds_sv.x;
+	} while (--width >= 0);
+#else
+#define SPANSIZE 16
+#define INVSPAN	0.0625f
+
+	startz = 1.f/iz;
+	startu = uz*startz;
+	startv = vz*startz;
+
+	izstep = ds_sz.x * SPANSIZE;
+	uzstep = ds_su.x * SPANSIZE;
+	vzstep = ds_sv.x * SPANSIZE;
+	//x1 = 0;
+	width++;
+
+	while (width >= SPANSIZE)
+	{
+		iz += izstep;
+		uz += uzstep;
+		vz += vzstep;
+
+		endz = 1.f/iz;
+		endu = uz*endz;
+		endv = vz*endz;
+		stepu = (INT64)((endu - startu) * INVSPAN);
+		stepv = (INT64)((endv - startv) * INVSPAN);
+		u = (INT64)(startu) + viewx;
+		v = (INT64)(startv) + viewy;
+
+		for (i = SPANSIZE-1; i >= 0; i--)
+		{
+			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+			*dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
+			dest++;
+			u += stepu;
+			v += stepv;
+		}
+		startu = endu;
+		startv = endv;
+		width -= SPANSIZE;
+	}
+	if (width > 0)
+	{
+		if (width == 1)
+		{
+			u = (INT64)(startu);
+			v = (INT64)(startv);
+			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+			*dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
+		}
+		else
+		{
+			double left = width;
+			iz += ds_sz.x * left;
+			uz += ds_su.x * left;
+			vz += ds_sv.x * left;
+
+			endz = 1.f/iz;
+			endu = uz*endz;
+			endv = vz*endz;
+			left = 1.f/left;
+			stepu = (INT64)((endu - startu) * left);
+			stepv = (INT64)((endv - startv) * left);
+			u = (INT64)(startu) + viewx;
+			v = (INT64)(startv) + viewy;
+
+			for (; width != 0; width--)
+			{
+				colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+				*dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
+				dest++;
+				u += stepu;
+				v += stepv;
+			}
+		}
+	}
+#endif
+}
+
+/**	\brief The R_DrawTiltedTranslucentSpan_8 function
+	Like DrawTiltedSpan, but translucent
+*/
+void R_DrawTiltedTranslucentSpan_8(void)
+{
+	// x1, x2 = ds_x1, ds_x2
+	int width = ds_x2 - ds_x1;
+	double iz, uz, vz;
+	UINT32 u, v;
+	int i;
+
+	UINT8 *source;
+	UINT8 *colormap;
+	UINT8 *dest;
+
+	double startz, startu, startv;
+	double izstep, uzstep, vzstep;
+	double endz, endu, endv;
+	UINT32 stepu, stepv;
+
+	iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx);
+
+	// Lighting is simple. It's just linear interpolation from start to end
+	{
+		float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f;
+		float lightstart, lightend;
+
+		lightend = (iz + ds_sz.x*width) * planelightfloat;
+		lightstart = iz * planelightfloat;
+
+		R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend));
+		//CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf);
+	}
+
+	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
+	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
+
+	dest = ylookup[ds_y] + columnofs[ds_x1];
+	source = ds_source;
+	//colormap = ds_colormap;
+
+#if 0	// The "perfect" reference version of this routine. Pretty slow.
+		// Use it only to see how things are supposed to look.
+	i = 0;
+	do
+	{
+		double z = 1.f/iz;
+		u = (INT64)(uz*z) + viewx;
+		v = (INT64)(vz*z) + viewy;
+
+		colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+
+		*dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])];
+		dest++;
+		iz += ds_sz.x;
+		uz += ds_su.x;
+		vz += ds_sv.x;
+	} while (--width >= 0);
+#else
+#define SPANSIZE 16
+#define INVSPAN	0.0625f
+
+	startz = 1.f/iz;
+	startu = uz*startz;
+	startv = vz*startz;
+
+	izstep = ds_sz.x * SPANSIZE;
+	uzstep = ds_su.x * SPANSIZE;
+	vzstep = ds_sv.x * SPANSIZE;
+	//x1 = 0;
+	width++;
+
+	while (width >= SPANSIZE)
+	{
+		iz += izstep;
+		uz += uzstep;
+		vz += vzstep;
+
+		endz = 1.f/iz;
+		endu = uz*endz;
+		endv = vz*endz;
+		stepu = (INT64)((endu - startu) * INVSPAN);
+		stepv = (INT64)((endv - startv) * INVSPAN);
+		u = (INT64)(startu) + viewx;
+		v = (INT64)(startv) + viewy;
+
+		for (i = SPANSIZE-1; i >= 0; i--)
+		{
+			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+			*dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])];
+			dest++;
+			u += stepu;
+			v += stepv;
+		}
+		startu = endu;
+		startv = endv;
+		width -= SPANSIZE;
+	}
+	if (width > 0)
+	{
+		if (width == 1)
+		{
+			u = (INT64)(startu);
+			v = (INT64)(startv);
+			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+			*dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])];
+		}
+		else
+		{
+			double left = width;
+			iz += ds_sz.x * left;
+			uz += ds_su.x * left;
+			vz += ds_sv.x * left;
+
+			endz = 1.f/iz;
+			endu = uz*endz;
+			endv = vz*endz;
+			left = 1.f/left;
+			stepu = (INT64)((endu - startu) * left);
+			stepv = (INT64)((endv - startv) * left);
+			u = (INT64)(startu) + viewx;
+			v = (INT64)(startv) + viewy;
+
+			for (; width != 0; width--)
+			{
+				colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+				*dest = colormap[*(ds_transmap + (source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)] << 8) + dest[0])];
+				dest++;
+				u += stepu;
+				v += stepv;
+			}
+		}
+	}
+#endif
+}
+
+void R_DrawTiltedSplat_8(void)
+{
+	// x1, x2 = ds_x1, ds_x2
+	int width = ds_x2 - ds_x1;
+	double iz, uz, vz;
+	UINT32 u, v;
+	int i;
+
+	UINT8 *source;
+	UINT8 *colormap;
+	UINT8 *dest;
+
+	UINT8 val;
+
+	double startz, startu, startv;
+	double izstep, uzstep, vzstep;
+	double endz, endu, endv;
+	UINT32 stepu, stepv;
+
+	iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx);
+
+	// Lighting is simple. It's just linear interpolation from start to end
+	{
+		float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f;
+		float lightstart, lightend;
+
+		lightend = (iz + ds_sz.x*width) * planelightfloat;
+		lightstart = iz * planelightfloat;
+
+		R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend));
+		//CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf);
+	}
+
+	uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx);
+	vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx);
+
+	dest = ylookup[ds_y] + columnofs[ds_x1];
+	source = ds_source;
+	//colormap = ds_colormap;
+
+#if 0	// The "perfect" reference version of this routine. Pretty slow.
+		// Use it only to see how things are supposed to look.
+	i = 0;
+	do
+	{
+		double z = 1.f/iz;
+		u = (INT64)(uz*z) + viewx;
+		v = (INT64)(vz*z) + viewy;
+
+		colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+
+		val = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
+		if (val != TRANSPARENTPIXEL)
+			*dest = val;
+		dest++;
+		iz += ds_sz.x;
+		uz += ds_su.x;
+		vz += ds_sv.x;
+	} while (--width >= 0);
+#else
+#define SPANSIZE 16
+#define INVSPAN	0.0625f
+
+	startz = 1.f/iz;
+	startu = uz*startz;
+	startv = vz*startz;
+
+	izstep = ds_sz.x * SPANSIZE;
+	uzstep = ds_su.x * SPANSIZE;
+	vzstep = ds_sv.x * SPANSIZE;
+	//x1 = 0;
+	width++;
+
+	while (width >= SPANSIZE)
+	{
+		iz += izstep;
+		uz += uzstep;
+		vz += vzstep;
+
+		endz = 1.f/iz;
+		endu = uz*endz;
+		endv = vz*endz;
+		stepu = (INT64)((endu - startu) * INVSPAN);
+		stepv = (INT64)((endv - startv) * INVSPAN);
+		u = (INT64)(startu) + viewx;
+		v = (INT64)(startv) + viewy;
+
+		for (i = SPANSIZE-1; i >= 0; i--)
+		{
+			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+			val = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
+			if (val != TRANSPARENTPIXEL)
+				*dest = val;
+			dest++;
+			u += stepu;
+			v += stepv;
+		}
+		startu = endu;
+		startv = endv;
+		width -= SPANSIZE;
+	}
+	if (width > 0)
+	{
+		if (width == 1)
+		{
+			u = (INT64)(startu);
+			v = (INT64)(startv);
+			colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+			val = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
+			if (val != TRANSPARENTPIXEL)
+				*dest = val;
+		}
+		else
+		{
+			double left = width;
+			iz += ds_sz.x * left;
+			uz += ds_su.x * left;
+			vz += ds_sv.x * left;
+
+			endz = 1.f/iz;
+			endu = uz*endz;
+			endv = vz*endz;
+			left = 1.f/left;
+			stepu = (INT64)((endu - startu) * left);
+			stepv = (INT64)((endv - startv) * left);
+			u = (INT64)(startu) + viewx;
+			v = (INT64)(startv) + viewy;
+
+			for (; width != 0; width--)
+			{
+				colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
+				val = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]];
+				if (val != TRANSPARENTPIXEL)
+					*dest = val;
+				dest++;
+				u += stepu;
+				v += stepv;
+			}
+		}
+	}
+#endif
+}
+#endif // ESLOPE
+
 /**	\brief The R_DrawSplat_8 function
 	Just like R_DrawSpan_8, but skips transparent pixels.
 */
diff --git a/src/r_main.c b/src/r_main.c
index 1edcb815b5f5dbded625c5474bb5213a16f635bc..71b225e836f292f2d2d984e9c6d59a3548f487ce 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -114,15 +114,6 @@ INT32 viewangletox[FINEANGLES/2];
 // from clipangle to -clipangle.
 angle_t xtoviewangle[MAXVIDWIDTH+1];
 
-// UNUSED.
-// The finetangentgent[angle+FINEANGLES/4] table
-// holds the fixed_t tangent values for view angles,
-// ranging from INT32_MIN to 0 to INT32_MAX.
-
-#if !(defined _NDS) || !(defined NONET)
-fixed_t *finecosine = &finesine[FINEANGLES/4];
-#endif
-
 lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE];
 lighttable_t *scalelightfixed[MAXLIGHTSCALE];
 lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ];
@@ -316,13 +307,13 @@ angle_t R_PointToAngle(fixed_t x, fixed_t y)
 	x >= 0 ?
 	y >= 0 ?
 		(x > y) ? tantoangle[SlopeDiv(y,x)] :                          // octant 0
-		ANGLE_90-1-tantoangle[SlopeDiv(x,y)] :                         // octant 1
+		ANGLE_90-tantoangle[SlopeDiv(x,y)] :                           // octant 1
 		x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] :                   // octant 8
 		ANGLE_270+tantoangle[SlopeDiv(x,y)] :                          // octant 7
-		y >= 0 ? (x = -x) > y ? ANGLE_180-1-tantoangle[SlopeDiv(y,x)] :// octant 3
+		y >= 0 ? (x = -x) > y ? ANGLE_180-tantoangle[SlopeDiv(y,x)] :  // octant 3
 		ANGLE_90 + tantoangle[SlopeDiv(x,y)] :                         // octant 2
-		(x = -x) > (y = -y) ? ANGLE_180+tantoangle[ SlopeDiv(y,x)] :   // octant 4
-		ANGLE_270-1-tantoangle[SlopeDiv(x,y)] :                        // octant 5
+		(x = -x) > (y = -y) ? ANGLE_180+tantoangle[SlopeDiv(y,x)] :    // octant 4
+		ANGLE_270-tantoangle[SlopeDiv(x,y)] :                          // octant 5
 		0;
 }
 
@@ -332,13 +323,13 @@ angle_t R_PointToAngle2(fixed_t pviewx, fixed_t pviewy, fixed_t x, fixed_t y)
 	x >= 0 ?
 	y >= 0 ?
 		(x > y) ? tantoangle[SlopeDiv(y,x)] :                          // octant 0
-		ANGLE_90-1-tantoangle[SlopeDiv(x,y)] :                         // octant 1
+		ANGLE_90-tantoangle[SlopeDiv(x,y)] :                           // octant 1
 		x > (y = -y) ? 0-tantoangle[SlopeDiv(y,x)] :                   // octant 8
 		ANGLE_270+tantoangle[SlopeDiv(x,y)] :                          // octant 7
-		y >= 0 ? (x = -x) > y ? ANGLE_180-1-tantoangle[SlopeDiv(y,x)] :// octant 3
+		y >= 0 ? (x = -x) > y ? ANGLE_180-tantoangle[SlopeDiv(y,x)] :  // octant 3
 		ANGLE_90 + tantoangle[SlopeDiv(x,y)] :                         // octant 2
-		(x = -x) > (y = -y) ? ANGLE_180+tantoangle[ SlopeDiv(y,x)] :   // octant 4
-		ANGLE_270-1-tantoangle[SlopeDiv(x,y)] :                        // octant 5
+		(x = -x) > (y = -y) ? ANGLE_180+tantoangle[SlopeDiv(y,x)] :    // octant 4
+		ANGLE_270-tantoangle[SlopeDiv(x,y)] :                          // octant 5
 		0;
 }
 
@@ -527,6 +518,8 @@ static void R_InitTextureMapping(void)
 	focallength = FixedDiv(centerxfrac,
 		FINETANGENT(FINEANGLES/4+/*cv_fov.value*/ FIELDOFVIEW/2));
 
+	focallengthf = FIXED_TO_FLOAT(focallength);
+
 	for (i = 0; i < FINEANGLES/2; i++)
 	{
 		if (FINETANGENT(i) > FRACUNIT*2)
@@ -1276,7 +1269,7 @@ void R_RenderPlayerView(player_t *player)
 		if (cv_homremoval.value == 1)
 			V_DrawFill(0, 0, vid.width, vid.height, 31); // No HOM effect!
 		else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted.
-			V_DrawFill(0, 0, vid.width, vid.height, 128+(timeinmap&15));
+			V_DrawFill(0, 0, vid.width, vid.height, 32+(timeinmap&15));
 	}
 
 	portalrender = 0;
diff --git a/src/r_plane.c b/src/r_plane.c
index dcff25c1304fd45deba11b9845cdaa40f23c7658..417f0360a8856f3e3ed1381b29384c5983905f79 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -28,6 +28,8 @@
 
 #include "p_setup.h" // levelflats
 
+#include "p_slopes.h"
+
 //
 // opening
 //
@@ -74,7 +76,7 @@ static INT32 spanstart[MAXVIDHEIGHT];
 //
 // texture mapping
 //
-static lighttable_t **planezlight;
+lighttable_t **planezlight;
 static fixed_t planeheight;
 
 //added : 10-02-98: yslopetab is what yslope used to be,
@@ -327,6 +329,11 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
 	if (pindex >= MAXLIGHTZ)
 		pindex = MAXLIGHTZ - 1;
 
+#ifdef ESLOPE
+	if (currentplane->slope)
+		ds_colormap = colormaps;
+	else
+#endif
 	ds_colormap = planezlight[pindex];
 
 	if (currentplane->extra_colormap)
@@ -423,11 +430,18 @@ 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)
+	ffloor_t *pfloor
+#ifdef ESLOPE
+			, pslope_t *slope
+#endif
+			)
 {
 	visplane_t *check;
 	unsigned hash;
 
+#ifdef ESLOPE
+	if (slope); else // Don't mess with this right now if a slope is involved
+#endif
 	if (plangle != 0)
 	{
 		// Add the view offset, rotated by the plane angle.
@@ -462,7 +476,11 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 			&& xoff == check->xoffs && yoff == check->yoffs
 			&& planecolormap == check->extra_colormap
 			&& !pfloor && !check->ffloor && check->viewz == viewz
-			&& check->viewangle == viewangle)
+			&& check->viewangle == viewangle
+#ifdef ESLOPE
+			&& check->slope == slope
+#endif
+			)
 		{
 			return check;
 		}
@@ -485,6 +503,9 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 #ifdef POLYOBJECTS_PLANES
 	check->polyobj = NULL;
 #endif
+#ifdef ESLOPE
+	check->slope = slope;
+#endif
 
 	memset(check->top, 0xff, sizeof (check->top));
 	memset(check->bottom, 0x00, sizeof (check->bottom));
@@ -551,6 +572,9 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop)
 		new_pl->plangle = pl->plangle;
 #ifdef POLYOBJECTS_PLANES
 		new_pl->polyobj = pl->polyobj;
+#endif
+#ifdef ESLOPE
+		new_pl->slope = pl->slope;
 #endif
 		pl = new_pl;
 		pl->minx = start;
@@ -726,31 +750,15 @@ void R_DrawSinglePlane(visplane_t *pl)
 		// Hacked up support for alpha value in software mode Tails 09-24-2002 (sidenote: ported to polys 10-15-2014, there was no time travel involved -Red)
 		if (pl->polyobj->translucency >= 10)
 			return; // Don't even draw it
-		else if (pl->polyobj->translucency == 9)
-			ds_transmap = ((tr_trans90)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-		else if (pl->polyobj->translucency == 8)
-			ds_transmap = ((tr_trans80)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-		else if (pl->polyobj->translucency == 7)
-			ds_transmap = ((tr_trans70)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-		else if (pl->polyobj->translucency == 6)
-			ds_transmap = ((tr_trans60)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-		else if (pl->polyobj->translucency == 5)
-			ds_transmap = ((tr_trans50)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-		else if (pl->polyobj->translucency == 4)
-			ds_transmap = ((tr_trans40)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-		else if (pl->polyobj->translucency == 3)
-			ds_transmap = ((tr_trans30)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-		else if (pl->polyobj->translucency == 2)
-			ds_transmap = ((tr_trans20)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-		else if (pl->polyobj->translucency == 1)
-			ds_transmap = ((tr_trans10)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		else if (pl->polyobj->translucency > 0)
+			ds_transmap = transtables + ((pl->polyobj->translucency-1)<<FF_TRANSSHIFT);
 		else // Opaque, but allow transparent flat pixels
 			spanfunc = splatfunc;
 
 		if (pl->extra_colormap && pl->extra_colormap->fog)
 			light = (pl->lightlevel >> LIGHTSEGSHIFT);
 		else
-		light = LIGHTLEVELS-1;
+			light = LIGHTLEVELS-1;
 
 	} else
 #endif
@@ -781,23 +789,23 @@ void R_DrawSinglePlane(visplane_t *pl)
 			if (pl->ffloor->alpha < 12)
 				return; // Don't even draw it
 			else if (pl->ffloor->alpha < 38)
-				ds_transmap = ((tr_trans90)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+				ds_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT);
 			else if (pl->ffloor->alpha < 64)
-				ds_transmap = ((tr_trans80)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+				ds_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT);
 			else if (pl->ffloor->alpha < 89)
-				ds_transmap = ((tr_trans70)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+				ds_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT);
 			else if (pl->ffloor->alpha < 115)
-				ds_transmap = ((tr_trans60)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+				ds_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT);
 			else if (pl->ffloor->alpha < 140)
-				ds_transmap = ((tr_trans50)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+				ds_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
 			else if (pl->ffloor->alpha < 166)
-				ds_transmap = ((tr_trans40)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+				ds_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT);
 			else if (pl->ffloor->alpha < 192)
-				ds_transmap = ((tr_trans30)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+				ds_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT);
 			else if (pl->ffloor->alpha < 217)
-				ds_transmap = ((tr_trans20)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+				ds_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT);
 			else if (pl->ffloor->alpha < 243)
-				ds_transmap = ((tr_trans10)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+				ds_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT);
 			else // Opaque, but allow transparent flat pixels
 				spanfunc = splatfunc;
 
@@ -814,7 +822,11 @@ void R_DrawSinglePlane(visplane_t *pl)
 		else light = (pl->lightlevel >> LIGHTSEGSHIFT);
 
 #ifndef NOWATER
-		if (pl->ffloor->flags & FF_RIPPLE)
+		if (pl->ffloor->flags & FF_RIPPLE
+#ifdef ESLOPE
+				&& !pl->slope
+#endif
+			)
 		{
 			INT32 top, bottom;
 
@@ -842,6 +854,9 @@ void R_DrawSinglePlane(visplane_t *pl)
 	}
 	else light = (pl->lightlevel >> LIGHTSEGSHIFT);
 
+#ifdef ESLOPE
+	if (!pl->slope) // Don't mess with angle on slopes! We'll handle this ourselves later
+#endif
 	if (viewangle != pl->viewangle)
 	{
 		memset(cachedheight, 0, sizeof (cachedheight));
@@ -915,6 +930,106 @@ void R_DrawSinglePlane(visplane_t *pl)
 	if (light < 0)
 		light = 0;
 
+#ifdef ESLOPE
+	if (pl->slope) {
+		// Potentially override other stuff for now cus we're mean. :< But draw a slope plane!
+		// I copied ZDoom's code and adapted it to SRB2... -Red
+		floatv3_t p, m, n;
+		float ang;
+		float vx, vy, vz;
+		float fudge;
+		// compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly
+		// use this as a temp var to store P_GetZAt's return value each time
+		fixed_t temp;
+
+		xoffs &= ((1 << (32-nflatshiftup))-1);
+		yoffs &= ((1 << (32-nflatshiftup))-1);
+
+		xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);
+		yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1);
+
+		// Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red
+		fudge = ((1<<nflatshiftup)+1.0f)/(1<<nflatshiftup);
+
+		xoffs *= fudge;
+		yoffs /= fudge;
+
+		vx = FIXED_TO_FLOAT(viewx+xoffs);
+		vy = FIXED_TO_FLOAT(viewy-yoffs);
+		vz = FIXED_TO_FLOAT(viewz);
+
+		temp = P_GetZAt(pl->slope, viewx, viewy);
+		zeroheight = FIXED_TO_FLOAT(temp);
+
+#define ANG2RAD(angle) ((float)((angle)*M_PI)/ANGLE_180)
+
+		// p is the texture origin in view space
+		// Don't add in the offsets at this stage, because doing so can result in
+		// errors if the flat is rotated.
+		ang = ANG2RAD(ANGLE_270 - viewangle);
+		p.x = vx * cos(ang) - vy * sin(ang);
+		p.z = vx * sin(ang) + vy * cos(ang);
+		temp = P_GetZAt(pl->slope, -xoffs, yoffs);
+		p.y = FIXED_TO_FLOAT(temp) - vz;
+
+		// m is the v direction vector in view space
+		ang = ANG2RAD(ANGLE_180 - viewangle - pl->plangle);
+		m.x = cos(ang);
+		m.z = sin(ang);
+
+		// n is the u direction vector in view space
+		n.x = sin(ang);
+		n.z = -cos(ang);
+
+		ang = ANG2RAD(pl->plangle);
+		temp = P_GetZAt(pl->slope, viewx + FLOAT_TO_FIXED(sin(ang)), viewy + FLOAT_TO_FIXED(cos(ang)));
+		m.y = FIXED_TO_FLOAT(temp) - zeroheight;
+		temp = P_GetZAt(pl->slope, viewx + FLOAT_TO_FIXED(cos(ang)), viewy - FLOAT_TO_FIXED(sin(ang)));
+		n.y = FIXED_TO_FLOAT(temp) - zeroheight;
+
+		m.x /= fudge;
+		m.y /= fudge;
+		m.z /= fudge;
+
+		n.x *= fudge;
+		n.y *= fudge;
+		n.z *= fudge;
+
+		// Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using.
+#define CROSS(d, v1, v2) \
+   d.x = (v1.y * v2.z) - (v1.z * v2.y);\
+   d.y = (v1.z * v2.x) - (v1.x * v2.z);\
+   d.z = (v1.x * v2.y) - (v1.y * v2.x)
+		CROSS(ds_su, p, m);
+		CROSS(ds_sv, p, n);
+		CROSS(ds_sz, m, n);
+#undef CROSS
+
+		ds_su.z *= focallengthf;
+		ds_sv.z *= focallengthf;
+		ds_sz.z *= focallengthf;
+
+		// Premultiply the texture vectors with the scale factors
+#define SFMULT 65536.f*(1<<nflatshiftup)
+		ds_su.x *= SFMULT;
+		ds_su.y *= SFMULT;
+		ds_su.z *= SFMULT;
+		ds_sv.x *= SFMULT;
+		ds_sv.y *= SFMULT;
+		ds_sv.z *= SFMULT;
+#undef SFMULT
+
+		if (spanfunc == R_DrawTranslucentSpan_8)
+			spanfunc = R_DrawTiltedTranslucentSpan_8;
+		else if (spanfunc == splatfunc)
+			spanfunc = R_DrawTiltedSplat_8;
+		else
+			spanfunc = R_DrawTiltedSpan_8;
+
+		planezlight = scalelight[light];
+	} else
+#endif // ESLOPE
+
 	planezlight = zlight[light];
 
 	// set the maximum value for unsigned
@@ -951,7 +1066,7 @@ using the palette colors.
 	if (spanfunc == R_DrawSpan_8)
 	{
 		INT32 i;
-		ds_transmap = ((tr_trans50)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		ds_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
 		spanfunc = R_DrawTranslucentSpan_8;
 		for (i=0; i<4; i++)
 		{
diff --git a/src/r_plane.h b/src/r_plane.h
index f3a7f573fe90c0201f944430953327f29c999e17..239723ed1d6316c33efa6a44ab97c719df330ea8 100644
--- a/src/r_plane.h
+++ b/src/r_plane.h
@@ -61,6 +61,9 @@ typedef struct visplane_s
 #ifdef POLYOBJECTS_PLANES
 	polyobj_t *polyobj;
 #endif
+#ifdef ESLOPE
+	pslope_t *slope;
+#endif
 } visplane_t;
 
 extern visplane_t *floorplane;
@@ -79,6 +82,8 @@ extern fixed_t cachedxstep[MAXVIDHEIGHT];
 extern fixed_t cachedystep[MAXVIDHEIGHT];
 extern fixed_t basexscale, baseyscale;
 
+extern lighttable_t **planezlight;
+
 extern fixed_t *yslope;
 extern fixed_t distscale[MAXVIDWIDTH];
 
@@ -91,7 +96,11 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2);
 void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2);
 void R_DrawPlanes(void);
 visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle,
-	extracolormap_t *planecolormap, ffloor_t *ffloor);
+	extracolormap_t *planecolormap, ffloor_t *ffloor
+#ifdef ESLOPE
+	, pslope_t *slope
+#endif
+	);
 visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop);
 void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
 void R_PlaneBounds(visplane_t *plane);
@@ -110,6 +119,14 @@ typedef struct planemgr_s
 	INT16 f_clip[MAXVIDWIDTH];
 	INT16 c_clip[MAXVIDWIDTH];
 
+#ifdef ESLOPE
+	// For slope rendering; the height at the other end
+	fixed_t f_pos_slope;
+	fixed_t b_pos_slope;
+
+	struct pslope_s *slope;
+#endif
+
 	struct ffloor_s *ffloor;
 #ifdef POLYOBJECTS_PLANES
 	polyobj_t *polyobj;
diff --git a/src/r_segs.c b/src/r_segs.c
index 7467f532472ae35d9eca14373ee9faf95e2e7b45..04873b29cda604ef7fff122520e139b0edc0604f 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -22,6 +22,7 @@
 #include "d_netcmd.h"
 #include "m_misc.h"
 #include "p_local.h" // Camera...
+#include "p_slopes.h"
 #include "console.h" // con_clipviewtop
 
 // OPTIMIZE: closed two sided lines as single sided
@@ -50,12 +51,20 @@ static fixed_t rw_offset2; // for splats
 static fixed_t rw_scale, rw_scalestep;
 static fixed_t rw_midtexturemid, rw_toptexturemid, rw_bottomtexturemid;
 static INT32 worldtop, worldbottom, worldhigh, worldlow;
+#ifdef ESLOPE
+static INT32 worldtopslope, worldbottomslope, worldhighslope, worldlowslope; // worldtop/bottom at end of slope
+static fixed_t rw_toptextureslide, rw_midtextureslide, rw_bottomtextureslide; // Defines how to adjust Y offsets along the wall for slopes
+static fixed_t rw_midtextureback, rw_midtexturebackslide; // Values for masked midtexture height calculation
+#endif
 static fixed_t pixhigh, pixlow, pixhighstep, pixlowstep;
 static fixed_t topfrac, topstep;
 static fixed_t bottomfrac, bottomstep;
 
 static lighttable_t **walllights;
 static INT16 *maskedtexturecol;
+#ifdef ESLOPE
+static fixed_t *maskedtextureheight = NULL;
+#endif
 
 // ==========================================================================
 // R_Splats Wall Splats Drawer
@@ -174,7 +183,7 @@ static void R_DrawWallSplats(void)
 					colfunc = basecolfunc;
 				else
 				{
-					dc_transmap = ((tr_trans50 - 1)<<FF_TRANSSHIFT) + transtables;
+					dc_transmap = transtables + ((tr_trans50 - 1)<<FF_TRANSSHIFT);
 					colfunc = fuzzcolfunc;
 				}
 
@@ -295,39 +304,15 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 	switch (ldef->special)
 	{
 		case 900:
-			dc_transmap = ((tr_trans10)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-			colfunc = fuzzcolfunc;
-			break;
 		case 901:
-			dc_transmap = ((tr_trans20)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-			colfunc = fuzzcolfunc;
-			break;
 		case 902:
-			dc_transmap = ((tr_trans30)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-			colfunc = fuzzcolfunc;
-			break;
 		case 903:
-			dc_transmap = ((tr_trans40)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-			colfunc = fuzzcolfunc;
-			break;
 		case 904:
-			dc_transmap = ((tr_trans50)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-			colfunc = fuzzcolfunc;
-			break;
 		case 905:
-			dc_transmap = ((tr_trans60)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-			colfunc = fuzzcolfunc;
-			break;
 		case 906:
-			dc_transmap = ((tr_trans70)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-			colfunc = fuzzcolfunc;
-			break;
 		case 907:
-			dc_transmap = ((tr_trans80)<<FF_TRANSSHIFT) - 0x10000 + transtables;
-			colfunc = fuzzcolfunc;
-			break;
 		case 908:
-			dc_transmap = ((tr_trans90)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+			dc_transmap = transtables + ((ldef->special-900)<<FF_TRANSSHIFT);
 			colfunc = fuzzcolfunc;
 			break;
 		case 909:
@@ -345,7 +330,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 		if (curline->polyseg->translucency >= NUMTRANSMAPS)
 			return;
 
-		dc_transmap = ((curline->polyseg->translucency)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		dc_transmap = transtables + ((curline->polyseg->translucency-1)<<FF_TRANSSHIFT);
 		colfunc = fuzzcolfunc;
 	}
 
@@ -474,6 +459,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 			spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
 		}
 
+
+#ifndef ESLOPE
 		if (curline->linedef->flags & ML_DONTPEGBOTTOM)
 		{
 			dc_texturemid = front->floorheight > back->floorheight
@@ -492,12 +479,21 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 			dc_texturemid += (textureheight[texnum])*times;
 		else
 			dc_texturemid -= (textureheight[texnum])*times;
+#endif
 
 		dc_texheight = textureheight[texnum]>>FRACBITS;
 
 		// draw the columns
 		for (dc_x = x1; dc_x <= x2; dc_x++)
 		{
+#ifdef ESLOPE
+			dc_texturemid = ds->maskedtextureheight[dc_x];
+
+			if (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3))
+				dc_texturemid += (textureheight[texnum])*times + textureheight[texnum];
+			else
+				dc_texturemid -= (textureheight[texnum])*times;
+#endif
 			// calculate lighting
 			if (maskedtexturecol[dc_x] != INT16_MAX)
 			{
@@ -679,6 +675,10 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	r_lightlist_t   *rlight;
 	fixed_t         lheight;
 	line_t          *newline = NULL;
+#ifdef ESLOPE
+	// Render FOF sides kinda like normal sides, with the frac and step and everything
+	fixed_t         top_frac, top_step, bottom_frac, bottom_step;
+#endif
 
 	void (*colfunc_2s) (column_t *);
 
@@ -709,23 +709,23 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 		if (pfloor->alpha < 12)
 			return; // Don't even draw it
 		else if (pfloor->alpha < 38)
-			dc_transmap = ((tr_trans90)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+			dc_transmap = transtables + ((tr_trans90-1)<<FF_TRANSSHIFT);
 		else if (pfloor->alpha < 64)
-			dc_transmap = ((tr_trans80)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+			dc_transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT);
 		else if (pfloor->alpha < 89)
-			dc_transmap = ((tr_trans70)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+			dc_transmap = transtables + ((tr_trans70-1)<<FF_TRANSSHIFT);
 		else if (pfloor->alpha < 115)
-			dc_transmap = ((tr_trans60)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+			dc_transmap = transtables + ((tr_trans60-1)<<FF_TRANSSHIFT);
 		else if (pfloor->alpha < 140)
-			dc_transmap = ((tr_trans50)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+			dc_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
 		else if (pfloor->alpha < 166)
-			dc_transmap = ((tr_trans40)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+			dc_transmap = transtables + ((tr_trans40-1)<<FF_TRANSSHIFT);
 		else if (pfloor->alpha < 192)
-			dc_transmap = ((tr_trans30)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+			dc_transmap = transtables + ((tr_trans30-1)<<FF_TRANSSHIFT);
 		else if (pfloor->alpha < 217)
-			dc_transmap = ((tr_trans20)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+			dc_transmap = transtables + ((tr_trans20-1)<<FF_TRANSSHIFT);
 		else if (pfloor->alpha < 243)
-			dc_transmap = ((tr_trans10)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+			dc_transmap = transtables + ((tr_trans10-1)<<FF_TRANSSHIFT);
 		else
 			fuzzy = false; // Opaque
 
@@ -853,6 +853,34 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 		column2s_length = textures[texnum]->height;
 	}
 
+#ifdef ESLOPE
+	// Set heights according to plane, or slope, whichever
+	{
+		fixed_t left_top, right_top, left_bottom, right_bottom;
+
+		left_top = *pfloor->t_slope ? P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) : *pfloor->topheight;
+		right_top = *pfloor->t_slope ? P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) : *pfloor->topheight;
+		left_bottom = *pfloor->b_slope ? P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) : *pfloor->bottomheight;
+		right_bottom = *pfloor->b_slope ? P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) : *pfloor->bottomheight;
+
+		left_top -= viewz;
+		right_top -= viewz;
+		left_bottom -= viewz;
+		right_bottom -= viewz;
+
+		top_frac = centeryfrac - FixedMul(left_top, ds->scale1);
+		bottom_frac = centeryfrac - FixedMul(left_bottom, ds->scale1);
+		top_step = centeryfrac - FixedMul(right_top, ds->scale2);
+		bottom_step = centeryfrac - FixedMul(right_bottom, ds->scale2);
+
+		top_step = (top_step-top_frac)/(ds->x2-ds->x1+1);
+		bottom_step = (bottom_step-bottom_frac)/(ds->x2-ds->x1+1);
+
+		top_frac += top_step * (x1 - ds->x1);
+		bottom_frac += bottom_step * (x1 - ds->x1);
+	}
+#endif
+
 	// draw the columns
 	for (dc_x = x1; dc_x <= x2; dc_x++)
 	{
@@ -868,8 +896,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 				INT32 solid = 0;
 				INT32 lighteffect = 0;
 
+#ifdef ESLOPE
+				sprtopscreen = windowtop = top_frac;
+				sprbotscreen = windowbottom = bottom_frac;
+
+				top_frac += top_step;
+				bottom_frac += bottom_step;
+#else
 				sprtopscreen = windowtop = (centeryfrac - FixedMul((dc_texturemid - offsetvalue), spryscale));
 				sprbotscreen = windowbottom = FixedMul(*pfloor->topheight - *pfloor->bottomheight, spryscale) + sprtopscreen;
+#endif
 
 				// SoM: If column is out of range, why bother with it??
 				if (windowbottom < topbounds || windowtop > bottombounds)
@@ -1011,11 +1047,24 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 			 || ((signed)dc_texturemid < 0 && (spryscale) && (signed)(dc_texturemid)>>FRACBITS < (INT32_MIN / spryscale)))
 			{
 				spryscale += rw_scalestep;
+#ifdef ESLOPE
+				top_frac += top_step;
+				bottom_frac += bottom_step;
+#endif
 				continue;
 			}
 
+#ifdef ESLOPE
+			sprtopscreen = windowtop = top_frac;
+			sprbotscreen = windowbottom = bottom_frac;
+
+			top_frac += top_step;
+			bottom_frac += bottom_step;
+#else
 			sprtopscreen = windowtop = (centeryfrac - FixedMul((dc_texturemid - offsetvalue), spryscale));
 			sprbotscreen = windowbottom = FixedMul(*pfloor->topheight - *pfloor->bottomheight, spryscale) + sprtopscreen;
+#endif
+
 			dc_iscale = 0xffffffffu / (unsigned)spryscale;
 
 			// draw the texture
@@ -1061,6 +1110,7 @@ static void R_RenderSegLoop (void)
 
 	INT32     mid;
 	fixed_t texturecolumn = 0;
+	fixed_t oldtexturecolumn = -1;
 	INT32     top;
 	INT32     bottom;
 	INT32     i;
@@ -1197,6 +1247,17 @@ static void R_RenderSegLoop (void)
 		// calculate texture offset
 		angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT;
 		texturecolumn = rw_offset-FixedMul(FINETANGENT(angle),rw_distance);
+
+#ifdef ESLOPE
+		if (oldtexturecolumn != -1) {
+			rw_bottomtexturemid += FixedMul(rw_bottomtextureslide,  oldtexturecolumn-texturecolumn);
+			rw_midtexturemid    += FixedMul(rw_midtextureslide,     oldtexturecolumn-texturecolumn);
+			rw_toptexturemid    += FixedMul(rw_toptextureslide,     oldtexturecolumn-texturecolumn);
+			rw_midtextureback   += FixedMul(rw_midtexturebackslide, oldtexturecolumn-texturecolumn);
+		}
+		oldtexturecolumn = texturecolumn;
+#endif
+
 		texturecolumn >>= FRACBITS;
 
 		// texturecolumn and lighting are independent of wall tiers
@@ -1345,6 +1406,14 @@ static void R_RenderSegLoop (void)
 			// save texturecol
 			//  for backdrawing of masked mid texture
 			maskedtexturecol[rw_x] = (INT16)texturecolumn;
+
+#ifdef ESLOPE
+			if (maskedtextureheight != NULL) {
+				maskedtextureheight[rw_x] = (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3) ?
+											max(rw_midtexturemid, rw_midtextureback) :
+											min(rw_midtexturemid, rw_midtextureback));
+			}
+#endif
 		}
 
 		if (dc_numlights)
@@ -1397,23 +1466,31 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	fixed_t       hyp;
 	fixed_t       sineval;
 	angle_t       distangle, offsetangle;
-	fixed_t       vtop;
+	//fixed_t       vtop;
 	INT32           lightnum;
 	INT32           i, p;
 	lightlist_t   *light;
 	r_lightlist_t *rlight;
+#ifdef ESLOPE
+	vertex_t segleft, segright;
+	fixed_t ceilingfrontslide, floorfrontslide, ceilingbackslide, floorbackslide;
+#endif
 	static size_t maxdrawsegs = 0;
 
+	maskedtextureheight = NULL;
+
+	//initialize segleft and segright
+	memset(&segleft, 0x00, sizeof(segleft));
+	memset(&segright, 0x00, sizeof(segright));
+
 	if (ds_p == drawsegs+maxdrawsegs)
 	{
 		size_t pos = ds_p - drawsegs;
-		size_t pos2 = firstnewseg - drawsegs;
 		size_t newmax = maxdrawsegs ? maxdrawsegs*2 : 128;
 		if (firstseg)
 			firstseg = (drawseg_t *)(firstseg - drawsegs);
 		drawsegs = Z_Realloc(drawsegs, newmax*sizeof (*drawsegs), PU_STATIC, NULL);
 		ds_p = drawsegs + pos;
-		firstnewseg = drawsegs + pos2;
 		maxdrawsegs = newmax;
 		if (firstseg)
 			firstseg = drawsegs + (size_t)firstseg;
@@ -1502,8 +1579,80 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 	// calculate texture boundaries
 	//  and decide if floor / ceiling marks are needed
-	worldtop = frontsector->ceilingheight - viewz;
-	worldbottom = frontsector->floorheight - viewz;
+#ifdef ESLOPE
+	// Figure out map coordinates of where start and end are mapping to on seg, so we can clip right for slope bullshit
+	if (frontsector->hasslope || (backsector && backsector->hasslope)) // Commenting this out for FOFslop. -Red
+	{
+		angle_t temp;
+
+		// left
+		temp = xtoviewangle[start]+viewangle;
+
+		{
+			// Both lines can be written in slope-intercept form, so figure out line intersection
+			float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector...
+			///TODO: convert to FPU
+
+			a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y);
+			b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x);
+			c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y);
+
+			a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT));
+			b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT));
+			c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy);
+
+			det = a1*b2 - a2*b1;
+
+			ds_p->leftpos.x = segleft.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det);
+			ds_p->leftpos.y = segleft.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det);
+		}
+
+		// right
+		temp = xtoviewangle[stop]+viewangle;
+
+		{
+			// Both lines can be written in slope-intercept form, so figure out line intersection
+			float a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector...
+			///TODO: convert to FPU
+
+			a1 = FIXED_TO_FLOAT(curline->v2->y-curline->v1->y);
+			b1 = FIXED_TO_FLOAT(curline->v1->x-curline->v2->x);
+			c1 = a1*FIXED_TO_FLOAT(curline->v1->x) + b1*FIXED_TO_FLOAT(curline->v1->y);
+
+			a2 = -FIXED_TO_FLOAT(FINESINE(temp>>ANGLETOFINESHIFT));
+			b2 = FIXED_TO_FLOAT(FINECOSINE(temp>>ANGLETOFINESHIFT));
+			c2 = a2*FIXED_TO_FLOAT(viewx) + b2*FIXED_TO_FLOAT(viewy);
+
+			det = a1*b2 - a2*b1;
+
+			ds_p->rightpos.x = segright.x = FLOAT_TO_FIXED((b2*c1 - b1*c2)/det);
+			ds_p->rightpos.y = segright.y = FLOAT_TO_FIXED((a1*c2 - a2*c1)/det);
+		}
+	}
+
+	if (frontsector->c_slope) {
+		worldtop = P_GetZAt(frontsector->c_slope, segleft.x, segleft.y) - viewz;
+		worldtopslope = P_GetZAt(frontsector->c_slope, segright.x, segright.y) - viewz;
+	} else {
+		worldtopslope =
+#else
+	{
+#endif
+		worldtop = frontsector->ceilingheight - viewz;
+	}
+
+
+#ifdef ESLOPE
+	if (frontsector->f_slope) {
+		worldbottom = P_GetZAt(frontsector->f_slope, segleft.x, segleft.y) - viewz;
+		worldbottomslope = P_GetZAt(frontsector->f_slope, segright.x, segright.y) - viewz;
+	} else {
+		worldbottomslope =
+#else
+	{
+#endif
+		worldbottom = frontsector->floorheight - viewz;
+	}
 
 	midtexture = toptexture = bottomtexture = maskedtexture = 0;
 	ds_p->maskedtexturecol = NULL;
@@ -1524,27 +1673,72 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			if (ffloor[i].polyobj && (!ds_p->curline->polyseg || ffloor[i].polyobj != ds_p->curline->polyseg))
 				continue;
 #endif
+
+#ifdef ESLOPE
+			if (ffloor[i].slope) {
+				ffloor[i].f_pos = P_GetZAt(ffloor[i].slope, segleft.x, segleft.y) - viewz;
+				ffloor[i].f_pos_slope = P_GetZAt(ffloor[i].slope, segright.x, segright.y) - viewz;
+			} else
+				ffloor[i].f_pos_slope =
+#endif
 			ffloor[i].f_pos = ffloor[i].height - viewz;
 		}
 	}
 
+#ifdef ESLOPE
+	// Set up texture Y offset slides for sloped walls
+	rw_toptextureslide = rw_midtextureslide = rw_bottomtextureslide = 0;
+	ceilingfrontslide = floorfrontslide = ceilingbackslide = floorbackslide = 0;
+
+	{
+		angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y);
+
+		if (frontsector->f_slope)
+			floorfrontslide = FixedMul(frontsector->f_slope->zdelta, FINECOSINE((lineangle-frontsector->f_slope->xydirection)>>ANGLETOFINESHIFT));
+
+		if (frontsector->c_slope)
+			ceilingfrontslide = FixedMul(frontsector->c_slope->zdelta, FINECOSINE((lineangle-frontsector->c_slope->xydirection)>>ANGLETOFINESHIFT));
+
+		if (backsector && backsector->f_slope)
+			floorbackslide = FixedMul(backsector->f_slope->zdelta, FINECOSINE((lineangle-backsector->f_slope->xydirection)>>ANGLETOFINESHIFT));
+
+		if (backsector && backsector->c_slope)
+			ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT));
+	}
+#endif
+
 	if (!backsector)
 	{
 		// single sided line
 		midtexture = texturetranslation[sidedef->midtexture];
 		// a single sided line is terminal, so it must mark ends
 		markfloor = markceiling = true;
-
+#ifdef ESLOPE
+		if (!(linedef->flags & ML_EFFECT1)) {
+			if (linedef->flags & ML_DONTPEGBOTTOM)
+				rw_midtexturemid = frontsector->floorheight + textureheight[sidedef->midtexture] - viewz;
+			else
+				rw_midtexturemid = frontsector->ceilingheight;
+		}
+#endif
 		if (linedef->flags & ML_DONTPEGBOTTOM)
 		{
+#ifdef ESLOPE
+			rw_midtexturemid = worldbottom + textureheight[sidedef->midtexture];
+			rw_midtextureslide = floorfrontslide;
+#else
 			vtop = frontsector->floorheight + textureheight[sidedef->midtexture];
 			// bottom of texture at bottom
 			rw_midtexturemid = vtop - viewz;
+#endif
 		}
 		else
 		{
 			// top of texture at top
 			rw_midtexturemid = worldtop;
+#ifdef ESLOPE
+			rw_midtextureslide = ceilingfrontslide;
+#endif
 		}
 		rw_midtexturemid += sidedef->rowoffset;
 
@@ -1557,47 +1751,120 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	else
 	{
 		// two sided line
+
+#ifdef ESLOPE
+		if (backsector->c_slope) {
+			worldhigh = P_GetZAt(backsector->c_slope, segleft.x, segleft.y) - viewz;
+			worldhighslope = P_GetZAt(backsector->c_slope, segright.x, segright.y) - viewz;
+		} else {
+			worldhighslope =
+#else
+		{
+#endif
+			worldhigh = backsector->ceilingheight - viewz;
+		}
+
+
+#ifdef ESLOPE
+		if (backsector->f_slope) {
+			worldlow = P_GetZAt(backsector->f_slope, segleft.x, segleft.y) - viewz;
+			worldlowslope = P_GetZAt(backsector->f_slope, segright.x, segright.y) - viewz;
+		} else {
+			worldlowslope =
+#else
+		{
+#endif
+			worldlow = backsector->floorheight - viewz;
+		}
+
+
+		// hack to allow height changes in outdoor areas
+		if (frontsector->ceilingpic == skyflatnum
+			&& backsector->ceilingpic == skyflatnum)
+		{
+#ifdef ESLOPE
+			worldtopslope = worldhighslope =
+#endif
+			worldtop = worldhigh;
+		}
+
 		ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
 		ds_p->silhouette = 0;
 
-		if (frontsector->floorheight > backsector->floorheight)
+		if (
+#ifdef ESLOPE
+			worldbottomslope > worldlowslope ||
+#endif
+			worldbottom > worldlow)
 		{
 			ds_p->silhouette = SIL_BOTTOM;
+#ifdef ESLOPE
+			ds_p->bsilheight = (frontsector->f_slope ? INT32_MAX : frontsector->floorheight);
+#else
 			ds_p->bsilheight = frontsector->floorheight;
+#endif
 		}
+#ifdef ESLOPE
+		else if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz)
+#else
 		else if (backsector->floorheight > viewz)
+#endif
 		{
 			ds_p->silhouette = SIL_BOTTOM;
 			ds_p->bsilheight = INT32_MAX;
 			// ds_p->sprbottomclip = negonearray;
 		}
 
-		if (frontsector->ceilingheight < backsector->ceilingheight)
+		if (
+#ifdef ESLOPE
+			worldtopslope < worldhighslope ||
+#endif
+			worldtop < worldhigh)
 		{
 			ds_p->silhouette |= SIL_TOP;
+#ifdef ESLOPE
+			ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight);
+#else
 			ds_p->tsilheight = frontsector->ceilingheight;
+#endif
 		}
+#ifdef ESLOPE
+		else if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz)
+#else
 		else if (backsector->ceilingheight < viewz)
+#endif
 		{
 			ds_p->silhouette |= SIL_TOP;
 			ds_p->tsilheight = INT32_MIN;
 			// ds_p->sprtopclip = screenheightarray;
 		}
 
-		if (backsector->ceilingheight <= frontsector->floorheight)
+#ifdef ESLOPE
+		if (worldhigh <= worldbottom && worldhighslope <= worldbottomslope)
+#else
+		if (worldhigh <= worldbottom)
+#endif
 		{
 			ds_p->sprbottomclip = negonearray;
 			ds_p->bsilheight = INT32_MAX;
 			ds_p->silhouette |= SIL_BOTTOM;
 		}
 
-		if (backsector->floorheight >= frontsector->ceilingheight)
+#ifdef ESLOPE
+		if (worldlow >= worldtop && worldlowslope >= worldtopslope)
+#else
+		if (worldlow >= worldtop)
+#endif
 		{
 			ds_p->sprtopclip = screenheightarray;
 			ds_p->tsilheight = INT32_MIN;
 			ds_p->silhouette |= SIL_TOP;
 		}
 
+#ifdef ESLOPE
+		// This causes issues with slopes.
+		if (!(frontsector->f_slope || frontsector->c_slope || backsector->f_slope || backsector->c_slope))
+#endif
 		//SoM: 3/25/2000: This code fixes an automap bug that didn't check
 		// frontsector->ceiling and backsector->floor to see if a door was closed.
 		// Without the following code, sprites get displayed behind closed doors.
@@ -1616,17 +1883,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			}
 		}
 
-		worldhigh = backsector->ceilingheight - viewz;
-		worldlow = backsector->floorheight - viewz;
-
-		// hack to allow height changes in outdoor areas
-		if (frontsector->ceilingpic == skyflatnum
-			&& backsector->ceilingpic == skyflatnum)
-		{
-			worldtop = worldhigh;
-		}
-
 		if (worldlow != worldbottom
+#ifdef ESLOPE
+			|| worldlowslope != worldbottomslope
+			|| backsector->f_slope != frontsector->f_slope
+#endif
 		    || backsector->floorpic != frontsector->floorpic
 		    || backsector->lightlevel != frontsector->lightlevel
 		    //SoM: 3/22/2000: Check floor x and y offsets.
@@ -1649,6 +1910,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		}
 
 		if (worldhigh != worldtop
+#ifdef ESLOPE
+			|| worldhighslope != worldtopslope
+			|| backsector->c_slope != frontsector->c_slope
+#endif
 		    || backsector->ceilingpic != frontsector->ceilingpic
 		    || backsector->lightlevel != frontsector->lightlevel
 		    //SoM: 3/22/2000: Check floor x and y offsets.
@@ -1678,7 +1943,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		}
 
 		// check TOP TEXTURE
-		if (worldhigh < worldtop)
+		if (worldhigh < worldtop
+#ifdef ESLOPE
+				|| worldhighslope < worldtopslope
+#endif
+			)
 		{
 			// top texture
 			if ((linedef->flags & (ML_DONTPEGTOP) && (linedef->flags & ML_DONTPEGBOTTOM))
@@ -1691,49 +1960,100 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 				if (!toptexture) //Second side has no texture, use the first side's instead.
 					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[def->toptexture];
+					rw_toptextureslide = ceilingbackslide;
+#else
 					vtop = backsector->ceilingheight + textureheight[def->toptexture];
 					// bottom of texture
 					rw_toptexturemid = vtop - viewz;
+#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;
+#else
 					vtop = backsector->ceilingheight + textureheight[sidedef->toptexture];
 					// bottom of texture
 					rw_toptexturemid = vtop - viewz;
+#endif
 				}
 			}
 		}
 		// check BOTTOM TEXTURE
-		if (worldlow > worldbottom)     //seulement si VISIBLE!!!
+		if (worldlow > worldbottom
+#ifdef ESLOPE
+				|| worldlowslope > worldbottomslope
+#endif
+			)     //seulement si VISIBLE!!!
 		{
 			// bottom texture
 			bottomtexture = texturetranslation[sidedef->bottomtexture];
 
+#ifdef ESLOPE
+			if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked
+				if (linedef->flags & ML_DONTPEGBOTTOM)
+					rw_bottomtexturemid = frontsector->floorheight - viewz;
+				else
+					rw_bottomtexturemid = backsector->floorheight - viewz;
+			} else
+#endif
 			if (linedef->flags & ML_DONTPEGBOTTOM)
 			{
 				// bottom of texture at bottom
 				// top of texture at top
-				rw_bottomtexturemid = worldtop;
+				rw_bottomtexturemid = worldbottom;
+#ifdef ESLOPE
+				rw_bottomtextureslide = floorfrontslide;
+#endif
 			}
-			else    // top of texture at top
+			else {   // top of texture at top
 				rw_bottomtexturemid = worldlow;
+#ifdef ESLOPE
+				rw_bottomtextureslide = floorbackslide;
+#endif
+			}
 		}
 
 		rw_toptexturemid += sidedef->rowoffset;
@@ -1745,6 +2065,12 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			ffloor_t *rover;
 			ffloor_t *r2;
 			fixed_t   lowcut, highcut;
+#ifdef ESLOPE
+			fixed_t lowcutslope, highcutslope;
+
+			// Used for height comparisons and etc across FOFs and slopes
+			fixed_t high1, highslope1, low1, lowslope1, high2, highslope2, low2, lowslope2;
+#endif
 
 			//markceiling = markfloor = true;
 			maskedtexture = true;
@@ -1752,8 +2078,12 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			ds_p->thicksidecol = maskedtexturecol = lastopening - rw_x;
 			lastopening += rw_stopx - rw_x;
 
-			lowcut = frontsector->floorheight > backsector->floorheight ? frontsector->floorheight : backsector->floorheight;
-			highcut = frontsector->ceilingheight < backsector->ceilingheight ? frontsector->ceilingheight : backsector->ceilingheight;
+			lowcut = max(worldbottom, worldlow) + viewz;
+			highcut = min(worldtop, worldhigh) + viewz;
+#ifdef ESLOPE
+			lowcutslope = max(worldbottomslope, worldlowslope) + viewz;
+			highcutslope = min(worldtopslope, worldhighslope) + viewz;
+#endif
 
 			if (frontsector->ffloors && backsector->ffloors)
 			{
@@ -1764,16 +2094,33 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 						continue;
 					if (rover->flags & FF_INVERTSIDES)
 						continue;
-					if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
-						continue;
 
 					if (rover->norender == leveltime)
 						continue;
 
+#ifdef ESLOPE
+					if (*rover->t_slope) {
+						high1 = P_GetZAt(*rover->t_slope, segleft.x, segleft.y);
+						highslope1 = P_GetZAt(*rover->t_slope, segright.x, segright.y);
+					} else
+						high1 = highslope1 = *rover->topheight;
+					if (*rover->b_slope) {
+						low1 = P_GetZAt(*rover->b_slope, segleft.x, segleft.y);
+						lowslope1 = P_GetZAt(*rover->b_slope, segright.x, segright.y);
+					} else
+						low1 = lowslope1 = *rover->bottomheight;
+
+					if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
+						continue;
+#else
+					if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
+						continue;
+#endif
+
 					for (r2 = frontsector->ffloors; r2; r2 = r2->next)
 					{
 						if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)
-						    || *r2->topheight < lowcut || *r2->bottomheight > highcut)
+						    || *r2->topheight < lowcut || *r2->bottomheight > highcut) ///TODO: make these account for slopes -Red
 							continue;
 
 						if (r2->norender == leveltime)
@@ -1793,8 +2140,24 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 								continue;
 						}
 
+#ifdef ESLOPE
+						if (*r2->t_slope) {
+							high2 = P_GetZAt(*r2->t_slope, segleft.x, segleft.y);
+							highslope2 = P_GetZAt(*r2->t_slope, segright.x, segright.y);
+						} else
+							high2 = highslope2 = *r2->topheight;
+						if (*r2->b_slope) {
+							low2 = P_GetZAt(*r2->b_slope, segleft.x, segleft.y);
+							lowslope2 = P_GetZAt(*r2->b_slope, segright.x, segright.y);
+						} else
+							low2 = lowslope2 = *r2->bottomheight;
+
+						if ((high1 > high2 && highslope1 > highslope2) || (low1 < low2 && lowslope1 < lowslope2))
+							continue;
+#else
 						if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight)
 							continue;
+#endif
 
 						break;
 					}
@@ -1811,16 +2174,33 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 						continue;
 					if (!(rover->flags & FF_ALLSIDES))
 						continue;
-					if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
-						continue;
 
 					if (rover->norender == leveltime)
 						continue;
 
+#ifdef ESLOPE
+					if (*rover->t_slope) {
+						high1 = P_GetZAt(*rover->t_slope, segleft.x, segleft.y);
+						highslope1 = P_GetZAt(*rover->t_slope, segright.x, segright.y);
+					} else
+						high1 = highslope1 = *rover->topheight;
+					if (*rover->b_slope) {
+						low1 = P_GetZAt(*rover->b_slope, segleft.x, segleft.y);
+						lowslope1 = P_GetZAt(*rover->b_slope, segright.x, segright.y);
+					} else
+						low1 = lowslope1 = *rover->bottomheight;
+
+					if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope))
+						continue;
+#else
+					if (*rover->topheight < lowcut || *rover->bottomheight > highcut)
+						continue;
+#endif
+
 					for (r2 = backsector->ffloors; r2; r2 = r2->next)
 					{
 						if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)
-						    || *r2->topheight < lowcut || *r2->bottomheight > highcut)
+						    || *r2->topheight < lowcut || *r2->bottomheight > highcut) ///TODO: make these account for slopes -Red
 							continue;
 
 						if (r2->norender == leveltime)
@@ -1840,8 +2220,24 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 								continue;
 						}
 
+#ifdef ESLOPE
+						if (*r2->t_slope) {
+							high2 = P_GetZAt(*r2->t_slope, segleft.x, segleft.y);
+							highslope2 = P_GetZAt(*r2->t_slope, segright.x, segright.y);
+						} else
+							high2 = highslope2 = *r2->topheight;
+						if (*r2->b_slope) {
+							low2 = P_GetZAt(*r2->b_slope, segleft.x, segleft.y);
+							lowslope2 = P_GetZAt(*r2->b_slope, segright.x, segright.y);
+						} else
+							low2 = lowslope2 = *r2->bottomheight;
+
+						if ((high1 > high2 && highslope1 > highslope2) || (low1 < low2 && lowslope1 < lowslope2))
+							continue;
+#else
 						if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight)
 							continue;
+#endif
 
 						break;
 					}
@@ -1858,11 +2254,21 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 				{
 					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || rover->flags & FF_INVERTSIDES)
 						continue;
-					if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight)
-						continue;
 					if (rover->norender == leveltime)
 						continue;
 
+#ifdef ESLOPE
+					// Oy vey.
+					if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz
+							&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz)
+							||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz
+							&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz))
+						continue;
+#else
+					if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight)
+						continue;
+#endif
+
 					ds_p->thicksides[i] = rover;
 					i++;
 				}
@@ -1873,12 +2279,27 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 				{
 					if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_ALLSIDES))
 						continue;
+					if (rover->norender == leveltime)
+						continue;
+#ifdef ESLOPE
+					// Oy vey.
+					if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz
+							&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz)
+							||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz
+							&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz))
+						continue;
+
+					if ((	   (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldlow+viewz
+							&& (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldlowslope+viewz)
+							||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldhigh+viewz
+							&& (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldhighslope+viewz))
+						continue;
+#else
 					if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight)
 						continue;
 					if (*rover->topheight <= backsector->floorheight || *rover->bottomheight >= backsector->ceilingheight)
 						continue;
-					if (rover->norender == leveltime)
-						continue;
+#endif
 
 					ds_p->thicksides[i] = rover;
 					i++;
@@ -1898,6 +2319,32 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			else
 				ds_p->maskedtexturecol = ds_p->thicksidecol;
 
+#ifdef ESLOPE
+			maskedtextureheight = &(ds_p->maskedtextureheight[0]); // ????
+
+			// Set midtexture starting height
+			if (linedef->flags & ML_EFFECT2) { // Ignore slopes when texturing
+				rw_midtextureslide = rw_midtexturebackslide = 0;
+				if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3))
+					rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz;
+				else
+					rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz;
+
+			} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
+				rw_midtexturemid = worldbottom;
+				rw_midtextureslide = floorfrontslide;
+				rw_midtextureback = worldlow;
+				rw_midtexturebackslide = floorbackslide;
+			} else {
+				rw_midtexturemid = worldtop;
+				rw_midtextureslide = ceilingfrontslide;
+				rw_midtextureback = worldhigh;
+				rw_midtexturebackslide = ceilingbackslide;
+			}
+			rw_midtexturemid += sidedef->rowoffset;
+			rw_midtextureback += sidedef->rowoffset;
+#endif
+
 			maskedtexture = true;
 		}
 	}
@@ -1950,13 +2397,21 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	//  and doesn't need to be marked.
 	if (frontsector->heightsec == -1)
 	{
-		if (frontsector->floorheight >= viewz)
+		if ((
+#ifdef ESLOPE
+			frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) :
+#endif
+			frontsector->floorheight) >= viewz)
 		{
 			// above view plane
 			markfloor = false;
 		}
 
-		if (frontsector->ceilingheight <= viewz &&
+		if ((
+#ifdef ESLOPE
+			frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) :
+#endif
+			frontsector->ceilingheight) <= viewz &&
 		    frontsector->ceilingpic != skyflatnum)
 		{
 			// below view plane
@@ -1967,6 +2422,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	// calculate incremental stepping values for texture edges
 	worldtop >>= 4;
 	worldbottom >>= 4;
+#ifdef ESLOPE
+	worldtopslope >>= 4;
+	worldbottomslope >>= 4;
+#endif
 
 	topstep = -FixedMul (rw_scalestep, worldtop);
 	topfrac = (centeryfrac>>4) - FixedMul (worldtop, rw_scale);
@@ -1974,6 +2433,17 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	bottomstep = -FixedMul (rw_scalestep,worldbottom);
 	bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale);
 
+#ifdef ESLOPE
+	if (frontsector->c_slope) {
+		fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldtopslope, ds_p->scale2);
+		topstep = (topfracend-topfrac)/(stop-start+1);
+	}
+	if (frontsector->f_slope) {
+		fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldbottomslope, ds_p->scale2);
+		bottomstep = (bottomfracend-bottomfrac)/(stop-start+1);
+	}
+#endif
+
 	dc_numlights = 0;
 
 	if (frontsector->numlights)
@@ -1987,26 +2457,83 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 		for (i = p = 0; i < dc_numlights; i++)
 		{
+#ifdef ESLOPE
+			fixed_t leftheight, rightheight;
+#endif
+
 			light = &frontsector->lightlist[i];
 			rlight = &dc_lightlist[p];
 
+#ifdef ESLOPE
+			if (light->slope) {
+				leftheight = P_GetZAt(light->slope, segleft.x, segleft.y);
+				rightheight = P_GetZAt(light->slope, segright.x, segright.y);
+
+				// Flag sector as having slopes
+				frontsector->hasslope = true;
+			} else
+				leftheight = rightheight = light->height;
+
+			leftheight -= viewz;
+			rightheight -= viewz;
+
+			leftheight >>= 4;
+			rightheight >>= 4;
+#endif
+
 			if (i != 0)
 			{
+#ifdef ESLOPE
+				if (leftheight < worldbottom && rightheight < worldbottomslope)
+					continue;
+
+				if (leftheight > worldtop && rightheight > worldtopslope && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight)
+					continue;
+#else
 				if (light->height < frontsector->floorheight)
 					continue;
 
 				if (light->height > frontsector->ceilingheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight)
 					continue;
+#endif
 			}
 
+#ifdef ESLOPE
+			rlight->height = (centeryfrac>>4) - FixedMul(leftheight, rw_scale);
+			rlight->heightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2);
+			rlight->heightstep = (rlight->heightstep-rlight->height)/(stop-start+1);
+#else
 			rlight->height = (centeryfrac>>4) - FixedMul((light->height - viewz) >> 4, rw_scale);
 			rlight->heightstep = -FixedMul (rw_scalestep, (light->height - viewz) >> 4);
+#endif
 			rlight->flags = light->flags;
 
 			if (light->caster && light->caster->flags & FF_SOLID)
 			{
+#ifdef ESLOPE
+				if (*light->caster->b_slope) {
+					leftheight = P_GetZAt(*light->caster->b_slope, segleft.x, segleft.y);
+					rightheight = P_GetZAt(*light->caster->b_slope, segright.x, segright.y);
+
+					// Flag sector as having slopes
+					frontsector->hasslope = true;
+				} else
+					leftheight = rightheight = *light->caster->bottomheight;
+
+				leftheight -= viewz;
+				rightheight -= viewz;
+
+				leftheight >>= 4;
+				rightheight >>= 4;
+
+				rlight->botheight = (centeryfrac>>4) - FixedMul(leftheight, rw_scale);
+				rlight->botheightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2);
+				rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(stop-start+1);
+
+#else
 				rlight->botheight = (centeryfrac >> 4) - FixedMul((*light->caster->bottomheight - viewz) >> 4, rw_scale);
 				rlight->botheightstep = -FixedMul (rw_scalestep, (*light->caster->bottomheight - viewz) >> 4);
+#endif
 			}
 
 			rlight->lightlevel = *light->lightlevel;
@@ -2027,8 +2554,14 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 #endif
 
 			ffloor[i].f_pos >>= 4;
+#ifdef ESLOPE
+			ffloor[i].f_pos_slope >>= 4;
+			ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale);
+			ffloor[i].f_step = ((centeryfrac>>4) - FixedMul(ffloor[i].f_pos_slope, ds_p->scale2) - ffloor[i].f_frac)/(stop-start+1);
+#else
 			ffloor[i].f_step = FixedMul(-rw_scalestep, ffloor[i].f_pos);
 			ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale);
+#endif
 		}
 	}
 
@@ -2036,21 +2569,50 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	{
 		worldhigh >>= 4;
 		worldlow >>= 4;
+#ifdef ESLOPE
+		worldhighslope >>= 4;
+		worldlowslope >>= 4;
+#endif
 
-		if (worldhigh < worldtop)
+		if (worldhigh < worldtop
+#ifdef ESLOPE
+			|| worldhighslope <= worldtopslope
+#endif
+			)
 		{
 			pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
 			pixhighstep = -FixedMul (rw_scalestep,worldhigh);
+
+#ifdef ESLOPE
+			if (backsector->c_slope) {
+				fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldhighslope, ds_p->scale2);
+				pixhighstep = (topfracend-pixhigh)/(stop-start+1);
+			}
+#endif
 		}
 
-		if (worldlow > worldbottom)
+		if (worldlow > worldbottom
+#ifdef ESLOPE
+			|| worldlowslope >= worldbottomslope
+#endif
+			)
 		{
 			pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale);
 			pixlowstep = -FixedMul (rw_scalestep,worldlow);
+#ifdef ESLOPE
+			if (backsector->f_slope) {
+				fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldlowslope, ds_p->scale2);
+				pixlowstep = (bottomfracend-pixlow)/(stop-start+1);
+			}
+#endif
 		}
 
 		{
 			ffloor_t * rover;
+#ifdef ESLOPE
+			fixed_t rovertest;
+			fixed_t planevistest;
+#endif
 			i = 0;
 
 			if (backsector->ffloors)
@@ -2062,6 +2624,52 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					if (rover->norender == leveltime)
 						continue;
 
+#ifdef ESLOPE
+					// Let the renderer know this sector is sloped.
+					if (*rover->b_slope || *rover->t_slope)
+						backsector->hasslope = true;
+
+					rovertest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, backsector->soundorg.x, backsector->soundorg.y) : *rover->bottomheight) - viewz;
+					planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight);
+
+					if (rovertest>>4 <= worldhigh &&
+					    rovertest>>4 >= worldlow &&
+					    ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz > planevistest && (rover->flags & FF_BOTHPLANES))))
+					{
+						//ffloor[i].slope = *rover->b_slope;
+						ffloor[i].b_pos = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz;
+						ffloor[i].b_pos_slope = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz;
+						ffloor[i].b_pos >>= 4;
+						ffloor[i].b_pos_slope >>= 4;
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(stop-start+1);
+						i++;
+					}
+
+					if (i >= MAXFFLOORS)
+						break;
+
+					rovertest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, backsector->soundorg.x, backsector->soundorg.y) : *rover->topheight) - viewz;
+					planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight);
+
+					if (rovertest>>4 <= worldhigh &&
+					    rovertest>>4 >= worldlow &&
+					    ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz < planevistest && (rover->flags & FF_BOTHPLANES))))
+					{
+						//ffloor[i].slope = *rover->t_slope;
+						ffloor[i].b_pos = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz;
+						ffloor[i].b_pos_slope = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz;
+						ffloor[i].b_pos >>= 4;
+						ffloor[i].b_pos_slope >>= 4;
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(stop-start+1);
+						i++;
+					}
+#else
 					if (*rover->bottomheight <= backsector->ceilingheight &&
 					    *rover->bottomheight >= backsector->floorheight &&
 					    ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) ||
@@ -2073,8 +2681,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
 						i++;
 					}
+
 					if (i >= MAXFFLOORS)
 						break;
+
 					if (*rover->topheight >= backsector->floorheight &&
 					    *rover->topheight <= backsector->ceilingheight &&
 					    ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) ||
@@ -2086,6 +2696,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
 						i++;
 					}
+#endif
 				}
 			}
 			else if (frontsector && frontsector->ffloors)
@@ -2097,6 +2708,53 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					if (rover->norender == leveltime)
 						continue;
 
+
+#ifdef ESLOPE
+					// Let the renderer know this sector is sloped.
+					if (*rover->b_slope || *rover->t_slope)
+						frontsector->hasslope = true;
+
+					rovertest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, frontsector->soundorg.x, frontsector->soundorg.y) : *rover->bottomheight) - viewz;
+					planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight);
+
+					if (rovertest>>4 <= worldtop &&
+					    rovertest>>4 >= worldbottom &&
+					    ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz > planevistest && (rover->flags & FF_BOTHPLANES))))
+					{
+						//ffloor[i].slope = *rover->b_slope;
+						ffloor[i].b_pos = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz;
+						ffloor[i].b_pos_slope = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz;
+						ffloor[i].b_pos >>= 4;
+						ffloor[i].b_pos_slope >>= 4;
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(stop-start+1);
+						i++;
+					}
+
+					if (i >= MAXFFLOORS)
+						break;
+
+					rovertest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, frontsector->soundorg.x, frontsector->soundorg.y) : *rover->topheight) - viewz;
+					planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight);
+
+					if (rovertest>>4 <= worldtop &&
+					    rovertest>>4 >= worldbottom &&
+					    ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) ||
+					     (viewz < planevistest && (rover->flags & FF_BOTHPLANES))))
+					{
+						//ffloor[i].slope = *rover->t_slope;
+						ffloor[i].b_pos = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz;
+						ffloor[i].b_pos_slope = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz;
+						ffloor[i].b_pos >>= 4;
+						ffloor[i].b_pos_slope >>= 4;
+						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
+						ffloor[i].b_step = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos_slope, ds_p->scale2);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(stop-start+1);
+						i++;
+					}
+#else
 					if (*rover->bottomheight <= frontsector->ceilingheight &&
 					    *rover->bottomheight >= frontsector->floorheight &&
 					    ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) ||
@@ -2121,6 +2779,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 						ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale);
 						i++;
 					}
+#endif
 				}
 			}
 #ifdef POLYOBJECTS_PLANES
@@ -2137,6 +2796,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					if (ffloor[i].plane->maxx < ds_p->x2)
 						ffloor[i].plane->maxx = ds_p->x2;
 
+#ifdef ESLOPE
+					ffloor[i].slope = NULL;
+#endif
 					ffloor[i].b_pos = backsector->floorheight;
 					ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
 					ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
@@ -2153,6 +2815,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					if (ffloor[i].plane->maxx < ds_p->x2)
 						ffloor[i].plane->maxx = ds_p->x2;
 
+#ifdef ESLOPE
+					ffloor[i].slope = NULL;
+#endif
 					ffloor[i].b_pos = backsector->ceilingheight;
 					ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4;
 					ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos);
diff --git a/src/r_splats.c b/src/r_splats.c
index 72eca08fb05709d81c4b256e56ded57d140834b7..b37ce19233419009e81b806c46283b9a3642764b 100644
--- a/src/r_splats.c
+++ b/src/r_splats.c
@@ -503,7 +503,7 @@ static void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, UINT8 *pTe
 		{
 			ds_x1 = x1;
 			ds_x2 = x2;
-			ds_transmap = ((tr_trans50)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+			ds_transmap = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
 			splatfunc();
 		}
 
diff --git a/src/r_things.c b/src/r_things.c
index f5231854dc92a551d13f61bc5bc80ffdeefcb64c..b94db488e9e1cb1439c81b24e2419c28b8555d7f 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -24,6 +24,7 @@
 #include "r_plane.h"
 #include "p_tick.h"
 #include "p_local.h"
+#include "p_slopes.h"
 #include "dehacked.h" // get_number (for thok)
 #include "d_netfil.h" // blargh. for nameonly().
 #include "m_cheat.h" // objectplace
@@ -954,12 +955,22 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing)
 
 	for (i = 1; i < sector->numlights; i++)
 	{
-		if (sector->lightlist[i].height >= sprite->gzt || !(sector->lightlist[i].caster->flags & FF_CUTSPRITES))
+		fixed_t testheight = sector->lightlist[i].height;
+
+		if (!(sector->lightlist[i].caster->flags & FF_CUTSPRITES))
+			continue;
+
+#ifdef ESLOPE
+		if (sector->lightlist[i].slope)
+			testheight = P_GetZAt(sector->lightlist[i].slope, sprite->gx, sprite->gy);
+#endif
+
+		if (testheight >= sprite->gzt)
 			continue;
-		if (sector->lightlist[i].height <= sprite->gz)
+		if (testheight <= sprite->gz)
 			return;
 
-		cutfrac = (INT16)((centeryfrac - FixedMul(sector->lightlist[i].height - viewz, sprite->scale))>>FRACBITS);
+		cutfrac = (INT16)((centeryfrac - FixedMul(testheight - viewz, sprite->scale))>>FRACBITS);
 		if (cutfrac < 0)
 			continue;
 		if (cutfrac > vid.height)
@@ -970,15 +981,15 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing)
 		newsprite = M_Memcpy(R_NewVisSprite(), sprite, sizeof (vissprite_t));
 
 		sprite->cut |= SC_BOTTOM;
-		sprite->gz = sector->lightlist[i].height;
+		sprite->gz = testheight;
 
 		newsprite->gzt = sprite->gz;
 
 		sprite->sz = cutfrac;
 		newsprite->szt = (INT16)(sprite->sz - 1);
 
-		if (sector->lightlist[i].height < sprite->pzt && sector->lightlist[i].height > sprite->pz)
-			sprite->pz = newsprite->pzt = sector->lightlist[i].height;
+		if (testheight < sprite->pzt && testheight > sprite->pz)
+			sprite->pz = newsprite->pzt = testheight;
 		else
 		{
 			newsprite->pz = newsprite->gz;
@@ -1200,7 +1211,20 @@ static void R_ProjectSprite(mobj_t *thing)
 	if (thing->subsector->sector->numlights)
 	{
 		INT32 lightnum;
+#ifdef ESLOPE // R_GetPlaneLight won't work on sloped lights!
+		light = thing->subsector->sector->numlights - 1;
+
+		for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) {
+			fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y)
+			            : thing->subsector->sector->lightlist[lightnum].height;
+			if (h <= gzt) {
+				light = lightnum - 1;
+				break;
+			}
+		}
+#else
 		light = R_GetPlaneLight(thing->subsector->sector, gzt, false);
+#endif
 		lightnum = (*thing->subsector->sector->lightlist[light].lightlevel >> LIGHTSEGSHIFT);
 
 		if (lightnum < 0)
@@ -1242,7 +1266,8 @@ static void R_ProjectSprite(mobj_t *thing)
 	vis = R_NewVisSprite();
 	vis->heightsec = heightsec; //SoM: 3/17/2000
 	vis->mobjflags = thing->flags;
-	vis->scale = yscale + thing->info->dispoffset;           //<<detailshift;
+	vis->scale = yscale; //<<detailshift;
+	vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15
 	vis->gx = thing->x;
 	vis->gy = thing->y;
 	vis->gz = gz;
@@ -1305,9 +1330,9 @@ static void R_ProjectSprite(mobj_t *thing)
 	if (!cv_translucency.value)
 		; // no translucency
 	else if (thing->flags2 & MF2_SHADOW) // actually only the player should use this (temporary invisibility)
-		vis->transmap = ((tr_trans80-1)<<FF_TRANSSHIFT) + transtables; // because now the translucency is set through FF_TRANSMASK
+		vis->transmap = transtables + ((tr_trans80-1)<<FF_TRANSSHIFT); // because now the translucency is set through FF_TRANSMASK
 	else if (thing->frame & FF_TRANSMASK)
-		vis->transmap = (thing->frame & FF_TRANSMASK) - 0x10000 + transtables;
+		vis->transmap = transtables + (thing->frame & FF_TRANSMASK) - 0x10000;
 
 	if (((thing->frame & FF_FULLBRIGHT) || (thing->flags2 & MF2_SHADOW))
 		&& (!vis->extra_colormap || !vis->extra_colormap->fog))
@@ -1458,6 +1483,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
 	// store information in a vissprite
 	vis = R_NewVisSprite();
 	vis->scale = yscale; //<<detailshift;
+	vis->dispoffset = 0; // Monster Iestyn: 23/11/15
 	vis->gx = thing->x;
 	vis->gy = thing->y;
 	vis->gz = gz;
@@ -1609,6 +1635,7 @@ void R_SortVisSprites(void)
 	vissprite_t *best = NULL;
 	vissprite_t  unsorted;
 	fixed_t      bestscale;
+	INT32        bestdispoffset;
 
 	if (!visspritecount)
 		return;
@@ -1639,12 +1666,19 @@ void R_SortVisSprites(void)
 	vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
 	for (i = 0; i < visspritecount; i++)
 	{
-		bestscale = INT32_MAX;
+		bestscale = bestdispoffset = INT32_MAX;
 		for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
 		{
 			if (ds->scale < bestscale)
 			{
 				bestscale = ds->scale;
+				bestdispoffset = ds->dispoffset;
+				best = ds;
+			}
+			// order visprites of same scale by dispoffset, smallest first
+			else if (ds->scale == bestscale && ds->dispoffset < bestdispoffset)
+			{
+				bestdispoffset = ds->dispoffset;
 				best = ds;
 			}
 		}
@@ -1691,6 +1725,19 @@ static void R_CreateDrawNodes(void)
 		}
 		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!
+
+				entry = R_CreateDrawNode(&nodehead);
+				entry->plane = ds->curline->polyseg->visplane;
+				entry->seg = ds;
+				ds->curline->polyseg->visplane->polyobj = ds->curline->polyseg;
+				ds->curline->polyseg->visplane = NULL;
+			}
+#endif
+
 			entry = R_CreateDrawNode(&nodehead);
 			entry->seg = ds;
 		}
@@ -1707,7 +1754,7 @@ static void R_CreateDrawNodes(void)
 					plane = ds->ffloorplanes[p];
 					R_PlaneBounds(plane);
 
-					if (plane->low < con_clipviewtop || plane->high > vid.height || plane->high > plane->low)
+					if (plane->low < con_clipviewtop || plane->high > vid.height || plane->high > plane->low || plane->polyobj)
 					{
 						ds->ffloorplanes[p] = NULL;
 						continue;
@@ -1748,24 +1795,34 @@ static void R_CreateDrawNodes(void)
 		{
 			if (r2->plane)
 			{
+				fixed_t planeobjectz, planecameraz;
 				if (r2->plane->minx > rover->x2 || r2->plane->maxx < rover->x1)
 					continue;
 				if (rover->szt > r2->plane->low || rover->sz < r2->plane->high)
 					continue;
 
+#ifdef ESLOPE
+				// Effective height may be different for each comparison in the case of slopes
+				if (r2->plane->slope) {
+					planeobjectz = P_GetZAt(r2->plane->slope, rover->gx, rover->gy);
+					planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy);
+				} else
+#endif
+					planeobjectz = planecameraz = r2->plane->height;
+
 				if (rover->mobjflags & MF_NOCLIPHEIGHT)
 				{
 					//Objects with NOCLIPHEIGHT can appear halfway in.
-					if (r2->plane->height < viewz && rover->pz+(rover->thingheight/2) >= r2->plane->height)
+					if (planecameraz < viewz && rover->pz+(rover->thingheight/2) >= planeobjectz)
 						continue;
-					if (r2->plane->height > viewz && rover->pzt-(rover->thingheight/2) <= r2->plane->height)
+					if (planecameraz > viewz && rover->pzt-(rover->thingheight/2) <= planeobjectz)
 						continue;
 				}
 				else
 				{
-					if (r2->plane->height < viewz && rover->pz >= r2->plane->height)
+					if (planecameraz < viewz && rover->pz >= planeobjectz)
 						continue;
-					if (r2->plane->height > viewz && rover->pzt <= r2->plane->height)
+					if (planecameraz > viewz && rover->pzt <= planeobjectz)
 						continue;
 				}
 
@@ -1795,6 +1852,7 @@ static void R_CreateDrawNodes(void)
 			}
 			else if (r2->thickseg)
 			{
+				fixed_t topplaneobjectz, topplanecameraz, botplaneobjectz, botplanecameraz;
 				if (rover->x1 > r2->thickseg->x2 || rover->x2 < r2->thickseg->x1)
 					continue;
 
@@ -1805,9 +1863,25 @@ static void R_CreateDrawNodes(void)
 				if (scale <= rover->scale)
 					continue;
 
-				if ((*r2->ffloor->topheight > viewz && *r2->ffloor->bottomheight < viewz) ||
-				    (*r2->ffloor->topheight < viewz && rover->gzt < *r2->ffloor->topheight) ||
-				    (*r2->ffloor->bottomheight > viewz && rover->gz > *r2->ffloor->bottomheight))
+#ifdef ESLOPE
+				if (*r2->ffloor->t_slope) {
+					topplaneobjectz = P_GetZAt(*r2->ffloor->t_slope, rover->gx, rover->gy);
+					topplanecameraz = P_GetZAt(*r2->ffloor->t_slope, viewx, viewy);
+				} else
+#endif
+					topplaneobjectz = topplanecameraz = *r2->ffloor->topheight;
+
+#ifdef ESLOPE
+				if (*r2->ffloor->b_slope) {
+					botplaneobjectz = P_GetZAt(*r2->ffloor->b_slope, rover->gx, rover->gy);
+					botplanecameraz = P_GetZAt(*r2->ffloor->b_slope, viewx, viewy);
+				} else
+#endif
+					botplaneobjectz = botplanecameraz = *r2->ffloor->bottomheight;
+
+				if ((topplanecameraz > viewz && botplanecameraz < viewz) ||
+				    (topplanecameraz < viewz && rover->gzt < topplaneobjectz) ||
+				    (botplanecameraz > viewz && rover->gz > botplaneobjectz))
 				{
 					entry = R_CreateDrawNode(NULL);
 					(entry->prev = r2->prev)->next = entry;
@@ -1818,7 +1892,7 @@ static void R_CreateDrawNodes(void)
 			}
 			else if (r2->seg)
 			{
-#ifdef POLYOBJECTS_PLANES
+#if 0 //#ifdef POLYOBJECTS_PLANES
 				if (r2->seg->curline->polyseg && rover->mobj && P_MobjInsidePolyobj(r2->seg->curline->polyseg, rover->mobj)) {
 					// Determine if we need to sort in front of the polyobj, based on the planes. This fixes the issue where
 					// polyobject planes render above the object standing on them. (A bit hacky... but it works.) -Red
@@ -1856,7 +1930,8 @@ static void R_CreateDrawNodes(void)
 				if (r2->sprite->szt > rover->sz || r2->sprite->sz < rover->szt)
 					continue;
 
-				if (r2->sprite->scale > rover->scale)
+				if (r2->sprite->scale > rover->scale
+				 || (r2->sprite->scale == rover->scale && r2->sprite->dispoffset > rover->dispoffset))
 				{
 					entry = R_CreateDrawNode(NULL);
 					(entry->prev = r2->prev)->next = entry;
@@ -2026,21 +2101,21 @@ void R_ClipSprites(void)
 			if (spr->gzt <= ds->tsilheight)
 				silhouette &= ~SIL_TOP;
 
-			if (silhouette == 1)
+			if (silhouette == SIL_BOTTOM)
 			{
 				// bottom sil
 				for (x = r1; x <= r2; x++)
 					if (spr->clipbot[x] == -2)
 						spr->clipbot[x] = ds->sprbottomclip[x];
 			}
-			else if (silhouette == 2)
+			else if (silhouette == SIL_TOP)
 			{
 				// top sil
 				for (x = r1; x <= r2; x++)
 					if (spr->cliptop[x] == -2)
 						spr->cliptop[x] = ds->sprtopclip[x];
 			}
-			else if (silhouette == 3)
+			else if (silhouette == (SIL_TOP|SIL_BOTTOM))
 			{
 				// both
 				for (x = r1; x <= r2; x++)
@@ -2221,7 +2296,7 @@ static void Sk_SetDefaultValue(skin_t *skin)
 	strncpy(skin->face, "MISSING", 8);
 	strncpy(skin->superface, "MISSING", 8);
 
-	skin->starttranscolor = 160;
+	skin->starttranscolor = 96;
 	skin->prefcolor = SKINCOLOR_GREEN;
 
 	skin->normalspeed = 36<<FRACBITS;
@@ -2590,9 +2665,6 @@ next_token:
 		}
 		free(buf2);
 
-		if (skin != &skins[0])
-			skin->flags &= ~SF_SUPER;
-
 		// Add sprites
 		{
 			UINT16 z;
diff --git a/src/r_things.h b/src/r_things.h
index 054a6497d04340260d86ed5f04c58d0c5756d34f..3e2d13fd7604218943666a1b834a3b1bd0359602 100644
--- a/src/r_things.h
+++ b/src/r_things.h
@@ -162,6 +162,7 @@ typedef struct vissprite_s
 	boolean precip;
 	boolean vflip; // Flip vertically
 	boolean isScaled;
+	INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
 } vissprite_t;
 
 // A drawnode is something that points to a 3D floor, 3D side, or masked
diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt
index b4eeeeb5fb1c0e778be6a6a16758e0c116d9ad53..b3fa5390c50a748d60e87920073f46f5c28ff117 100644
--- a/src/sdl/CMakeLists.txt
+++ b/src/sdl/CMakeLists.txt
@@ -39,8 +39,7 @@ set(SRB2_SDL2_HEADERS
 	sdlmain.h
 )
 
-prepend_sources(SRB2_SDL2_SOURCES)
-prepend_sources(SRB2_SDL2_HEADERS)
+source_group("Interface Code" FILES ${SRB2_SDL2_SOURCES} ${SRB2_SDL2_HEADERS})
 
 # Dependency
 find_package(SDL2)
@@ -49,9 +48,22 @@ if(${SDL2_FOUND})
 	set(SRB2_SDL2_TOTAL_SOURCES
 		${SRB2_CORE_SOURCES}
 		${SRB2_CORE_HEADERS}
+		${SRB2_CORE_RENDER_SOURCES}
+		${SRB2_CORE_GAME_SOURCES}
+		${SRB2_LUA_SOURCES}
+		${SRB2_LUA_HEADERS}
+		${SRB2_BLUA_SOURCES}
+		${SRB2_BLUA_HEADERS}
 		${SRB2_SDL2_SOURCES}
 		${SRB2_SDL2_HEADERS}
 	)
+	
+	source_group("Main" FILES ${SRB2_CORE_SOURCES} ${SRB2_CORE_HEADERS})
+	source_group("Renderer" FILES ${SRB2_CORE_RENDER_SOURCES})
+	source_group("Game" FILES ${SRB2_CORE_GAME_SOURCES})
+	source_group("Assembly" FILES ${SRB2_ASM_SOURCES} ${SRB2_NASM_SOURCES})
+	source_group("LUA" FILES ${SRB2_LUA_SOURCES} ${SRB2_LUA_HEADERS})
+	source_group("LUA\\Interpreter" FILES ${SRB2_BLUA_SOURCES} ${SRB2_BLUA_HEADERS})
 
 	if(${SRB2_CONFIG_HWRENDER})
 		set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES}
@@ -60,15 +72,9 @@ if(${SDL2_FOUND})
 			${SRB2_R_OPENGL_SOURCES}
 			${SRB2_R_OPENGL_HEADERS}
 		)
-	endif()
 
-	if(${SRB2_CONFIG_HAVE_BLUA})
-		set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES}
-			${SRB2_LUA_SOURCES}
-			${SRB2_LUA_HEADERS}
-			${SRB2_BLUA_SOURCES}
-			${SRB2_BLUA_HEADERS}
-		)
+		source_group("Hardware" FILES ${SRB2_HWRENDER_SOURCES} ${SRB2_HWRENDER_HEADERS})
+		source_group("Hardware\\OpenGL Renderer" FILES ${SRB2_R_OPENGL_SOURCES} ${SRB2_R_OPENGL_HEADERS})
 	endif()
 
 	if(${SRB2_USEASM})
@@ -85,7 +91,6 @@ if(${SDL2_FOUND})
 			set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES LANGUAGE C)
 			set_source_files_properties(${SRB2_ASM_SOURCES} PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp")
 		endif()
-
 	endif()
 
 	if(${CMAKE_SYSTEM} MATCHES Windows)
@@ -94,39 +99,36 @@ if(${SDL2_FOUND})
 			${CMAKE_SOURCE_DIR}/src/win32/Srb2win.rc
 		)
 	endif()
-	if(NOT CLANG)
-		set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES}
-			${CMAKE_SOURCE_DIR}/src/string.c
-		)
-	endif()
 
 	if(${CMAKE_SYSTEM} MATCHES Darwin)
 		set(MACOSX_BUNDLE_ICON_FILE Srb2mac.icns)
 		set_source_files_properties(macosx/Srb2mac.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
-		set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES}
+		set(SRB2_SDL2_MAC_SOURCES
 			macosx/mac_alert.c
 			macosx/mac_alert.h
 			macosx/mac_resources.c
 			macosx/mac_resources.h
 			macosx/Srb2mac.icns
 		)
+		source_group("Interface Code\\OSX Compatibility" FILES ${SRB2_SDL2_MAC_SOURCES})
+		set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} ${SRB2_SDL2_MAC_SOURCES})
 	endif()
 
+	add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 ${SRB2_SDL2_TOTAL_SOURCES})
+	set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME ${SRB2_SDL2_EXE_NAME})
+
 	if(CLANG)
-		add_executable(${SRB2_SDL2_EXE_NAME} MACOSX_BUNDLE ${SRB2_SDL2_TOTAL_SOURCES})
-		add_framework(CoreFoundation ${SRB2_SDL2_EXE_NAME})
-		add_framework(SDL2 ${SRB2_SDL2_EXE_NAME})
-		add_framework(SDL2_mixer ${SRB2_SDL2_EXE_NAME})
-		target_link_libraries(${SRB2_SDL2_EXE_NAME} PRIVATE
+		add_framework(CoreFoundation SRB2SDL2)
+		add_framework(SDL2 SRB2SDL2)
+		add_framework(SDL2_mixer SRB2SDL2)
+		target_link_libraries(SRB2SDL2 PRIVATE
 			${PNG_LIBRARIES}
 			${ZLIB_LIBRARIES}
 			${OPENGL_LIBRARIES}
 		)
-		set_target_properties(${SRB2_SDL2_EXE_NAME} PROPERTIES OUTPUT_NAME "Sonic Robo Blast 2")
+		set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME "Sonic Robo Blast 2")
 	else()
-		add_executable(${SRB2_SDL2_EXE_NAME} WIN32 ${SRB2_SDL2_TOTAL_SOURCES})
-
-		target_link_libraries(${SRB2_SDL2_EXE_NAME} PRIVATE
+		target_link_libraries(SRB2SDL2 PRIVATE
 			${SDL2_LIBRARIES}
 			${SDL2_MIXER_LIBRARIES}
 			${PNG_LIBRARIES}
@@ -135,14 +137,15 @@ if(${SDL2_FOUND})
 		)
 
 		if(${CMAKE_SYSTEM} MATCHES Linux)
-			target_link_libraries(${SRB2_SDL2_EXE_NAME} PRIVATE
+			target_link_libraries(SRB2SDL2 PRIVATE
 				m
 				rt
 			)
 		endif()
-
 	endif()
 
+	#target_link_libraries(SRB2SDL2 PRIVATE SRB2Core)
+
 	if(${SRB2_USEASM})
 		if(${SRB2_CONFIG_YASM})
 			set(ASM_ASSEMBLER_TEMP ${CMAKE_ASM_YASM_COMPILER})
@@ -159,7 +162,7 @@ if(${SDL2_FOUND})
 			foreach(ASMFILE ${SRB2_NASM_SOURCES})
 				get_filename_component(ASMFILE_NAME ${ASMFILE} NAME_WE)
 				set(ASMFILE_NAME ${ASMFILE_NAME}.obj)
-				add_custom_command(TARGET ${SRB2_SDL2_EXE_NAME} PRE_LINK
+				add_custom_command(TARGET SRB2SDL2 PRE_LINK
 					COMMAND ${ASM_ASSEMBLER_TEMP} ARGS -f ${ASM_ASSEMBLER_OBJFORMAT} -o ${CMAKE_CURRENT_BINARY_DIR}/${ASMFILE_NAME} ${ASMFILE}
 					COMMENT "assemble ${ASMFILE_NAME}."
 				)
@@ -167,23 +170,23 @@ if(${SDL2_FOUND})
 		endif()
 	endif()
 
-	set_target_properties(${SRB2_SDL2_EXE_NAME} PROPERTIES VERSION ${SRB2_VERSION})
+	set_target_properties(SRB2SDL2 PROPERTIES VERSION ${SRB2_VERSION})
 
 	if(${CMAKE_SYSTEM} MATCHES Windows)
-		target_link_libraries(${SRB2_SDL2_EXE_NAME} PRIVATE
+		target_link_libraries(SRB2SDL2 PRIVATE
 			ws2_32
 		)
-		target_compile_options(${SRB2_SDL2_EXE_NAME} PRIVATE
+		target_compile_options(SRB2SDL2 PRIVATE
 			-U_WINDOWS
 		)
 	endif()
 
 	if(MSVC)
 		find_package(SDL2_MAIN REQUIRED)
-		target_link_libraries(${SRB2_SDL2_EXE_NAME} PRIVATE
+		target_link_libraries(SRB2SDL2 PRIVATE
 			${SDL2_MAIN_LIBRARIES}
 		)
-		target_compile_options(${SRB2_SDL2_EXE_NAME} PRIVATE
+		target_compile_options(SRB2SDL2 PRIVATE
 			/Umain
 			/D_CRT_SECURE_NO_WARNINGS # something about string functions.
 			/D_CRT_NONSTDC_NO_DEPRECATE
@@ -192,7 +195,7 @@ if(${SDL2_FOUND})
 		)
 	endif()
 
-	target_include_directories(${SRB2_SDL2_EXE_NAME} PRIVATE
+	target_include_directories(SRB2SDL2 PRIVATE
 		${SDL2_INCLUDE_DIRS}
 		${SDL2_MIXER_INCLUDE_DIRS}
 		${PNG_INCLUDE_DIRS}
@@ -201,10 +204,10 @@ if(${SDL2_FOUND})
 	)
 
 	if(${SRB2_HAVE_MIXER})
-		target_compile_definitions(${SRB2_SDL2_EXE_NAME} PRIVATE -DHAVE_MIXER -DSOUND=SOUND_MIXER)
+		target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DSOUND=SOUND_MIXER)
 	endif()
 
-	target_compile_definitions(${SRB2_SDL2_EXE_NAME} PRIVATE
+	target_compile_definitions(SRB2SDL2 PRIVATE
 		-DHAVE_SDL
 	)
 
@@ -212,21 +215,21 @@ if(${SDL2_FOUND})
 	if(CMAKE_COMPILER_IS_GNUCC)
 		if(${CMAKE_BUILD_TYPE} MATCHES Debug)
 			message(STATUS "Will make separate debug symbols in *.debug")
-			add_custom_command(TARGET ${SRB2_SDL2_EXE_NAME} POST_BUILD
-				COMMAND ${OBJCOPY} --only-keep-debug $<TARGET_FILE:${SRB2_SDL2_EXE_NAME}> $<TARGET_FILE:${SRB2_SDL2_EXE_NAME}>.debug
-				COMMAND ${OBJCOPY} --strip-debug $<TARGET_FILE:${SRB2_SDL2_EXE_NAME}>
-				COMMAND ${OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE_NAME:${SRB2_SDL2_EXE_NAME}>.debug $<TARGET_FILE:${SRB2_SDL2_EXE_NAME}>
+			add_custom_command(TARGET SRB2SDL2 POST_BUILD
+				COMMAND ${OBJCOPY} --only-keep-debug $<TARGET_FILE:SRB2SDL2> $<TARGET_FILE:SRB2SDL2>.debug
+				COMMAND ${OBJCOPY} --strip-debug $<TARGET_FILE:SRB2SDL2>
+				COMMAND ${OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE_NAME:SRB2SDL2>.debug $<TARGET_FILE:SRB2SDL2>
 			)
 		endif()
 	endif()
 
 	#### Installation ####
 	if (CLANG)
-		install(TARGETS ${SRB2_SDL2_EXE_NAME}
+		install(TARGETS SRB2SDL2
 			BUNDLE DESTINATION .
 		)
 	else()
-		install(TARGETS ${SRB2_SDL2_EXE_NAME} ${SRB2_SDL2_EXE_NAME}
+		install(TARGETS SRB2SDL2 SRB2SDL2
 			RUNTIME DESTINATION .
 		)
 	endif()
@@ -257,10 +260,10 @@ if(${SDL2_FOUND})
 
 		# We also want to copy those DLLs to build directories on MSVC.
 		# So we'll add a post_build step.
-		copy_files_to_build_dir(${SRB2_SDL2_EXE_NAME} win_extra_dll_list)
+		copy_files_to_build_dir(SRB2SDL2 win_extra_dll_list)
 	endif()
 
-	
+
 	# Mac bundle fixup
 	if(CLANG)
 		install(CODE "
@@ -271,6 +274,9 @@ if(${SDL2_FOUND})
 			)"
 		)
 	endif()
+
+	set(SRB2_SDL2_AVAILABLE YES PARENT_SCOPE)
 else()
-	message(WARNING "SDL2 wasn't found, so ${SRB2_SDL2_EXE_NAME} won't be available")
-endif()
+	message(WARNING "SDL2 was not found, so the SDL2 target will not be available.")
+	set(SRB2_SDL2_AVAILABLE NO PARENT_SCOPE)
+endif()
\ No newline at end of file
diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c
index 976f7eb35760360129128616437c73fd903ea1ef..c157a6be792bcf44709d76c57d21147c4448d2fc 100644
--- a/src/sdl/i_main.c
+++ b/src/sdl/i_main.c
@@ -55,6 +55,10 @@ PSP_MAIN_THREAD_STACK_SIZE_KB(256);
 #include "i_ttf.h"
 #endif
 
+#if defined (_WIN32) && !defined (main)
+#define SDLMAIN
+#endif
+
 #ifdef SDLMAIN
 #include "SDL_main.h"
 #elif defined(FORCESDLMAIN)
@@ -132,7 +136,6 @@ static inline VOID MakeCodeWritable(VOID)
 
 	\return	int
 */
-FUNCNORETURN
 #if defined (_XBOX) && defined (__GNUC__)
 void XBoxStartup()
 {
@@ -141,8 +144,10 @@ void XBoxStartup()
 	myargv = NULL;
 #else
 #ifdef FORCESDLMAIN
+FUNCNORETURN
 int SDL_main(int argc, char **argv)
 #else
+FUNCNORETURN
 int main(int argc, char **argv)
 #endif
 {
diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c
index 66e1ece1863887f21f6b07678542da6fde715b75..db873765b3a15e9943b88a2133272313bfbecd0a 100644
--- a/src/sdl/i_system.c
+++ b/src/sdl/i_system.c
@@ -23,7 +23,7 @@
 #ifdef CMAKECONFIG
 #include "config.h"
 #else
-#include "config.h.in"
+#include "../config.h.in"
 #endif
 
 #ifndef _WIN32_WCE
diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c
index faee1bc695fc14939468d75c54f1289d815e4de0..dbb97f093eab06d11418e7d63ecf29216e22a354 100644
--- a/src/sdl/i_video.c
+++ b/src/sdl/i_video.c
@@ -217,10 +217,12 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen)
 		}
 	}
 
+#ifdef HWRENDER
 	if (rendermode == render_opengl)
 	{
 		OglSdlSurface(vid.width, vid.height);
 	}
+#endif
 
 	if (rendermode == render_soft)
 	{
@@ -401,9 +403,11 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code)
 		default:
 			break;
 	}
+#ifdef HWRENDER
 	DBG_Printf("Unknown incoming scancode: %d, represented %c\n",
 				code,
 				SDL_GetKeyName(SDL_GetKeyFromScancode(code)));
+#endif
 	return 0;
 }
 
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 6e19b92ff05a3fe436c4e7ab5010ecb942ec12cf..ba5ae1ec084b853b9299ef8aa3d11f73bd7bdb9d 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -888,8 +888,8 @@ static void ST_drawFirstPersonHUD(void)
 
 // [21:42] <+Rob> Beige - Lavender - Steel Blue - Peach - Orange - Purple - Silver - Yellow - Pink - Red - Blue - Green - Cyan - Gold
 static skincolors_t linkColor[14] =
-{SKINCOLOR_BEIGE,  SKINCOLOR_LAVENDER, SKINCOLOR_STEELBLUE, SKINCOLOR_PEACH, SKINCOLOR_ORANGE,
- SKINCOLOR_PURPLE, SKINCOLOR_SILVER,   SKINCOLOR_SUPER4,    SKINCOLOR_PINK,  SKINCOLOR_RED,
+{SKINCOLOR_BEIGE,  SKINCOLOR_LAVENDER, SKINCOLOR_AZURE, SKINCOLOR_PEACH, SKINCOLOR_ORANGE,
+ SKINCOLOR_MAGENTA, SKINCOLOR_SILVER,   SKINCOLOR_SUPER4,    SKINCOLOR_PINK,  SKINCOLOR_RED,
  SKINCOLOR_BLUE,   SKINCOLOR_GREEN,    SKINCOLOR_CYAN,      SKINCOLOR_GOLD};
 
 static void ST_drawNightsRecords(void)
@@ -938,7 +938,7 @@ static void ST_drawNightsRecords(void)
 		V_DrawString(BASEVIDWIDTH/2 - 48, STRINGY(148), aflag, "BONUS:");
 		V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(140), V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings));
 		V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(148), V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings * 50));
-		ST_DrawNightsOverlayNum(BASEVIDWIDTH/2 + 48, STRINGY(160), aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_STEELBLUE);
+		ST_DrawNightsOverlayNum(BASEVIDWIDTH/2 + 48, STRINGY(160), aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_AZURE);
 
 		// If new record, say so!
 		if (!(netgame || multiplayer) && G_GetBestNightsScore(gamemap, stplyr->lastmare + 1) <= stplyr->lastmarescore)
@@ -1220,7 +1220,7 @@ static void ST_drawNiGHTSHUD(void)
 #endif
 	)
 	{
-		ST_DrawNightsOverlayNum(304, STRINGY(16), SPLITFLAGS(V_SNAPTOTOP)|V_SNAPTORIGHT, stplyr->marescore, nightsnum, SKINCOLOR_STEELBLUE);
+		ST_DrawNightsOverlayNum(304, STRINGY(16), SPLITFLAGS(V_SNAPTOTOP)|V_SNAPTORIGHT, stplyr->marescore, nightsnum, SKINCOLOR_AZURE);
 	}
 
 	if (!stplyr->exiting
@@ -1842,37 +1842,6 @@ static void ST_overlayDrawer(void)
 		LUAh_GameHUD(stplyr);
 #endif
 
-#if 0 // Pope XVI
-	if (!(netgame || multiplayer) && !modifiedgame && gamemap == 11 && ALL7EMERALDS(emeralds)
-		&& stplyr->mo && stplyr->mo->subsector && stplyr->mo->subsector->sector-sectors == 1361)
-	{
-		if (grade & 2048) // NAGZ
-		{
-			V_DrawCenteredString(BASEVIDWIDTH/2, 70, 0, M_GetText("I, Pope Rededict XVI proclaim"));
-			V_DrawCenteredString(BASEVIDWIDTH/2, 80, 0, M_GetText("AJ & Amy"));
-			V_DrawCenteredString(BASEVIDWIDTH/2, 90, 0, M_GetText("Husband & Wife"));
-			V_DrawCenteredString(BASEVIDWIDTH/2, 100, 0, M_GetText("on this day"));
-			V_DrawCenteredString(BASEVIDWIDTH/2, 110, 0, M_GetText("May 16, 2009"));
-
-			P_GivePlayerRings(stplyr, 9999);
-		}
-		else
-		{
-			V_DrawCenteredString(BASEVIDWIDTH/2,  60, 0, M_GetText("Oh... it's you again..."));
-			V_DrawCenteredString(BASEVIDWIDTH/2,  80, 0, M_GetText("Look, I wanted to apologize for the way"));
-			V_DrawCenteredString(BASEVIDWIDTH/2,  90, 0, M_GetText("I've acted in the past."));
-			V_DrawCenteredString(BASEVIDWIDTH/2, 110, 0, M_GetText("I've seen the error of my ways"));
-			V_DrawCenteredString(BASEVIDWIDTH/2, 120, 0, M_GetText("and turned over a new leaf."));
-			V_DrawCenteredString(BASEVIDWIDTH/2, 140, 0, M_GetText("Instead of sending people to hell,"));
-			V_DrawCenteredString(BASEVIDWIDTH/2, 150, 0, M_GetText("I now send them to heaven!"));
-
-			P_LinedefExecute(4200, stplyr->mo, stplyr->mo->subsector->sector);
-			P_LinedefExecute(4201, stplyr->mo, stplyr->mo->subsector->sector);
-			stplyr->mo->momx = stplyr->mo->momy = 0;
-		}
-	}
-#endif
-
 	// draw level title Tails
 	if (*mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer))
 #ifdef HAVE_BLUA
diff --git a/src/tables.c b/src/tables.c
index fa71effef44bd50761014a2db52580f672421f56..3f881be7d7d8247d121be61360f6c6a3f7f0fa07 100644
--- a/src/tables.c
+++ b/src/tables.c
@@ -162,1807 +162,1807 @@ angle_t FixedAngle(fixed_t fa)
 #if !(defined _NDS) || !(defined NONET)
 fixed_t finetangent[4096] =
 {
-	-170910304, -56965752, -34178904, -24413316, -18988036, -15535599, -13145455, -11392683,
-	-10052327, -8994149, -8137527, -7429880, -6835455, -6329090, -5892567, -5512368,
-	-5178251, -4882318, -4618375, -4381502, -4167737, -3973855, -3797206, -3635590,
-	-3487165, -3350381, -3223918, -3106651, -2997613, -2895966, -2800983, -2712030,
-	-2628549, -2550052, -2476104, -2406322, -2340362, -2277919, -2218719, -2162516,
-	-2109087, -2058233, -2009771, -1963536, -1919378, -1877161, -1836758, -1798063,
-	-1760956, -1725348, -1691149, -1658278, -1626658, -1596220, -1566898, -1538632,
-	-1511367, -1485049, -1459630, -1435065, -1411312, -1388330, -1366084, -1344537,
-	-1323658, -1303416, -1283783, -1264730, -1246234, -1228269, -1210813, -1193846,
-	-1177345, -1161294, -1145673, -1130465, -1115654, -1101225, -1087164, -1073455,
-	-1060087, -1047046, -1034322, -1021901, -1009774, -997931, -986361, -975054,
-	-964003, -953199, -942633, -932298, -922186, -912289, -902602, -893117,
-	-883829, -874730, -865817, -857081, -848520, -840127, -831898, -823827,
-	-815910, -808143, -800521, -793041, -785699, -778490, -771411, -764460,
-	-757631, -750922, -744331, -737853, -731486, -725227, -719074, -713023,
-	-707072, -701219, -695462, -689797, -684223, -678737, -673338, -668024,
-	-662792, -657640, -652568, -647572, -642651, -637803, -633028, -628323,
-	-623686, -619117, -614613, -610174, -605798, -601483, -597229, -593033,
-	-588896, -584815, -580789, -576818, -572901, -569035, -565221, -561456,
-	-557741, -554074, -550455, -546881, -543354, -539870, -536431, -533034,
-	-529680, -526366, -523094, -519861, -516667, -513512, -510394, -507313,
-	-504269, -501261, -498287, -495348, -492443, -489571, -486732, -483925,
-	-481150, -478406, -475692, -473009, -470355, -467730, -465133, -462565,
-	-460024, -457511, -455024, -452564, -450129, -447720, -445337, -442978,
-	-440643, -438332, -436045, -433781, -431540, -429321, -427125, -424951,
-	-422798, -420666, -418555, -416465, -414395, -412344, -410314, -408303,
-	-406311, -404338, -402384, -400448, -398530, -396630, -394747, -392882,
-	-391034, -389202, -387387, -385589, -383807, -382040, -380290, -378555,
-	-376835, -375130, -373440, -371765, -370105, -368459, -366826, -365208,
-	-363604, -362013, -360436, -358872, -357321, -355783, -354257, -352744,
-	-351244, -349756, -348280, -346816, -345364, -343924, -342495, -341078,
-	-339671, -338276, -336892, -335519, -334157, -332805, -331464, -330133,
-	-328812, -327502, -326201, -324910, -323629, -322358, -321097, -319844,
-	-318601, -317368, -316143, -314928, -313721, -312524, -311335, -310154,
-	-308983, -307819, -306664, -305517, -304379, -303248, -302126, -301011,
-	-299904, -298805, -297714, -296630, -295554, -294485, -293423, -292369,
-	-291322, -290282, -289249, -288223, -287204, -286192, -285186, -284188,
-	-283195, -282210, -281231, -280258, -279292, -278332, -277378, -276430,
-	-275489, -274553, -273624, -272700, -271782, -270871, -269965, -269064,
-	-268169, -267280, -266397, -265519, -264646, -263779, -262917, -262060,
-	-261209, -260363, -259522, -258686, -257855, -257029, -256208, -255392,
-	-254581, -253774, -252973, -252176, -251384, -250596, -249813, -249035,
-	-248261, -247492, -246727, -245966, -245210, -244458, -243711, -242967,
-	-242228, -241493, -240763, -240036, -239314, -238595, -237881, -237170,
-	-236463, -235761, -235062, -234367, -233676, -232988, -232304, -231624,
-	-230948, -230275, -229606, -228941, -228279, -227621, -226966, -226314,
-	-225666, -225022, -224381, -223743, -223108, -222477, -221849, -221225,
-	-220603, -219985, -219370, -218758, -218149, -217544, -216941, -216341,
-	-215745, -215151, -214561, -213973, -213389, -212807, -212228, -211652,
-	-211079, -210509, -209941, -209376, -208815, -208255, -207699, -207145,
-	-206594, -206045, -205500, -204956, -204416, -203878, -203342, -202809,
-	-202279, -201751, -201226, -200703, -200182, -199664, -199149, -198636,
-	-198125, -197616, -197110, -196606, -196105, -195606, -195109, -194614,
-	-194122, -193631, -193143, -192658, -192174, -191693, -191213, -190736,
-	-190261, -189789, -189318, -188849, -188382, -187918, -187455, -186995,
-	-186536, -186080, -185625, -185173, -184722, -184274, -183827, -183382,
-	-182939, -182498, -182059, -181622, -181186, -180753, -180321, -179891,
-	-179463, -179037, -178612, -178190, -177769, -177349, -176932, -176516,
-	-176102, -175690, -175279, -174870, -174463, -174057, -173653, -173251,
-	-172850, -172451, -172053, -171657, -171263, -170870, -170479, -170089,
-	-169701, -169315, -168930, -168546, -168164, -167784, -167405, -167027,
-	-166651, -166277, -165904, -165532, -165162, -164793, -164426, -164060,
-	-163695, -163332, -162970, -162610, -162251, -161893, -161537, -161182,
-	-160828, -160476, -160125, -159775, -159427, -159079, -158734, -158389,
-	-158046, -157704, -157363, -157024, -156686, -156349, -156013, -155678,
-	-155345, -155013, -154682, -154352, -154024, -153697, -153370, -153045,
-	-152722, -152399, -152077, -151757, -151438, -151120, -150803, -150487,
-	-150172, -149859, -149546, -149235, -148924, -148615, -148307, -148000,
-	-147693, -147388, -147084, -146782, -146480, -146179, -145879, -145580,
-	-145282, -144986, -144690, -144395, -144101, -143808, -143517, -143226,
-	-142936, -142647, -142359, -142072, -141786, -141501, -141217, -140934,
-	-140651, -140370, -140090, -139810, -139532, -139254, -138977, -138701,
-	-138426, -138152, -137879, -137607, -137335, -137065, -136795, -136526,
-	-136258, -135991, -135725, -135459, -135195, -134931, -134668, -134406,
-	-134145, -133884, -133625, -133366, -133108, -132851, -132594, -132339,
-	-132084, -131830, -131576, -131324, -131072, -130821, -130571, -130322,
-	-130073, -129825, -129578, -129332, -129086, -128841, -128597, -128353,
-	-128111, -127869, -127627, -127387, -127147, -126908, -126669, -126432,
-	-126195, -125959, -125723, -125488, -125254, -125020, -124787, -124555,
-	-124324, -124093, -123863, -123633, -123404, -123176, -122949, -122722,
-	-122496, -122270, -122045, -121821, -121597, -121374, -121152, -120930,
-	-120709, -120489, -120269, -120050, -119831, -119613, -119396, -119179,
-	-118963, -118747, -118532, -118318, -118104, -117891, -117678, -117466,
-	-117254, -117044, -116833, -116623, -116414, -116206, -115998, -115790,
-	-115583, -115377, -115171, -114966, -114761, -114557, -114354, -114151,
-	-113948, -113746, -113545, -113344, -113143, -112944, -112744, -112546,
-	-112347, -112150, -111952, -111756, -111560, -111364, -111169, -110974,
-	-110780, -110586, -110393, -110200, -110008, -109817, -109626, -109435,
-	-109245, -109055, -108866, -108677, -108489, -108301, -108114, -107927,
-	-107741, -107555, -107369, -107184, -107000, -106816, -106632, -106449,
-	-106266, -106084, -105902, -105721, -105540, -105360, -105180, -105000,
-	-104821, -104643, -104465, -104287, -104109, -103933, -103756, -103580,
-	-103404, -103229, -103054, -102880, -102706, -102533, -102360, -102187,
-	-102015, -101843, -101671, -101500, -101330, -101159, -100990, -100820,
-	-100651, -100482, -100314, -100146, -99979, -99812, -99645, -99479,
-	-99313, -99148, -98982, -98818, -98653, -98489, -98326, -98163,
-	-98000, -97837, -97675, -97513, -97352, -97191, -97030, -96870,
-	-96710, -96551, -96391, -96233, -96074, -95916, -95758, -95601,
-	-95444, -95287, -95131, -94975, -94819, -94664, -94509, -94354,
-	-94200, -94046, -93892, -93739, -93586, -93434, -93281, -93129,
-	-92978, -92826, -92675, -92525, -92375, -92225, -92075, -91926,
-	-91777, -91628, -91480, -91332, -91184, -91036, -90889, -90742,
-	-90596, -90450, -90304, -90158, -90013, -89868, -89724, -89579,
-	-89435, -89292, -89148, -89005, -88862, -88720, -88577, -88435,
-	-88294, -88152, -88011, -87871, -87730, -87590, -87450, -87310,
-	-87171, -87032, -86893, -86755, -86616, -86479, -86341, -86204,
-	-86066, -85930, -85793, -85657, -85521, -85385, -85250, -85114,
-	-84980, -84845, -84710, -84576, -84443, -84309, -84176, -84043,
-	-83910, -83777, -83645, -83513, -83381, -83250, -83118, -82987,
-	-82857, -82726, -82596, -82466, -82336, -82207, -82078, -81949,
-	-81820, -81691, -81563, -81435, -81307, -81180, -81053, -80925,
-	-80799, -80672, -80546, -80420, -80294, -80168, -80043, -79918,
-	-79793, -79668, -79544, -79420, -79296, -79172, -79048, -78925,
-	-78802, -78679, -78557, -78434, -78312, -78190, -78068, -77947,
-	-77826, -77705, -77584, -77463, -77343, -77223, -77103, -76983,
-	-76864, -76744, -76625, -76506, -76388, -76269, -76151, -76033,
-	-75915, -75797, -75680, -75563, -75446, -75329, -75213, -75096,
-	-74980, -74864, -74748, -74633, -74517, -74402, -74287, -74172,
-	-74058, -73944, -73829, -73715, -73602, -73488, -73375, -73262,
-	-73149, -73036, -72923, -72811, -72699, -72587, -72475, -72363,
-	-72252, -72140, -72029, -71918, -71808, -71697, -71587, -71477,
-	-71367, -71257, -71147, -71038, -70929, -70820, -70711, -70602,
-	-70494, -70385, -70277, -70169, -70061, -69954, -69846, -69739,
-	-69632, -69525, -69418, -69312, -69205, -69099, -68993, -68887,
-	-68781, -68676, -68570, -68465, -68360, -68255, -68151, -68046,
-	-67942, -67837, -67733, -67629, -67526, -67422, -67319, -67216,
-	-67113, -67010, -66907, -66804, -66702, -66600, -66498, -66396,
-	-66294, -66192, -66091, -65989, -65888, -65787, -65686, -65586,
-	-65485, -65385, -65285, -65185, -65085, -64985, -64885, -64786,
-	-64687, -64587, -64488, -64389, -64291, -64192, -64094, -63996,
-	-63897, -63799, -63702, -63604, -63506, -63409, -63312, -63215,
-	-63118, -63021, -62924, -62828, -62731, -62635, -62539, -62443,
-	-62347, -62251, -62156, -62060, -61965, -61870, -61775, -61680,
-	-61585, -61491, -61396, -61302, -61208, -61114, -61020, -60926,
-	-60833, -60739, -60646, -60552, -60459, -60366, -60273, -60181,
-	-60088, -59996, -59903, -59811, -59719, -59627, -59535, -59444,
-	-59352, -59261, -59169, -59078, -58987, -58896, -58805, -58715,
-	-58624, -58534, -58443, -58353, -58263, -58173, -58083, -57994,
-	-57904, -57815, -57725, -57636, -57547, -57458, -57369, -57281,
-	-57192, -57104, -57015, -56927, -56839, -56751, -56663, -56575,
-	-56487, -56400, -56312, -56225, -56138, -56051, -55964, -55877,
-	-55790, -55704, -55617, -55531, -55444, -55358, -55272, -55186,
-	-55100, -55015, -54929, -54843, -54758, -54673, -54587, -54502,
-	-54417, -54333, -54248, -54163, -54079, -53994, -53910, -53826,
-	-53741, -53657, -53574, -53490, -53406, -53322, -53239, -53156,
-	-53072, -52989, -52906, -52823, -52740, -52657, -52575, -52492,
-	-52410, -52327, -52245, -52163, -52081, -51999, -51917, -51835,
-	-51754, -51672, -51591, -51509, -51428, -51347, -51266, -51185,
-	-51104, -51023, -50942, -50862, -50781, -50701, -50621, -50540,
-	-50460, -50380, -50300, -50221, -50141, -50061, -49982, -49902,
-	-49823, -49744, -49664, -49585, -49506, -49427, -49349, -49270,
-	-49191, -49113, -49034, -48956, -48878, -48799, -48721, -48643,
-	-48565, -48488, -48410, -48332, -48255, -48177, -48100, -48022,
-	-47945, -47868, -47791, -47714, -47637, -47560, -47484, -47407,
-	-47331, -47254, -47178, -47102, -47025, -46949, -46873, -46797,
-	-46721, -46646, -46570, -46494, -46419, -46343, -46268, -46193,
-	-46118, -46042, -45967, -45892, -45818, -45743, -45668, -45593,
-	-45519, -45444, -45370, -45296, -45221, -45147, -45073, -44999,
-	-44925, -44851, -44778, -44704, -44630, -44557, -44483, -44410,
-	-44337, -44263, -44190, -44117, -44044, -43971, -43898, -43826,
-	-43753, -43680, -43608, -43535, -43463, -43390, -43318, -43246,
-	-43174, -43102, -43030, -42958, -42886, -42814, -42743, -42671,
-	-42600, -42528, -42457, -42385, -42314, -42243, -42172, -42101,
-	-42030, -41959, -41888, -41817, -41747, -41676, -41605, -41535,
-	-41465, -41394, -41324, -41254, -41184, -41113, -41043, -40973,
-	-40904, -40834, -40764, -40694, -40625, -40555, -40486, -40416,
-	-40347, -40278, -40208, -40139, -40070, -40001, -39932, -39863,
-	-39794, -39726, -39657, -39588, -39520, -39451, -39383, -39314,
-	-39246, -39178, -39110, -39042, -38973, -38905, -38837, -38770,
-	-38702, -38634, -38566, -38499, -38431, -38364, -38296, -38229,
-	-38161, -38094, -38027, -37960, -37893, -37826, -37759, -37692,
-	-37625, -37558, -37491, -37425, -37358, -37291, -37225, -37158,
-	-37092, -37026, -36959, -36893, -36827, -36761, -36695, -36629,
-	-36563, -36497, -36431, -36365, -36300, -36234, -36168, -36103,
-	-36037, -35972, -35907, -35841, -35776, -35711, -35646, -35580,
-	-35515, -35450, -35385, -35321, -35256, -35191, -35126, -35062,
-	-34997, -34932, -34868, -34803, -34739, -34675, -34610, -34546,
-	-34482, -34418, -34354, -34289, -34225, -34162, -34098, -34034,
-	-33970, -33906, -33843, -33779, -33715, -33652, -33588, -33525,
-	-33461, -33398, -33335, -33272, -33208, -33145, -33082, -33019,
-	-32956, -32893, -32830, -32767, -32705, -32642, -32579, -32516,
-	-32454, -32391, -32329, -32266, -32204, -32141, -32079, -32017,
-	-31955, -31892, -31830, -31768, -31706, -31644, -31582, -31520,
-	-31458, -31396, -31335, -31273, -31211, -31150, -31088, -31026,
-	-30965, -30904, -30842, -30781, -30719, -30658, -30597, -30536,
-	-30474, -30413, -30352, -30291, -30230, -30169, -30108, -30048,
-	-29987, -29926, -29865, -29805, -29744, -29683, -29623, -29562,
-	-29502, -29441, -29381, -29321, -29260, -29200, -29140, -29080,
-	-29020, -28959, -28899, -28839, -28779, -28719, -28660, -28600,
-	-28540, -28480, -28420, -28361, -28301, -28241, -28182, -28122,
-	-28063, -28003, -27944, -27884, -27825, -27766, -27707, -27647,
-	-27588, -27529, -27470, -27411, -27352, -27293, -27234, -27175,
-	-27116, -27057, -26998, -26940, -26881, -26822, -26763, -26705,
-	-26646, -26588, -26529, -26471, -26412, -26354, -26295, -26237,
-	-26179, -26120, -26062, -26004, -25946, -25888, -25830, -25772,
-	-25714, -25656, -25598, -25540, -25482, -25424, -25366, -25308,
-	-25251, -25193, -25135, -25078, -25020, -24962, -24905, -24847,
-	-24790, -24732, -24675, -24618, -24560, -24503, -24446, -24389,
-	-24331, -24274, -24217, -24160, -24103, -24046, -23989, -23932,
-	-23875, -23818, -23761, -23704, -23647, -23591, -23534, -23477,
-	-23420, -23364, -23307, -23250, -23194, -23137, -23081, -23024,
-	-22968, -22911, -22855, -22799, -22742, -22686, -22630, -22573,
-	-22517, -22461, -22405, -22349, -22293, -22237, -22181, -22125,
-	-22069, -22013, -21957, -21901, -21845, -21789, -21733, -21678,
-	-21622, -21566, -21510, -21455, -21399, -21343, -21288, -21232,
-	-21177, -21121, -21066, -21010, -20955, -20900, -20844, -20789,
-	-20734, -20678, -20623, -20568, -20513, -20457, -20402, -20347,
-	-20292, -20237, -20182, -20127, -20072, -20017, -19962, -19907,
-	-19852, -19797, -19742, -19688, -19633, -19578, -19523, -19469,
-	-19414, -19359, -19305, -19250, -19195, -19141, -19086, -19032,
-	-18977, -18923, -18868, -18814, -18760, -18705, -18651, -18597,
-	-18542, -18488, -18434, -18380, -18325, -18271, -18217, -18163,
-	-18109, -18055, -18001, -17946, -17892, -17838, -17784, -17731,
-	-17677, -17623, -17569, -17515, -17461, -17407, -17353, -17300,
-	-17246, -17192, -17138, -17085, -17031, -16977, -16924, -16870,
-	-16817, -16763, -16710, -16656, -16603, -16549, -16496, -16442,
-	-16389, -16335, -16282, -16229, -16175, -16122, -16069, -16015,
-	-15962, -15909, -15856, -15802, -15749, -15696, -15643, -15590,
-	-15537, -15484, -15431, -15378, -15325, -15272, -15219, -15166,
-	-15113, -15060, -15007, -14954, -14901, -14848, -14795, -14743,
-	-14690, -14637, -14584, -14531, -14479, -14426, -14373, -14321,
-	-14268, -14215, -14163, -14110, -14057, -14005, -13952, -13900,
-	-13847, -13795, -13742, -13690, -13637, -13585, -13533, -13480,
-	-13428, -13375, -13323, -13271, -13218, -13166, -13114, -13062,
-	-13009, -12957, -12905, -12853, -12800, -12748, -12696, -12644,
-	-12592, -12540, -12488, -12436, -12383, -12331, -12279, -12227,
-	-12175, -12123, -12071, -12019, -11967, -11916, -11864, -11812,
-	-11760, -11708, -11656, -11604, -11552, -11501, -11449, -11397,
-	-11345, -11293, -11242, -11190, -11138, -11086, -11035, -10983,
-	-10931, -10880, -10828, -10777, -10725, -10673, -10622, -10570,
-	-10519, -10467, -10415, -10364, -10312, -10261, -10209, -10158,
-	-10106, -10055, -10004, -9952, -9901, -9849, -9798, -9747,
-	-9695, -9644, -9592, -9541, -9490, -9438, -9387, -9336,
-	-9285, -9233, -9182, -9131, -9080, -9028, -8977, -8926,
-	-8875, -8824, -8772, -8721, -8670, -8619, -8568, -8517,
-	-8466, -8414, -8363, -8312, -8261, -8210, -8159, -8108,
-	-8057, -8006, -7955, -7904, -7853, -7802, -7751, -7700,
-	-7649, -7598, -7547, -7496, -7445, -7395, -7344, -7293,
-	-7242, -7191, -7140, -7089, -7038, -6988, -6937, -6886,
-	-6835, -6784, -6733, -6683, -6632, -6581, -6530, -6480,
-	-6429, -6378, -6327, -6277, -6226, -6175, -6124, -6074,
-	-6023, -5972, -5922, -5871, -5820, -5770, -5719, -5668,
-	-5618, -5567, -5517, -5466, -5415, -5365, -5314, -5264,
-	-5213, -5162, -5112, -5061, -5011, -4960, -4910, -4859,
-	-4808, -4758, -4707, -4657, -4606, -4556, -4505, -4455,
-	-4404, -4354, -4303, -4253, -4202, -4152, -4101, -4051,
-	-4001, -3950, -3900, -3849, -3799, -3748, -3698, -3648,
-	-3597, -3547, -3496, -3446, -3395, -3345, -3295, -3244,
-	-3194, -3144, -3093, -3043, -2992, -2942, -2892, -2841,
-	-2791, -2741, -2690, -2640, -2590, -2539, -2489, -2439,
-	-2388, -2338, -2288, -2237, -2187, -2137, -2086, -2036,
-	-1986, -1935, -1885, -1835, -1784, -1734, -1684, -1633,
-	-1583, -1533, -1483, -1432, -1382, -1332, -1281, -1231,
-	-1181, -1131, -1080, -1030, -980, -929, -879, -829,
-	-779, -728, -678, -628, -578, -527, -477, -427,
-	-376, -326, -276, -226, -175, -125, -75, -25,
-	25, 75, 125, 175, 226, 276, 326, 376,
-	427, 477, 527, 578, 628, 678, 728, 779,
-	829, 879, 929, 980, 1030, 1080, 1131, 1181,
-	1231, 1281, 1332, 1382, 1432, 1483, 1533, 1583,
-	1633, 1684, 1734, 1784, 1835, 1885, 1935, 1986,
-	2036, 2086, 2137, 2187, 2237, 2288, 2338, 2388,
-	2439, 2489, 2539, 2590, 2640, 2690, 2741, 2791,
-	2841, 2892, 2942, 2992, 3043, 3093, 3144, 3194,
-	3244, 3295, 3345, 3395, 3446, 3496, 3547, 3597,
-	3648, 3698, 3748, 3799, 3849, 3900, 3950, 4001,
-	4051, 4101, 4152, 4202, 4253, 4303, 4354, 4404,
-	4455, 4505, 4556, 4606, 4657, 4707, 4758, 4808,
-	4859, 4910, 4960, 5011, 5061, 5112, 5162, 5213,
-	5264, 5314, 5365, 5415, 5466, 5517, 5567, 5618,
-	5668, 5719, 5770, 5820, 5871, 5922, 5972, 6023,
-	6074, 6124, 6175, 6226, 6277, 6327, 6378, 6429,
-	6480, 6530, 6581, 6632, 6683, 6733, 6784, 6835,
-	6886, 6937, 6988, 7038, 7089, 7140, 7191, 7242,
-	7293, 7344, 7395, 7445, 7496, 7547, 7598, 7649,
-	7700, 7751, 7802, 7853, 7904, 7955, 8006, 8057,
-	8108, 8159, 8210, 8261, 8312, 8363, 8414, 8466,
-	8517, 8568, 8619, 8670, 8721, 8772, 8824, 8875,
-	8926, 8977, 9028, 9080, 9131, 9182, 9233, 9285,
-	9336, 9387, 9438, 9490, 9541, 9592, 9644, 9695,
-	9747, 9798, 9849, 9901, 9952, 10004, 10055, 10106,
-	10158, 10209, 10261, 10312, 10364, 10415, 10467, 10519,
-	10570, 10622, 10673, 10725, 10777, 10828, 10880, 10931,
-	10983, 11035, 11086, 11138, 11190, 11242, 11293, 11345,
-	11397, 11449, 11501, 11552, 11604, 11656, 11708, 11760,
-	11812, 11864, 11916, 11967, 12019, 12071, 12123, 12175,
-	12227, 12279, 12331, 12383, 12436, 12488, 12540, 12592,
-	12644, 12696, 12748, 12800, 12853, 12905, 12957, 13009,
-	13062, 13114, 13166, 13218, 13271, 13323, 13375, 13428,
-	13480, 13533, 13585, 13637, 13690, 13742, 13795, 13847,
-	13900, 13952, 14005, 14057, 14110, 14163, 14215, 14268,
-	14321, 14373, 14426, 14479, 14531, 14584, 14637, 14690,
-	14743, 14795, 14848, 14901, 14954, 15007, 15060, 15113,
-	15166, 15219, 15272, 15325, 15378, 15431, 15484, 15537,
-	15590, 15643, 15696, 15749, 15802, 15856, 15909, 15962,
-	16015, 16069, 16122, 16175, 16229, 16282, 16335, 16389,
-	16442, 16496, 16549, 16603, 16656, 16710, 16763, 16817,
-	16870, 16924, 16977, 17031, 17085, 17138, 17192, 17246,
-	17300, 17353, 17407, 17461, 17515, 17569, 17623, 17677,
-	17731, 17784, 17838, 17892, 17946, 18001, 18055, 18109,
-	18163, 18217, 18271, 18325, 18380, 18434, 18488, 18542,
-	18597, 18651, 18705, 18760, 18814, 18868, 18923, 18977,
-	19032, 19086, 19141, 19195, 19250, 19305, 19359, 19414,
-	19469, 19523, 19578, 19633, 19688, 19742, 19797, 19852,
-	19907, 19962, 20017, 20072, 20127, 20182, 20237, 20292,
-	20347, 20402, 20457, 20513, 20568, 20623, 20678, 20734,
-	20789, 20844, 20900, 20955, 21010, 21066, 21121, 21177,
-	21232, 21288, 21343, 21399, 21455, 21510, 21566, 21622,
-	21678, 21733, 21789, 21845, 21901, 21957, 22013, 22069,
-	22125, 22181, 22237, 22293, 22349, 22405, 22461, 22517,
-	22573, 22630, 22686, 22742, 22799, 22855, 22911, 22968,
-	23024, 23081, 23137, 23194, 23250, 23307, 23364, 23420,
-	23477, 23534, 23591, 23647, 23704, 23761, 23818, 23875,
-	23932, 23989, 24046, 24103, 24160, 24217, 24274, 24331,
-	24389, 24446, 24503, 24560, 24618, 24675, 24732, 24790,
-	24847, 24905, 24962, 25020, 25078, 25135, 25193, 25251,
-	25308, 25366, 25424, 25482, 25540, 25598, 25656, 25714,
-	25772, 25830, 25888, 25946, 26004, 26062, 26120, 26179,
-	26237, 26295, 26354, 26412, 26471, 26529, 26588, 26646,
-	26705, 26763, 26822, 26881, 26940, 26998, 27057, 27116,
-	27175, 27234, 27293, 27352, 27411, 27470, 27529, 27588,
-	27647, 27707, 27766, 27825, 27884, 27944, 28003, 28063,
-	28122, 28182, 28241, 28301, 28361, 28420, 28480, 28540,
-	28600, 28660, 28719, 28779, 28839, 28899, 28959, 29020,
-	29080, 29140, 29200, 29260, 29321, 29381, 29441, 29502,
-	29562, 29623, 29683, 29744, 29805, 29865, 29926, 29987,
-	30048, 30108, 30169, 30230, 30291, 30352, 30413, 30474,
-	30536, 30597, 30658, 30719, 30781, 30842, 30904, 30965,
-	31026, 31088, 31150, 31211, 31273, 31335, 31396, 31458,
-	31520, 31582, 31644, 31706, 31768, 31830, 31892, 31955,
-	32017, 32079, 32141, 32204, 32266, 32329, 32391, 32454,
-	32516, 32579, 32642, 32705, 32767, 32830, 32893, 32956,
-	33019, 33082, 33145, 33208, 33272, 33335, 33398, 33461,
-	33525, 33588, 33652, 33715, 33779, 33843, 33906, 33970,
-	34034, 34098, 34162, 34225, 34289, 34354, 34418, 34482,
-	34546, 34610, 34675, 34739, 34803, 34868, 34932, 34997,
-	35062, 35126, 35191, 35256, 35321, 35385, 35450, 35515,
-	35580, 35646, 35711, 35776, 35841, 35907, 35972, 36037,
-	36103, 36168, 36234, 36300, 36365, 36431, 36497, 36563,
-	36629, 36695, 36761, 36827, 36893, 36959, 37026, 37092,
-	37158, 37225, 37291, 37358, 37425, 37491, 37558, 37625,
-	37692, 37759, 37826, 37893, 37960, 38027, 38094, 38161,
-	38229, 38296, 38364, 38431, 38499, 38566, 38634, 38702,
-	38770, 38837, 38905, 38973, 39042, 39110, 39178, 39246,
-	39314, 39383, 39451, 39520, 39588, 39657, 39726, 39794,
-	39863, 39932, 40001, 40070, 40139, 40208, 40278, 40347,
-	40416, 40486, 40555, 40625, 40694, 40764, 40834, 40904,
-	40973, 41043, 41113, 41184, 41254, 41324, 41394, 41465,
-	41535, 41605, 41676, 41747, 41817, 41888, 41959, 42030,
-	42101, 42172, 42243, 42314, 42385, 42457, 42528, 42600,
-	42671, 42743, 42814, 42886, 42958, 43030, 43102, 43174,
-	43246, 43318, 43390, 43463, 43535, 43608, 43680, 43753,
-	43826, 43898, 43971, 44044, 44117, 44190, 44263, 44337,
-	44410, 44483, 44557, 44630, 44704, 44778, 44851, 44925,
-	44999, 45073, 45147, 45221, 45296, 45370, 45444, 45519,
-	45593, 45668, 45743, 45818, 45892, 45967, 46042, 46118,
-	46193, 46268, 46343, 46419, 46494, 46570, 46646, 46721,
-	46797, 46873, 46949, 47025, 47102, 47178, 47254, 47331,
-	47407, 47484, 47560, 47637, 47714, 47791, 47868, 47945,
-	48022, 48100, 48177, 48255, 48332, 48410, 48488, 48565,
-	48643, 48721, 48799, 48878, 48956, 49034, 49113, 49191,
-	49270, 49349, 49427, 49506, 49585, 49664, 49744, 49823,
-	49902, 49982, 50061, 50141, 50221, 50300, 50380, 50460,
-	50540, 50621, 50701, 50781, 50862, 50942, 51023, 51104,
-	51185, 51266, 51347, 51428, 51509, 51591, 51672, 51754,
-	51835, 51917, 51999, 52081, 52163, 52245, 52327, 52410,
-	52492, 52575, 52657, 52740, 52823, 52906, 52989, 53072,
-	53156, 53239, 53322, 53406, 53490, 53574, 53657, 53741,
-	53826, 53910, 53994, 54079, 54163, 54248, 54333, 54417,
-	54502, 54587, 54673, 54758, 54843, 54929, 55015, 55100,
-	55186, 55272, 55358, 55444, 55531, 55617, 55704, 55790,
-	55877, 55964, 56051, 56138, 56225, 56312, 56400, 56487,
-	56575, 56663, 56751, 56839, 56927, 57015, 57104, 57192,
-	57281, 57369, 57458, 57547, 57636, 57725, 57815, 57904,
-	57994, 58083, 58173, 58263, 58353, 58443, 58534, 58624,
-	58715, 58805, 58896, 58987, 59078, 59169, 59261, 59352,
-	59444, 59535, 59627, 59719, 59811, 59903, 59996, 60088,
-	60181, 60273, 60366, 60459, 60552, 60646, 60739, 60833,
-	60926, 61020, 61114, 61208, 61302, 61396, 61491, 61585,
-	61680, 61775, 61870, 61965, 62060, 62156, 62251, 62347,
-	62443, 62539, 62635, 62731, 62828, 62924, 63021, 63118,
-	63215, 63312, 63409, 63506, 63604, 63702, 63799, 63897,
-	63996, 64094, 64192, 64291, 64389, 64488, 64587, 64687,
-	64786, 64885, 64985, 65085, 65185, 65285, 65385, 65485,
-	65586, 65686, 65787, 65888, 65989, 66091, 66192, 66294,
-	66396, 66498, 66600, 66702, 66804, 66907, 67010, 67113,
-	67216, 67319, 67422, 67526, 67629, 67733, 67837, 67942,
-	68046, 68151, 68255, 68360, 68465, 68570, 68676, 68781,
-	68887, 68993, 69099, 69205, 69312, 69418, 69525, 69632,
-	69739, 69846, 69954, 70061, 70169, 70277, 70385, 70494,
-	70602, 70711, 70820, 70929, 71038, 71147, 71257, 71367,
-	71477, 71587, 71697, 71808, 71918, 72029, 72140, 72252,
-	72363, 72475, 72587, 72699, 72811, 72923, 73036, 73149,
-	73262, 73375, 73488, 73602, 73715, 73829, 73944, 74058,
-	74172, 74287, 74402, 74517, 74633, 74748, 74864, 74980,
-	75096, 75213, 75329, 75446, 75563, 75680, 75797, 75915,
-	76033, 76151, 76269, 76388, 76506, 76625, 76744, 76864,
-	76983, 77103, 77223, 77343, 77463, 77584, 77705, 77826,
-	77947, 78068, 78190, 78312, 78434, 78557, 78679, 78802,
-	78925, 79048, 79172, 79296, 79420, 79544, 79668, 79793,
-	79918, 80043, 80168, 80294, 80420, 80546, 80672, 80799,
-	80925, 81053, 81180, 81307, 81435, 81563, 81691, 81820,
-	81949, 82078, 82207, 82336, 82466, 82596, 82726, 82857,
-	82987, 83118, 83250, 83381, 83513, 83645, 83777, 83910,
-	84043, 84176, 84309, 84443, 84576, 84710, 84845, 84980,
-	85114, 85250, 85385, 85521, 85657, 85793, 85930, 86066,
-	86204, 86341, 86479, 86616, 86755, 86893, 87032, 87171,
-	87310, 87450, 87590, 87730, 87871, 88011, 88152, 88294,
-	88435, 88577, 88720, 88862, 89005, 89148, 89292, 89435,
-	89579, 89724, 89868, 90013, 90158, 90304, 90450, 90596,
-	90742, 90889, 91036, 91184, 91332, 91480, 91628, 91777,
-	91926, 92075, 92225, 92375, 92525, 92675, 92826, 92978,
-	93129, 93281, 93434, 93586, 93739, 93892, 94046, 94200,
-	94354, 94509, 94664, 94819, 94975, 95131, 95287, 95444,
-	95601, 95758, 95916, 96074, 96233, 96391, 96551, 96710,
-	96870, 97030, 97191, 97352, 97513, 97675, 97837, 98000,
-	98163, 98326, 98489, 98653, 98818, 98982, 99148, 99313,
-	99479, 99645, 99812, 99979, 100146, 100314, 100482, 100651,
-	100820, 100990, 101159, 101330, 101500, 101671, 101843, 102015,
-	102187, 102360, 102533, 102706, 102880, 103054, 103229, 103404,
-	103580, 103756, 103933, 104109, 104287, 104465, 104643, 104821,
-	105000, 105180, 105360, 105540, 105721, 105902, 106084, 106266,
-	106449, 106632, 106816, 107000, 107184, 107369, 107555, 107741,
-	107927, 108114, 108301, 108489, 108677, 108866, 109055, 109245,
-	109435, 109626, 109817, 110008, 110200, 110393, 110586, 110780,
-	110974, 111169, 111364, 111560, 111756, 111952, 112150, 112347,
-	112546, 112744, 112944, 113143, 113344, 113545, 113746, 113948,
-	114151, 114354, 114557, 114761, 114966, 115171, 115377, 115583,
-	115790, 115998, 116206, 116414, 116623, 116833, 117044, 117254,
-	117466, 117678, 117891, 118104, 118318, 118532, 118747, 118963,
-	119179, 119396, 119613, 119831, 120050, 120269, 120489, 120709,
-	120930, 121152, 121374, 121597, 121821, 122045, 122270, 122496,
-	122722, 122949, 123176, 123404, 123633, 123863, 124093, 124324,
-	124555, 124787, 125020, 125254, 125488, 125723, 125959, 126195,
-	126432, 126669, 126908, 127147, 127387, 127627, 127869, 128111,
-	128353, 128597, 128841, 129086, 129332, 129578, 129825, 130073,
-	130322, 130571, 130821, 131072, 131324, 131576, 131830, 132084,
-	132339, 132594, 132851, 133108, 133366, 133625, 133884, 134145,
-	134406, 134668, 134931, 135195, 135459, 135725, 135991, 136258,
-	136526, 136795, 137065, 137335, 137607, 137879, 138152, 138426,
-	138701, 138977, 139254, 139532, 139810, 140090, 140370, 140651,
-	140934, 141217, 141501, 141786, 142072, 142359, 142647, 142936,
-	143226, 143517, 143808, 144101, 144395, 144690, 144986, 145282,
-	145580, 145879, 146179, 146480, 146782, 147084, 147388, 147693,
-	148000, 148307, 148615, 148924, 149235, 149546, 149859, 150172,
-	150487, 150803, 151120, 151438, 151757, 152077, 152399, 152722,
-	153045, 153370, 153697, 154024, 154352, 154682, 155013, 155345,
-	155678, 156013, 156349, 156686, 157024, 157363, 157704, 158046,
-	158389, 158734, 159079, 159427, 159775, 160125, 160476, 160828,
-	161182, 161537, 161893, 162251, 162610, 162970, 163332, 163695,
-	164060, 164426, 164793, 165162, 165532, 165904, 166277, 166651,
-	167027, 167405, 167784, 168164, 168546, 168930, 169315, 169701,
-	170089, 170479, 170870, 171263, 171657, 172053, 172451, 172850,
-	173251, 173653, 174057, 174463, 174870, 175279, 175690, 176102,
-	176516, 176932, 177349, 177769, 178190, 178612, 179037, 179463,
-	179891, 180321, 180753, 181186, 181622, 182059, 182498, 182939,
-	183382, 183827, 184274, 184722, 185173, 185625, 186080, 186536,
-	186995, 187455, 187918, 188382, 188849, 189318, 189789, 190261,
-	190736, 191213, 191693, 192174, 192658, 193143, 193631, 194122,
-	194614, 195109, 195606, 196105, 196606, 197110, 197616, 198125,
-	198636, 199149, 199664, 200182, 200703, 201226, 201751, 202279,
-	202809, 203342, 203878, 204416, 204956, 205500, 206045, 206594,
-	207145, 207699, 208255, 208815, 209376, 209941, 210509, 211079,
-	211652, 212228, 212807, 213389, 213973, 214561, 215151, 215745,
-	216341, 216941, 217544, 218149, 218758, 219370, 219985, 220603,
-	221225, 221849, 222477, 223108, 223743, 224381, 225022, 225666,
-	226314, 226966, 227621, 228279, 228941, 229606, 230275, 230948,
-	231624, 232304, 232988, 233676, 234367, 235062, 235761, 236463,
-	237170, 237881, 238595, 239314, 240036, 240763, 241493, 242228,
-	242967, 243711, 244458, 245210, 245966, 246727, 247492, 248261,
-	249035, 249813, 250596, 251384, 252176, 252973, 253774, 254581,
-	255392, 256208, 257029, 257855, 258686, 259522, 260363, 261209,
-	262060, 262917, 263779, 264646, 265519, 266397, 267280, 268169,
-	269064, 269965, 270871, 271782, 272700, 273624, 274553, 275489,
-	276430, 277378, 278332, 279292, 280258, 281231, 282210, 283195,
-	284188, 285186, 286192, 287204, 288223, 289249, 290282, 291322,
-	292369, 293423, 294485, 295554, 296630, 297714, 298805, 299904,
-	301011, 302126, 303248, 304379, 305517, 306664, 307819, 308983,
-	310154, 311335, 312524, 313721, 314928, 316143, 317368, 318601,
-	319844, 321097, 322358, 323629, 324910, 326201, 327502, 328812,
-	330133, 331464, 332805, 334157, 335519, 336892, 338276, 339671,
-	341078, 342495, 343924, 345364, 346816, 348280, 349756, 351244,
-	352744, 354257, 355783, 357321, 358872, 360436, 362013, 363604,
-	365208, 366826, 368459, 370105, 371765, 373440, 375130, 376835,
-	378555, 380290, 382040, 383807, 385589, 387387, 389202, 391034,
-	392882, 394747, 396630, 398530, 400448, 402384, 404338, 406311,
-	408303, 410314, 412344, 414395, 416465, 418555, 420666, 422798,
-	424951, 427125, 429321, 431540, 433781, 436045, 438332, 440643,
-	442978, 445337, 447720, 450129, 452564, 455024, 457511, 460024,
-	462565, 465133, 467730, 470355, 473009, 475692, 478406, 481150,
-	483925, 486732, 489571, 492443, 495348, 498287, 501261, 504269,
-	507313, 510394, 513512, 516667, 519861, 523094, 526366, 529680,
-	533034, 536431, 539870, 543354, 546881, 550455, 554074, 557741,
-	561456, 565221, 569035, 572901, 576818, 580789, 584815, 588896,
-	593033, 597229, 601483, 605798, 610174, 614613, 619117, 623686,
-	628323, 633028, 637803, 642651, 647572, 652568, 657640, 662792,
-	668024, 673338, 678737, 684223, 689797, 695462, 701219, 707072,
-	713023, 719074, 725227, 731486, 737853, 744331, 750922, 757631,
-	764460, 771411, 778490, 785699, 793041, 800521, 808143, 815910,
-	823827, 831898, 840127, 848520, 857081, 865817, 874730, 883829,
-	893117, 902602, 912289, 922186, 932298, 942633, 953199, 964003,
-	975054, 986361, 997931, 1009774, 1021901, 1034322, 1047046, 1060087,
-	1073455, 1087164, 1101225, 1115654, 1130465, 1145673, 1161294, 1177345,
-	1193846, 1210813, 1228269, 1246234, 1264730, 1283783, 1303416, 1323658,
-	1344537, 1366084, 1388330, 1411312, 1435065, 1459630, 1485049, 1511367,
-	1538632, 1566898, 1596220, 1626658, 1658278, 1691149, 1725348, 1760956,
-	1798063, 1836758, 1877161, 1919378, 1963536, 2009771, 2058233, 2109087,
-	2162516, 2218719, 2277919, 2340362, 2406322, 2476104, 2550052, 2628549,
-	2712030, 2800983, 2895966, 2997613, 3106651, 3223918, 3350381, 3487165,
-	3635590, 3797206, 3973855, 4167737, 4381502, 4618375, 4882318, 5178251,
-	5512368, 5892567, 6329090, 6835455, 7429880, 8137527, 8994149, 10052327,
-	11392683, 13145455, 15535599, 18988036, 24413316, 34178904, 56965752, 170910304
+	INT32_MIN, -85445642, -42722796, -28481836, -21361347, -17089048, -14240842, -12206405,
+	-10680573, -9493811, -8544398, -7767602, -7120270, -6572525, -6103026, -5696125,
+	-5340085, -5025930, -4746679, -4496821, -4271947, -4068489, -3883524, -3714643,
+	-3559833, -3417407, -3285935, -3164201, -3051161, -2945916, -2847685, -2755792,
+	-2669640, -2588709, -2512537, -2440718, -2372887, -2308722, -2247933, -2190260,
+	-2135471, -2083353, -2033716, -1986387, -1941209, -1898038, -1856743, -1817205,
+	-1779313, -1742967, -1708075, -1674550, -1642314, -1611294, -1581422, -1552635,
+	-1524876, -1498091, -1472229, -1447242, -1423088, -1399726, -1377116, -1355224,
+	-1334015, -1313459, -1293525, -1274185, -1255414, -1237186, -1219479, -1202270,
+	-1185538, -1169265, -1153430, -1138018, -1123011, -1108393, -1094149, -1080266,
+	-1066729, -1053527, -1040645, -1028074, -1015802, -1003818, -992112, -980675,
+	-969498, -958571, -947887, -937438, -927215, -917211, -907420, -897835,
+	-888449, -879257, -870251, -861428, -852780, -844303, -835992, -827843,
+	-819849, -812008, -804314, -796763, -789353, -782077, -774934, -767919,
+	-761030, -754261, -747612, -741077, -734655, -728343, -722137, -716035,
+	-710035, -704133, -698328, -692618, -686999, -681469, -676027, -670671,
+	-665398, -660206, -655094, -650060, -645102, -640218, -635407, -630667,
+	-625996, -621393, -616857, -612386, -607978, -603633, -599348, -595124,
+	-590957, -586848, -582795, -578797, -574853, -570962, -567122, -563332,
+	-559593, -555902, -552259, -548662, -545112, -541606, -538145, -534727,
+	-531351, -528018, -524725, -521472, -518259, -515084, -511948, -508849,
+	-505787, -502760, -499769, -496813, -493891, -491003, -488148, -485325,
+	-482534, -479774, -477045, -474347, -471678, -469038, -466428, -463845,
+	-461291, -458764, -456264, -453791, -451343, -448922, -446526, -444154,
+	-441807, -439485, -437186, -434910, -432658, -430428, -428221, -426035,
+	-423871, -421729, -419608, -417507, -415427, -413367, -411327, -409306,
+	-407305, -405323, -403359, -401414, -399487, -397578, -395686, -393812,
+	-391956, -390116, -388293, -386486, -384696, -382921, -381163, -379420,
+	-377693, -375981, -374283, -372601, -370933, -369280, -367641, -366016,
+	-364404, -362807, -361223, -359652, -358094, -356550, -355018, -353499,
+	-351993, -350499, -349017, -347547, -346089, -344643, -343208, -341785,
+	-340373, -338973, -337583, -336204, -334837, -333480, -332133, -330797,
+	-329471, -328156, -326850, -325554, -324269, -322993, -321726, -320469,
+	-319222, -317984, -316754, -315535, -314324, -313121, -311928, -310743,
+	-309567, -308400, -307240, -306090, -304947, -303812, -302686, -301567,
+	-300457, -299354, -298259, -297171, -296091, -295018, -293953, -292895,
+	-291845, -290801, -289765, -288735, -287713, -286697, -285688, -284686,
+	-283691, -282702, -281719, -280743, -279774, -278811, -277854, -276903,
+	-275959, -275020, -274088, -273161, -272241, -271326, -270417, -269514,
+	-268616, -267724, -266838, -265957, -265082, -264212, -263347, -262488,
+	-261634, -260785, -259941, -259103, -258270, -257441, -256618, -255799,
+	-254986, -254177, -253373, -252574, -251779, -250989, -250204, -249423,
+	-248647, -247876, -247109, -246346, -245588, -244834, -244084, -243338,
+	-242597, -241860, -241128, -240399, -239674, -238954, -238237, -237525,
+	-236816, -236112, -235411, -234714, -234021, -233331, -232646, -231964,
+	-231286, -230611, -229940, -229273, -228610, -227949, -227293, -226640,
+	-225990, -225344, -224701, -224061, -223425, -222792, -222163, -221536,
+	-220913, -220294, -219677, -219064, -218453, -217846, -217242, -216641,
+	-216043, -215448, -214856, -214267, -213681, -213097, -212517, -211940,
+	-211365, -210793, -210225, -209658, -209095, -208535, -207977, -207422,
+	-206869, -206319, -205772, -205228, -204686, -204147, -203610, -203076,
+	-202544, -202015, -201488, -200964, -200442, -199923, -199406, -198892,
+	-198380, -197870, -197363, -196858, -196355, -195855, -195357, -194861,
+	-194367, -193876, -193387, -192900, -192416, -191933, -191453, -190975,
+	-190499, -190025, -189553, -189083, -188615, -188150, -187686, -187225,
+	-186765, -186308, -185852, -185399, -184947, -184498, -184050, -183604,
+	-183160, -182718, -182278, -181840, -181404, -180969, -180537, -180106,
+	-179677, -179250, -178824, -178401, -177979, -177559, -177140, -176724,
+	-176309, -175896, -175484, -175074, -174666, -174260, -173855, -173452,
+	-173050, -172650, -172252, -171855, -171460, -171066, -170674, -170284,
+	-169895, -169508, -169122, -168738, -168355, -167974, -167594, -167216,
+	-166839, -166464, -166090, -165718, -165347, -164977, -164609, -164242,
+	-163877, -163513, -163151, -162790, -162430, -162072, -161715, -161359,
+	-161005, -160652, -160300, -159950, -159601, -159253, -158906, -158561,
+	-158217, -157875, -157533, -157193, -156855, -156517, -156181, -155845,
+	-155512, -155179, -154847, -154517, -154188, -153860, -153533, -153208,
+	-152883, -152560, -152238, -151917, -151597, -151279, -150961, -150645,
+	-150329, -150015, -149702, -149390, -149079, -148769, -148461, -148153,
+	-147846, -147541, -147236, -146933, -146630, -146329, -146029, -145729,
+	-145431, -145134, -144837, -144542, -144248, -143955, -143662, -143371,
+	-143081, -142791, -142503, -142215, -141929, -141643, -141359, -141075,
+	-140792, -140511, -140230, -139950, -139671, -139393, -139115, -138839,
+	-138564, -138289, -138016, -137743, -137471, -137200, -136930, -136661,
+	-136392, -136125, -135858, -135592, -135327, -135063, -134799, -134537,
+	-134275, -134014, -133754, -133495, -133237, -132979, -132722, -132466,
+	-132211, -131957, -131703, -131450, -131198, -130947, -130696, -130446,
+	-130197, -129949, -129701, -129455, -129209, -128963, -128719, -128475,
+	-128232, -127990, -127748, -127507, -127267, -127027, -126789, -126551,
+	-126313, -126077, -125841, -125605, -125371, -125137, -124904, -124671,
+	-124439, -124208, -123978, -123748, -123519, -123290, -123062, -122835,
+	-122609, -122383, -122158, -121933, -121709, -121486, -121263, -121041,
+	-120820, -120599, -120379, -120159, -119940, -119722, -119504, -119287,
+	-119071, -118855, -118639, -118425, -118211, -117997, -117784, -117572,
+	-117360, -117149, -116938, -116728, -116519, -116310, -116102, -115894,
+	-115687, -115480, -115274, -115069, -114864, -114659, -114455, -114252,
+	-114049, -113847, -113645, -113444, -113244, -113043, -112844, -112645,
+	-112446, -112248, -112051, -111854, -111658, -111462, -111266, -111071,
+	-110877, -110683, -110490, -110297, -110104, -109912, -109721, -109530,
+	-109340, -109150, -108960, -108771, -108583, -108395, -108207, -108020,
+	-107834, -107648, -107462, -107277, -107092, -106908, -106724, -106541,
+	-106358, -106175, -105993, -105812, -105631, -105450, -105270, -105090,
+	-104911, -104732, -104554, -104376, -104198, -104021, -103844, -103668,
+	-103492, -103317, -103142, -102967, -102793, -102619, -102446, -102273,
+	-102101, -101929, -101757, -101586, -101415, -101244, -101074, -100905,
+	-100736, -100567, -100398, -100230, -100063, -99895, -99729, -99562,
+	-99396, -99230, -99065, -98900, -98735, -98571, -98408, -98244,
+	-98081, -97918, -97756, -97594, -97433, -97271, -97111, -96950,
+	-96790, -96630, -96471, -96312, -96153, -95995, -95837, -95680,
+	-95522, -95365, -95209, -95053, -94897, -94741, -94586, -94431,
+	-94277, -94123, -93969, -93816, -93663, -93510, -93357, -93205,
+	-93053, -92902, -92751, -92600, -92450, -92300, -92150, -92000,
+	-91851, -91702, -91554, -91406, -91258, -91110, -90963, -90816,
+	-90669, -90523, -90377, -90231, -90086, -89941, -89796, -89651,
+	-89507, -89363, -89220, -89077, -88934, -88791, -88648, -88506,
+	-88365, -88223, -88082, -87941, -87800, -87660, -87520, -87380,
+	-87241, -87101, -86963, -86824, -86686, -86547, -86410, -86272,
+	-86135, -85998, -85861, -85725, -85589, -85453, -85317, -85182,
+	-85047, -84912, -84778, -84643, -84509, -84376, -84242, -84109,
+	-83976, -83843, -83711, -83579, -83447, -83315, -83184, -83053,
+	-82922, -82791, -82661, -82531, -82401, -82271, -82142, -82013,
+	-81884, -81756, -81627, -81499, -81371, -81244, -81116, -80989,
+	-80862, -80735, -80609, -80483, -80357, -80231, -80106, -79980,
+	-79855, -79731, -79606, -79482, -79358, -79234, -79110, -78987,
+	-78864, -78741, -78618, -78495, -78373, -78251, -78129, -78008,
+	-77886, -77765, -77644, -77524, -77403, -77283, -77163, -77043,
+	-76923, -76804, -76685, -76566, -76447, -76328, -76210, -76092,
+	-75974, -75856, -75739, -75621, -75504, -75387, -75271, -75154,
+	-75038, -74922, -74806, -74690, -74575, -74460, -74345, -74230,
+	-74115, -74001, -73886, -73772, -73659, -73545, -73431, -73318,
+	-73205, -73092, -72979, -72867, -72755, -72643, -72531, -72419,
+	-72307, -72196, -72085, -71974, -71863, -71752, -71642, -71532,
+	-71422, -71312, -71202, -71093, -70983, -70874, -70765, -70656,
+	-70548, -70439, -70331, -70223, -70115, -70007, -69900, -69793,
+	-69685, -69578, -69472, -69365, -69258, -69152, -69046, -68940,
+	-68834, -68728, -68623, -68518, -68413, -68308, -68203, -68098,
+	-67994, -67889, -67785, -67681, -67578, -67474, -67371, -67267,
+	-67164, -67061, -66958, -66856, -66753, -66651, -66549, -66447,
+	-66345, -66243, -66141, -66040, -65939, -65838, -65737, -65636,
+	-65536, -65435, -65335, -65235, -65135, -65035, -64935, -64836,
+	-64736, -64637, -64538, -64439, -64340, -64241, -64143, -64045,
+	-63946, -63848, -63750, -63653, -63555, -63458, -63360, -63263,
+	-63166, -63069, -62972, -62876, -62779, -62683, -62587, -62491,
+	-62395, -62299, -62204, -62108, -62013, -61918, -61822, -61728,
+	-61633, -61538, -61444, -61349, -61255, -61161, -61067, -60973,
+	-60879, -60786, -60692, -60599, -60506, -60413, -60320, -60227,
+	-60134, -60042, -59950, -59857, -59765, -59673, -59581, -59489,
+	-59398, -59306, -59215, -59124, -59033, -58942, -58851, -58760,
+	-58669, -58579, -58489, -58398, -58308, -58218, -58128, -58039,
+	-57949, -57859, -57770, -57681, -57592, -57503, -57414, -57325,
+	-57236, -57148, -57059, -56971, -56883, -56795, -56707, -56619,
+	-56531, -56444, -56356, -56269, -56181, -56094, -56007, -55920,
+	-55834, -55747, -55660, -55574, -55487, -55401, -55315, -55229,
+	-55143, -55057, -54972, -54886, -54801, -54715, -54630, -54545,
+	-54460, -54375, -54290, -54205, -54121, -54036, -53952, -53868,
+	-53784, -53699, -53615, -53532, -53448, -53364, -53281, -53197,
+	-53114, -53031, -52948, -52865, -52782, -52699, -52616, -52533,
+	-52451, -52369, -52286, -52204, -52122, -52040, -51958, -51876,
+	-51794, -51713, -51631, -51550, -51469, -51387, -51306, -51225,
+	-51144, -51063, -50983, -50902, -50822, -50741, -50661, -50581,
+	-50500, -50420, -50340, -50260, -50181, -50101, -50021, -49942,
+	-49862, -49783, -49704, -49625, -49546, -49467, -49388, -49309,
+	-49230, -49152, -49073, -48995, -48917, -48838, -48760, -48682,
+	-48604, -48526, -48449, -48371, -48293, -48216, -48138, -48061,
+	-47984, -47907, -47830, -47753, -47676, -47599, -47522, -47445,
+	-47369, -47292, -47216, -47140, -47063, -46987, -46911, -46835,
+	-46759, -46684, -46608, -46532, -46457, -46381, -46306, -46230,
+	-46155, -46080, -46005, -45930, -45855, -45780, -45705, -45631,
+	-45556, -45482, -45407, -45333, -45259, -45184, -45110, -45036,
+	-44962, -44888, -44815, -44741, -44667, -44594, -44520, -44447,
+	-44373, -44300, -44227, -44154, -44081, -44008, -43935, -43862,
+	-43789, -43717, -43644, -43571, -43499, -43427, -43354, -43282,
+	-43210, -43138, -43066, -42994, -42922, -42850, -42779, -42707,
+	-42635, -42564, -42492, -42421, -42350, -42279, -42207, -42136,
+	-42065, -41994, -41923, -41853, -41782, -41711, -41641, -41570,
+	-41500, -41429, -41359, -41289, -41219, -41148, -41078, -41008,
+	-40939, -40869, -40799, -40729, -40660, -40590, -40520, -40451,
+	-40382, -40312, -40243, -40174, -40105, -40036, -39967, -39898,
+	-39829, -39760, -39691, -39623, -39554, -39486, -39417, -39349,
+	-39280, -39212, -39144, -39076, -39007, -38939, -38871, -38804,
+	-38736, -38668, -38600, -38532, -38465, -38397, -38330, -38262,
+	-38195, -38128, -38060, -37993, -37926, -37859, -37792, -37725,
+	-37658, -37591, -37525, -37458, -37391, -37325, -37258, -37192,
+	-37125, -37059, -36993, -36926, -36860, -36794, -36728, -36662,
+	-36596, -36530, -36464, -36398, -36333, -36267, -36201, -36136,
+	-36070, -36005, -35939, -35874, -35809, -35743, -35678, -35613,
+	-35548, -35483, -35418, -35353, -35288, -35223, -35159, -35094,
+	-35029, -34965, -34900, -34836, -34771, -34707, -34642, -34578,
+	-34514, -34450, -34386, -34322, -34257, -34194, -34130, -34066,
+	-34002, -33938, -33874, -33811, -33747, -33684, -33620, -33557,
+	-33493, -33430, -33366, -33303, -33240, -33177, -33114, -33051,
+	-32988, -32925, -32862, -32799, -32736, -32673, -32610, -32548,
+	-32485, -32422, -32360, -32297, -32235, -32173, -32110, -32048,
+	-31986, -31923, -31861, -31799, -31737, -31675, -31613, -31551,
+	-31489, -31427, -31366, -31304, -31242, -31180, -31119, -31057,
+	-30996, -30934, -30873, -30811, -30750, -30689, -30627, -30566,
+	-30505, -30444, -30383, -30322, -30261, -30200, -30139, -30078,
+	-30017, -29956, -29896, -29835, -29774, -29714, -29653, -29593,
+	-29532, -29472, -29411, -29351, -29291, -29230, -29170, -29110,
+	-29050, -28989, -28929, -28869, -28809, -28749, -28689, -28630,
+	-28570, -28510, -28450, -28390, -28331, -28271, -28212, -28152,
+	-28092, -28033, -27974, -27914, -27855, -27795, -27736, -27677,
+	-27618, -27559, -27499, -27440, -27381, -27322, -27263, -27204,
+	-27145, -27087, -27028, -26969, -26910, -26851, -26793, -26734,
+	-26675, -26617, -26558, -26500, -26441, -26383, -26325, -26266,
+	-26208, -26150, -26091, -26033, -25975, -25917, -25859, -25801,
+	-25743, -25685, -25627, -25569, -25511, -25453, -25395, -25337,
+	-25280, -25222, -25164, -25106, -25049, -24991, -24934, -24876,
+	-24819, -24761, -24704, -24646, -24589, -24532, -24474, -24417,
+	-24360, -24303, -24246, -24188, -24131, -24074, -24017, -23960,
+	-23903, -23846, -23789, -23733, -23676, -23619, -23562, -23505,
+	-23449, -23392, -23335, -23279, -23222, -23166, -23109, -23053,
+	-22996, -22940, -22883, -22827, -22770, -22714, -22658, -22602,
+	-22545, -22489, -22433, -22377, -22321, -22265, -22209, -22153,
+	-22097, -22041, -21985, -21929, -21873, -21817, -21761, -21705,
+	-21650, -21594, -21538, -21483, -21427, -21371, -21316, -21260,
+	-21205, -21149, -21094, -21038, -20983, -20927, -20872, -20817,
+	-20761, -20706, -20651, -20595, -20540, -20485, -20430, -20375,
+	-20320, -20264, -20209, -20154, -20099, -20044, -19989, -19935,
+	-19880, -19825, -19770, -19715, -19660, -19605, -19551, -19496,
+	-19441, -19387, -19332, -19277, -19223, -19168, -19114, -19059,
+	-19005, -18950, -18896, -18841, -18787, -18732, -18678, -18624,
+	-18569, -18515, -18461, -18407, -18352, -18298, -18244, -18190,
+	-18136, -18082, -18028, -17974, -17919, -17865, -17811, -17758,
+	-17704, -17650, -17596, -17542, -17488, -17434, -17380, -17327,
+	-17273, -17219, -17165, -17112, -17058, -17004, -16951, -16897,
+	-16843, -16790, -16736, -16683, -16629, -16576, -16522, -16469,
+	-16415, -16362, -16309, -16255, -16202, -16149, -16095, -16042,
+	-15989, -15935, -15882, -15829, -15776, -15723, -15670, -15616,
+	-15563, -15510, -15457, -15404, -15351, -15298, -15245, -15192,
+	-15139, -15086, -15033, -14980, -14927, -14875, -14822, -14769,
+	-14716, -14663, -14611, -14558, -14505, -14452, -14400, -14347,
+	-14294, -14242, -14189, -14136, -14084, -14031, -13979, -13926,
+	-13874, -13821, -13769, -13716, -13664, -13611, -13559, -13506,
+	-13454, -13402, -13349, -13297, -13245, -13192, -13140, -13088,
+	-13035, -12983, -12931, -12879, -12827, -12774, -12722, -12670,
+	-12618, -12566, -12514, -12462, -12409, -12357, -12305, -12253,
+	-12201, -12149, -12097, -12045, -11993, -11941, -11890, -11838,
+	-11786, -11734, -11682, -11630, -11578, -11526, -11475, -11423,
+	-11371, -11319, -11268, -11216, -11164, -11112, -11061, -11009,
+	-10957, -10906, -10854, -10802, -10751, -10699, -10647, -10596,
+	-10544, -10493, -10441, -10390, -10338, -10287, -10235, -10184,
+	-10132, -10081, -10029, -9978, -9926, -9875, -9824, -9772,
+	-9721, -9669, -9618, -9567, -9515, -9464, -9413, -9362,
+	-9310, -9259, -9208, -9156, -9105, -9054, -9003, -8952,
+	-8900, -8849, -8798, -8747, -8696, -8645, -8593, -8542,
+	-8491, -8440, -8389, -8338, -8287, -8236, -8185, -8134,
+	-8083, -8032, -7981, -7930, -7879, -7828, -7777, -7726,
+	-7675, -7624, -7573, -7522, -7471, -7420, -7369, -7318,
+	-7267, -7216, -7166, -7115, -7064, -7013, -6962, -6911,
+	-6861, -6810, -6759, -6708, -6657, -6607, -6556, -6505,
+	-6454, -6403, -6353, -6302, -6251, -6201, -6150, -6099,
+	-6048, -5998, -5947, -5896, -5846, -5795, -5744, -5694,
+	-5643, -5592, -5542, -5491, -5441, -5390, -5339, -5289,
+	-5238, -5188, -5137, -5086, -5036, -4985, -4935, -4884,
+	-4834, -4783, -4733, -4682, -4632, -4581, -4531, -4480,
+	-4430, -4379, -4329, -4278, -4228, -4177, -4127, -4076,
+	-4026, -3975, -3925, -3874, -3824, -3774, -3723, -3673,
+	-3622, -3572, -3521, -3471, -3421, -3370, -3320, -3269,
+	-3219, -3169, -3118, -3068, -3018, -2967, -2917, -2866,
+	-2816, -2766, -2715, -2665, -2615, -2564, -2514, -2464,
+	-2413, -2363, -2313, -2262, -2212, -2162, -2111, -2061,
+	-2011, -1960, -1910, -1860, -1810, -1759, -1709, -1659,
+	-1608, -1558, -1508, -1457, -1407, -1357, -1307, -1256,
+	-1206, -1156, -1105, -1055, -1005, -955, -904, -854,
+	-804, -754, -703, -653, -603, -552, -502, -452,
+	-402, -351, -301, -251, -201, -150, -100, -50,
+	0, 50, 100, 150, 201, 251, 301, 351,
+	402, 452, 502, 552, 603, 653, 703, 754,
+	804, 854, 904, 955, 1005, 1055, 1105, 1156,
+	1206, 1256, 1307, 1357, 1407, 1457, 1508, 1558,
+	1608, 1659, 1709, 1759, 1810, 1860, 1910, 1960,
+	2011, 2061, 2111, 2162, 2212, 2262, 2313, 2363,
+	2413, 2464, 2514, 2564, 2615, 2665, 2715, 2766,
+	2816, 2866, 2917, 2967, 3018, 3068, 3118, 3169,
+	3219, 3269, 3320, 3370, 3421, 3471, 3521, 3572,
+	3622, 3673, 3723, 3774, 3824, 3874, 3925, 3975,
+	4026, 4076, 4127, 4177, 4228, 4278, 4329, 4379,
+	4430, 4480, 4531, 4581, 4632, 4682, 4733, 4783,
+	4834, 4884, 4935, 4985, 5036, 5086, 5137, 5188,
+	5238, 5289, 5339, 5390, 5441, 5491, 5542, 5592,
+	5643, 5694, 5744, 5795, 5846, 5896, 5947, 5998,
+	6048, 6099, 6150, 6201, 6251, 6302, 6353, 6403,
+	6454, 6505, 6556, 6607, 6657, 6708, 6759, 6810,
+	6861, 6911, 6962, 7013, 7064, 7115, 7166, 7216,
+	7267, 7318, 7369, 7420, 7471, 7522, 7573, 7624,
+	7675, 7726, 7777, 7828, 7879, 7930, 7981, 8032,
+	8083, 8134, 8185, 8236, 8287, 8338, 8389, 8440,
+	8491, 8542, 8593, 8645, 8696, 8747, 8798, 8849,
+	8900, 8952, 9003, 9054, 9105, 9156, 9208, 9259,
+	9310, 9362, 9413, 9464, 9515, 9567, 9618, 9669,
+	9721, 9772, 9824, 9875, 9926, 9978, 10029, 10081,
+	10132, 10184, 10235, 10287, 10338, 10390, 10441, 10493,
+	10544, 10596, 10647, 10699, 10751, 10802, 10854, 10906,
+	10957, 11009, 11061, 11112, 11164, 11216, 11268, 11319,
+	11371, 11423, 11475, 11526, 11578, 11630, 11682, 11734,
+	11786, 11838, 11890, 11941, 11993, 12045, 12097, 12149,
+	12201, 12253, 12305, 12357, 12409, 12462, 12514, 12566,
+	12618, 12670, 12722, 12774, 12827, 12879, 12931, 12983,
+	13035, 13088, 13140, 13192, 13245, 13297, 13349, 13402,
+	13454, 13506, 13559, 13611, 13664, 13716, 13769, 13821,
+	13874, 13926, 13979, 14031, 14084, 14136, 14189, 14242,
+	14294, 14347, 14400, 14452, 14505, 14558, 14611, 14663,
+	14716, 14769, 14822, 14875, 14927, 14980, 15033, 15086,
+	15139, 15192, 15245, 15298, 15351, 15404, 15457, 15510,
+	15563, 15616, 15670, 15723, 15776, 15829, 15882, 15935,
+	15989, 16042, 16095, 16149, 16202, 16255, 16309, 16362,
+	16415, 16469, 16522, 16576, 16629, 16683, 16736, 16790,
+	16843, 16897, 16951, 17004, 17058, 17112, 17165, 17219,
+	17273, 17327, 17380, 17434, 17488, 17542, 17596, 17650,
+	17704, 17758, 17811, 17865, 17919, 17974, 18028, 18082,
+	18136, 18190, 18244, 18298, 18352, 18407, 18461, 18515,
+	18569, 18624, 18678, 18732, 18787, 18841, 18896, 18950,
+	19005, 19059, 19114, 19168, 19223, 19277, 19332, 19387,
+	19441, 19496, 19551, 19605, 19660, 19715, 19770, 19825,
+	19880, 19935, 19989, 20044, 20099, 20154, 20209, 20264,
+	20320, 20375, 20430, 20485, 20540, 20595, 20651, 20706,
+	20761, 20817, 20872, 20927, 20983, 21038, 21094, 21149,
+	21205, 21260, 21316, 21371, 21427, 21483, 21538, 21594,
+	21650, 21705, 21761, 21817, 21873, 21929, 21985, 22041,
+	22097, 22153, 22209, 22265, 22321, 22377, 22433, 22489,
+	22545, 22602, 22658, 22714, 22770, 22827, 22883, 22940,
+	22996, 23053, 23109, 23166, 23222, 23279, 23335, 23392,
+	23449, 23505, 23562, 23619, 23676, 23733, 23789, 23846,
+	23903, 23960, 24017, 24074, 24131, 24188, 24246, 24303,
+	24360, 24417, 24474, 24532, 24589, 24646, 24704, 24761,
+	24819, 24876, 24934, 24991, 25049, 25106, 25164, 25222,
+	25280, 25337, 25395, 25453, 25511, 25569, 25627, 25685,
+	25743, 25801, 25859, 25917, 25975, 26033, 26091, 26150,
+	26208, 26266, 26325, 26383, 26441, 26500, 26558, 26617,
+	26675, 26734, 26793, 26851, 26910, 26969, 27028, 27087,
+	27145, 27204, 27263, 27322, 27381, 27440, 27499, 27559,
+	27618, 27677, 27736, 27795, 27855, 27914, 27974, 28033,
+	28092, 28152, 28212, 28271, 28331, 28390, 28450, 28510,
+	28570, 28630, 28689, 28749, 28809, 28869, 28929, 28989,
+	29050, 29110, 29170, 29230, 29291, 29351, 29411, 29472,
+	29532, 29593, 29653, 29714, 29774, 29835, 29896, 29956,
+	30017, 30078, 30139, 30200, 30261, 30322, 30383, 30444,
+	30505, 30566, 30627, 30689, 30750, 30811, 30873, 30934,
+	30996, 31057, 31119, 31180, 31242, 31304, 31366, 31427,
+	31489, 31551, 31613, 31675, 31737, 31799, 31861, 31923,
+	31986, 32048, 32110, 32173, 32235, 32297, 32360, 32422,
+	32485, 32548, 32610, 32673, 32736, 32799, 32862, 32925,
+	32988, 33051, 33114, 33177, 33240, 33303, 33366, 33430,
+	33493, 33557, 33620, 33684, 33747, 33811, 33874, 33938,
+	34002, 34066, 34130, 34194, 34257, 34322, 34386, 34450,
+	34514, 34578, 34642, 34707, 34771, 34836, 34900, 34965,
+	35029, 35094, 35159, 35223, 35288, 35353, 35418, 35483,
+	35548, 35613, 35678, 35743, 35809, 35874, 35939, 36005,
+	36070, 36136, 36201, 36267, 36333, 36398, 36464, 36530,
+	36596, 36662, 36728, 36794, 36860, 36926, 36993, 37059,
+	37125, 37192, 37258, 37325, 37391, 37458, 37525, 37591,
+	37658, 37725, 37792, 37859, 37926, 37993, 38060, 38128,
+	38195, 38262, 38330, 38397, 38465, 38532, 38600, 38668,
+	38736, 38804, 38871, 38939, 39007, 39076, 39144, 39212,
+	39280, 39349, 39417, 39486, 39554, 39623, 39691, 39760,
+	39829, 39898, 39967, 40036, 40105, 40174, 40243, 40312,
+	40382, 40451, 40520, 40590, 40660, 40729, 40799, 40869,
+	40939, 41008, 41078, 41148, 41219, 41289, 41359, 41429,
+	41500, 41570, 41641, 41711, 41782, 41853, 41923, 41994,
+	42065, 42136, 42207, 42279, 42350, 42421, 42492, 42564,
+	42635, 42707, 42779, 42850, 42922, 42994, 43066, 43138,
+	43210, 43282, 43354, 43427, 43499, 43571, 43644, 43717,
+	43789, 43862, 43935, 44008, 44081, 44154, 44227, 44300,
+	44373, 44447, 44520, 44594, 44667, 44741, 44815, 44888,
+	44962, 45036, 45110, 45184, 45259, 45333, 45407, 45482,
+	45556, 45631, 45705, 45780, 45855, 45930, 46005, 46080,
+	46155, 46230, 46306, 46381, 46457, 46532, 46608, 46684,
+	46759, 46835, 46911, 46987, 47063, 47140, 47216, 47292,
+	47369, 47445, 47522, 47599, 47676, 47753, 47830, 47907,
+	47984, 48061, 48138, 48216, 48293, 48371, 48449, 48526,
+	48604, 48682, 48760, 48838, 48917, 48995, 49073, 49152,
+	49230, 49309, 49388, 49467, 49546, 49625, 49704, 49783,
+	49862, 49942, 50021, 50101, 50181, 50260, 50340, 50420,
+	50500, 50581, 50661, 50741, 50822, 50902, 50983, 51063,
+	51144, 51225, 51306, 51387, 51469, 51550, 51631, 51713,
+	51794, 51876, 51958, 52040, 52122, 52204, 52286, 52369,
+	52451, 52533, 52616, 52699, 52782, 52865, 52948, 53031,
+	53114, 53197, 53281, 53364, 53448, 53532, 53615, 53699,
+	53784, 53868, 53952, 54036, 54121, 54205, 54290, 54375,
+	54460, 54545, 54630, 54715, 54801, 54886, 54972, 55057,
+	55143, 55229, 55315, 55401, 55487, 55574, 55660, 55747,
+	55834, 55920, 56007, 56094, 56181, 56269, 56356, 56444,
+	56531, 56619, 56707, 56795, 56883, 56971, 57059, 57148,
+	57236, 57325, 57414, 57503, 57592, 57681, 57770, 57859,
+	57949, 58039, 58128, 58218, 58308, 58398, 58489, 58579,
+	58669, 58760, 58851, 58942, 59033, 59124, 59215, 59306,
+	59398, 59489, 59581, 59673, 59765, 59857, 59950, 60042,
+	60134, 60227, 60320, 60413, 60506, 60599, 60692, 60786,
+	60879, 60973, 61067, 61161, 61255, 61349, 61444, 61538,
+	61633, 61728, 61822, 61918, 62013, 62108, 62204, 62299,
+	62395, 62491, 62587, 62683, 62779, 62876, 62972, 63069,
+	63166, 63263, 63360, 63458, 63555, 63653, 63750, 63848,
+	63946, 64045, 64143, 64241, 64340, 64439, 64538, 64637,
+	64736, 64836, 64935, 65035, 65135, 65235, 65335, 65435,
+	65536, 65636, 65737, 65838, 65939, 66040, 66141, 66243,
+	66345, 66447, 66549, 66651, 66753, 66856, 66958, 67061,
+	67164, 67267, 67371, 67474, 67578, 67681, 67785, 67889,
+	67994, 68098, 68203, 68308, 68413, 68518, 68623, 68728,
+	68834, 68940, 69046, 69152, 69258, 69365, 69472, 69578,
+	69685, 69793, 69900, 70007, 70115, 70223, 70331, 70439,
+	70548, 70656, 70765, 70874, 70983, 71093, 71202, 71312,
+	71422, 71532, 71642, 71752, 71863, 71974, 72085, 72196,
+	72307, 72419, 72531, 72643, 72755, 72867, 72979, 73092,
+	73205, 73318, 73431, 73545, 73659, 73772, 73886, 74001,
+	74115, 74230, 74345, 74460, 74575, 74690, 74806, 74922,
+	75038, 75154, 75271, 75387, 75504, 75621, 75739, 75856,
+	75974, 76092, 76210, 76328, 76447, 76566, 76685, 76804,
+	76923, 77043, 77163, 77283, 77403, 77524, 77644, 77765,
+	77886, 78008, 78129, 78251, 78373, 78495, 78618, 78741,
+	78864, 78987, 79110, 79234, 79358, 79482, 79606, 79731,
+	79855, 79980, 80106, 80231, 80357, 80483, 80609, 80735,
+	80862, 80989, 81116, 81244, 81371, 81499, 81627, 81756,
+	81884, 82013, 82142, 82271, 82401, 82531, 82661, 82791,
+	82922, 83053, 83184, 83315, 83447, 83579, 83711, 83843,
+	83976, 84109, 84242, 84376, 84509, 84643, 84778, 84912,
+	85047, 85182, 85317, 85453, 85589, 85725, 85861, 85998,
+	86135, 86272, 86410, 86547, 86686, 86824, 86963, 87101,
+	87241, 87380, 87520, 87660, 87800, 87941, 88082, 88223,
+	88365, 88506, 88648, 88791, 88934, 89077, 89220, 89363,
+	89507, 89651, 89796, 89941, 90086, 90231, 90377, 90523,
+	90669, 90816, 90963, 91110, 91258, 91406, 91554, 91702,
+	91851, 92000, 92150, 92300, 92450, 92600, 92751, 92902,
+	93053, 93205, 93357, 93510, 93663, 93816, 93969, 94123,
+	94277, 94431, 94586, 94741, 94897, 95053, 95209, 95365,
+	95522, 95680, 95837, 95995, 96153, 96312, 96471, 96630,
+	96790, 96950, 97111, 97271, 97433, 97594, 97756, 97918,
+	98081, 98244, 98408, 98571, 98735, 98900, 99065, 99230,
+	99396, 99562, 99729, 99895, 100063, 100230, 100398, 100567,
+	100736, 100905, 101074, 101244, 101415, 101586, 101757, 101929,
+	102101, 102273, 102446, 102619, 102793, 102967, 103142, 103317,
+	103492, 103668, 103844, 104021, 104198, 104376, 104554, 104732,
+	104911, 105090, 105270, 105450, 105631, 105812, 105993, 106175,
+	106358, 106541, 106724, 106908, 107092, 107277, 107462, 107648,
+	107834, 108020, 108207, 108395, 108583, 108771, 108960, 109150,
+	109340, 109530, 109721, 109912, 110104, 110297, 110490, 110683,
+	110877, 111071, 111266, 111462, 111658, 111854, 112051, 112248,
+	112446, 112645, 112844, 113043, 113244, 113444, 113645, 113847,
+	114049, 114252, 114455, 114659, 114864, 115069, 115274, 115480,
+	115687, 115894, 116102, 116310, 116519, 116728, 116938, 117149,
+	117360, 117572, 117784, 117997, 118211, 118425, 118639, 118855,
+	119071, 119287, 119504, 119722, 119940, 120159, 120379, 120599,
+	120820, 121041, 121263, 121486, 121709, 121933, 122158, 122383,
+	122609, 122835, 123062, 123290, 123519, 123748, 123978, 124208,
+	124439, 124671, 124904, 125137, 125371, 125605, 125841, 126077,
+	126313, 126551, 126789, 127027, 127267, 127507, 127748, 127990,
+	128232, 128475, 128719, 128963, 129209, 129455, 129701, 129949,
+	130197, 130446, 130696, 130947, 131198, 131450, 131703, 131957,
+	132211, 132466, 132722, 132979, 133237, 133495, 133754, 134014,
+	134275, 134537, 134799, 135063, 135327, 135592, 135858, 136125,
+	136392, 136661, 136930, 137200, 137471, 137743, 138016, 138289,
+	138564, 138839, 139115, 139393, 139671, 139950, 140230, 140511,
+	140792, 141075, 141359, 141643, 141929, 142215, 142503, 142791,
+	143081, 143371, 143662, 143955, 144248, 144542, 144837, 145134,
+	145431, 145729, 146029, 146329, 146630, 146933, 147236, 147541,
+	147846, 148153, 148461, 148769, 149079, 149390, 149702, 150015,
+	150329, 150645, 150961, 151279, 151597, 151917, 152238, 152560,
+	152883, 153208, 153533, 153860, 154188, 154517, 154847, 155179,
+	155512, 155845, 156181, 156517, 156855, 157193, 157533, 157875,
+	158217, 158561, 158906, 159253, 159601, 159950, 160300, 160652,
+	161005, 161359, 161715, 162072, 162430, 162790, 163151, 163513,
+	163877, 164242, 164609, 164977, 165347, 165718, 166090, 166464,
+	166839, 167216, 167594, 167974, 168355, 168738, 169122, 169508,
+	169895, 170284, 170674, 171066, 171460, 171855, 172252, 172650,
+	173050, 173452, 173855, 174260, 174666, 175074, 175484, 175896,
+	176309, 176724, 177140, 177559, 177979, 178401, 178824, 179250,
+	179677, 180106, 180537, 180969, 181404, 181840, 182278, 182718,
+	183160, 183604, 184050, 184498, 184947, 185399, 185852, 186308,
+	186765, 187225, 187686, 188150, 188615, 189083, 189553, 190025,
+	190499, 190975, 191453, 191933, 192416, 192900, 193387, 193876,
+	194367, 194861, 195357, 195855, 196355, 196858, 197363, 197870,
+	198380, 198892, 199406, 199923, 200442, 200964, 201488, 202015,
+	202544, 203076, 203610, 204147, 204686, 205228, 205772, 206319,
+	206869, 207422, 207977, 208535, 209095, 209658, 210225, 210793,
+	211365, 211940, 212517, 213097, 213681, 214267, 214856, 215448,
+	216043, 216641, 217242, 217846, 218453, 219064, 219677, 220294,
+	220913, 221536, 222163, 222792, 223425, 224061, 224701, 225344,
+	225990, 226640, 227293, 227949, 228610, 229273, 229940, 230611,
+	231286, 231964, 232646, 233331, 234021, 234714, 235411, 236112,
+	236816, 237525, 238237, 238954, 239674, 240399, 241128, 241860,
+	242597, 243338, 244084, 244834, 245588, 246346, 247109, 247876,
+	248647, 249423, 250204, 250989, 251779, 252574, 253373, 254177,
+	254986, 255799, 256618, 257441, 258270, 259103, 259941, 260785,
+	261634, 262488, 263347, 264212, 265082, 265957, 266838, 267724,
+	268616, 269514, 270417, 271326, 272241, 273161, 274088, 275020,
+	275959, 276903, 277854, 278811, 279774, 280743, 281719, 282702,
+	283691, 284686, 285688, 286697, 287713, 288735, 289765, 290801,
+	291845, 292895, 293953, 295018, 296091, 297171, 298259, 299354,
+	300457, 301567, 302686, 303812, 304947, 306090, 307240, 308400,
+	309567, 310743, 311928, 313121, 314324, 315535, 316754, 317984,
+	319222, 320469, 321726, 322993, 324269, 325554, 326850, 328156,
+	329471, 330797, 332133, 333480, 334837, 336204, 337583, 338973,
+	340373, 341785, 343208, 344643, 346089, 347547, 349017, 350499,
+	351993, 353499, 355018, 356550, 358094, 359652, 361223, 362807,
+	364404, 366016, 367641, 369280, 370933, 372601, 374283, 375981,
+	377693, 379420, 381163, 382921, 384696, 386486, 388293, 390116,
+	391956, 393812, 395686, 397578, 399487, 401414, 403359, 405323,
+	407305, 409306, 411327, 413367, 415427, 417507, 419608, 421729,
+	423871, 426035, 428221, 430428, 432658, 434910, 437186, 439485,
+	441807, 444154, 446526, 448922, 451343, 453791, 456264, 458764,
+	461291, 463845, 466428, 469038, 471678, 474347, 477045, 479774,
+	482534, 485325, 488148, 491003, 493891, 496813, 499769, 502760,
+	505787, 508849, 511948, 515084, 518259, 521472, 524725, 528018,
+	531351, 534727, 538145, 541606, 545112, 548662, 552259, 555902,
+	559593, 563332, 567122, 570962, 574853, 578797, 582795, 586848,
+	590957, 595124, 599348, 603633, 607978, 612386, 616857, 621393,
+	625996, 630667, 635407, 640218, 645102, 650060, 655094, 660206,
+	665398, 670671, 676027, 681469, 686999, 692618, 698328, 704133,
+	710035, 716035, 722137, 728343, 734655, 741077, 747612, 754261,
+	761030, 767919, 774934, 782077, 789353, 796763, 804314, 812008,
+	819849, 827843, 835992, 844303, 852780, 861428, 870251, 879257,
+	888449, 897835, 907420, 917211, 927215, 937438, 947887, 958571,
+	969498, 980675, 992112, 1003818, 1015802, 1028074, 1040645, 1053527,
+	1066729, 1080266, 1094149, 1108393, 1123011, 1138018, 1153430, 1169265,
+	1185538, 1202270, 1219479, 1237186, 1255414, 1274185, 1293525, 1313459,
+	1334015, 1355224, 1377116, 1399726, 1423088, 1447242, 1472229, 1498091,
+	1524876, 1552635, 1581422, 1611294, 1642314, 1674550, 1708075, 1742967,
+	1779313, 1817205, 1856743, 1898038, 1941209, 1986387, 2033716, 2083353,
+	2135471, 2190260, 2247933, 2308722, 2372887, 2440718, 2512537, 2588709,
+	2669640, 2755792, 2847685, 2945916, 3051161, 3164201, 3285935, 3417407,
+	3559833, 3714643, 3883524, 4068489, 4271947, 4496821, 4746679, 5025930,
+	5340085, 5696125, 6103026, 6572525, 7120270, 7767602, 8544398, 9493811,
+	10680573, 12206405, 14240842, 17089048, 21361347, 28481836, 42722796, 85445642
 };
 
 
 fixed_t finesine[10240] =
 {
-	25, 75, 125, 175, 226, 276, 326, 376,
-	427, 477, 527, 578, 628, 678, 728, 779,
-	829, 879, 929, 980, 1030, 1080, 1130, 1181,
-	1231, 1281, 1331, 1382, 1432, 1482, 1532, 1583,
-	1633, 1683, 1733, 1784, 1834, 1884, 1934, 1985,
-	2035, 2085, 2135, 2186, 2236, 2286, 2336, 2387,
-	2437, 2487, 2537, 2587, 2638, 2688, 2738, 2788,
-	2839, 2889, 2939, 2989, 3039, 3090, 3140, 3190,
-	3240, 3291, 3341, 3391, 3441, 3491, 3541, 3592,
-	3642, 3692, 3742, 3792, 3843, 3893, 3943, 3993,
-	4043, 4093, 4144, 4194, 4244, 4294, 4344, 4394,
-	4445, 4495, 4545, 4595, 4645, 4695, 4745, 4796,
-	4846, 4896, 4946, 4996, 5046, 5096, 5146, 5197,
-	5247, 5297, 5347, 5397, 5447, 5497, 5547, 5597,
-	5647, 5697, 5748, 5798, 5848, 5898, 5948, 5998,
-	6048, 6098, 6148, 6198, 6248, 6298, 6348, 6398,
-	6448, 6498, 6548, 6598, 6648, 6698, 6748, 6798,
-	6848, 6898, 6948, 6998, 7048, 7098, 7148, 7198,
-	7248, 7298, 7348, 7398, 7448, 7498, 7548, 7598,
-	7648, 7697, 7747, 7797, 7847, 7897, 7947, 7997,
-	8047, 8097, 8147, 8196, 8246, 8296, 8346, 8396,
-	8446, 8496, 8545, 8595, 8645, 8695, 8745, 8794,
-	8844, 8894, 8944, 8994, 9043, 9093, 9143, 9193,
-	9243, 9292, 9342, 9392, 9442, 9491, 9541, 9591,
-	9640, 9690, 9740, 9790, 9839, 9889, 9939, 9988,
-	10038, 10088, 10137, 10187, 10237, 10286, 10336, 10386,
-	10435, 10485, 10534, 10584, 10634, 10683, 10733, 10782,
-	10832, 10882, 10931, 10981, 11030, 11080, 11129, 11179,
-	11228, 11278, 11327, 11377, 11426, 11476, 11525, 11575,
-	11624, 11674, 11723, 11773, 11822, 11872, 11921, 11970,
-	12020, 12069, 12119, 12168, 12218, 12267, 12316, 12366,
-	12415, 12464, 12514, 12563, 12612, 12662, 12711, 12760,
-	12810, 12859, 12908, 12957, 13007, 13056, 13105, 13154,
-	13204, 13253, 13302, 13351, 13401, 13450, 13499, 13548,
-	13597, 13647, 13696, 13745, 13794, 13843, 13892, 13941,
-	13990, 14040, 14089, 14138, 14187, 14236, 14285, 14334,
-	14383, 14432, 14481, 14530, 14579, 14628, 14677, 14726,
-	14775, 14824, 14873, 14922, 14971, 15020, 15069, 15118,
-	15167, 15215, 15264, 15313, 15362, 15411, 15460, 15509,
-	15557, 15606, 15655, 15704, 15753, 15802, 15850, 15899,
-	15948, 15997, 16045, 16094, 16143, 16191, 16240, 16289,
-	16338, 16386, 16435, 16484, 16532, 16581, 16629, 16678,
-	16727, 16775, 16824, 16872, 16921, 16970, 17018, 17067,
-	17115, 17164, 17212, 17261, 17309, 17358, 17406, 17455,
-	17503, 17551, 17600, 17648, 17697, 17745, 17793, 17842,
-	17890, 17939, 17987, 18035, 18084, 18132, 18180, 18228,
-	18277, 18325, 18373, 18421, 18470, 18518, 18566, 18614,
-	18663, 18711, 18759, 18807, 18855, 18903, 18951, 19000,
-	19048, 19096, 19144, 19192, 19240, 19288, 19336, 19384,
-	19432, 19480, 19528, 19576, 19624, 19672, 19720, 19768,
-	19816, 19864, 19912, 19959, 20007, 20055, 20103, 20151,
-	20199, 20246, 20294, 20342, 20390, 20438, 20485, 20533,
-	20581, 20629, 20676, 20724, 20772, 20819, 20867, 20915,
-	20962, 21010, 21057, 21105, 21153, 21200, 21248, 21295,
-	21343, 21390, 21438, 21485, 21533, 21580, 21628, 21675,
-	21723, 21770, 21817, 21865, 21912, 21960, 22007, 22054,
-	22102, 22149, 22196, 22243, 22291, 22338, 22385, 22433,
-	22480, 22527, 22574, 22621, 22668, 22716, 22763, 22810,
-	22857, 22904, 22951, 22998, 23045, 23092, 23139, 23186,
-	23233, 23280, 23327, 23374, 23421, 23468, 23515, 23562,
-	23609, 23656, 23703, 23750, 23796, 23843, 23890, 23937,
-	23984, 24030, 24077, 24124, 24171, 24217, 24264, 24311,
-	24357, 24404, 24451, 24497, 24544, 24591, 24637, 24684,
-	24730, 24777, 24823, 24870, 24916, 24963, 25009, 25056,
-	25102, 25149, 25195, 25241, 25288, 25334, 25381, 25427,
-	25473, 25520, 25566, 25612, 25658, 25705, 25751, 25797,
-	25843, 25889, 25936, 25982, 26028, 26074, 26120, 26166,
-	26212, 26258, 26304, 26350, 26396, 26442, 26488, 26534,
-	26580, 26626, 26672, 26718, 26764, 26810, 26856, 26902,
-	26947, 26993, 27039, 27085, 27131, 27176, 27222, 27268,
-	27313, 27359, 27405, 27450, 27496, 27542, 27587, 27633,
-	27678, 27724, 27770, 27815, 27861, 27906, 27952, 27997,
-	28042, 28088, 28133, 28179, 28224, 28269, 28315, 28360,
-	28405, 28451, 28496, 28541, 28586, 28632, 28677, 28722,
-	28767, 28812, 28858, 28903, 28948, 28993, 29038, 29083,
-	29128, 29173, 29218, 29263, 29308, 29353, 29398, 29443,
-	29488, 29533, 29577, 29622, 29667, 29712, 29757, 29801,
-	29846, 29891, 29936, 29980, 30025, 30070, 30114, 30159,
-	30204, 30248, 30293, 30337, 30382, 30426, 30471, 30515,
-	30560, 30604, 30649, 30693, 30738, 30782, 30826, 30871,
-	30915, 30959, 31004, 31048, 31092, 31136, 31181, 31225,
-	31269, 31313, 31357, 31402, 31446, 31490, 31534, 31578,
-	31622, 31666, 31710, 31754, 31798, 31842, 31886, 31930,
-	31974, 32017, 32061, 32105, 32149, 32193, 32236, 32280,
-	32324, 32368, 32411, 32455, 32499, 32542, 32586, 32630,
-	32673, 32717, 32760, 32804, 32847, 32891, 32934, 32978,
-	33021, 33065, 33108, 33151, 33195, 33238, 33281, 33325,
-	33368, 33411, 33454, 33498, 33541, 33584, 33627, 33670,
-	33713, 33756, 33799, 33843, 33886, 33929, 33972, 34015,
-	34057, 34100, 34143, 34186, 34229, 34272, 34315, 34358,
-	34400, 34443, 34486, 34529, 34571, 34614, 34657, 34699,
-	34742, 34785, 34827, 34870, 34912, 34955, 34997, 35040,
-	35082, 35125, 35167, 35210, 35252, 35294, 35337, 35379,
-	35421, 35464, 35506, 35548, 35590, 35633, 35675, 35717,
-	35759, 35801, 35843, 35885, 35927, 35969, 36011, 36053,
-	36095, 36137, 36179, 36221, 36263, 36305, 36347, 36388,
-	36430, 36472, 36514, 36555, 36597, 36639, 36681, 36722,
-	36764, 36805, 36847, 36889, 36930, 36972, 37013, 37055,
-	37096, 37137, 37179, 37220, 37262, 37303, 37344, 37386,
-	37427, 37468, 37509, 37551, 37592, 37633, 37674, 37715,
-	37756, 37797, 37838, 37879, 37920, 37961, 38002, 38043,
-	38084, 38125, 38166, 38207, 38248, 38288, 38329, 38370,
-	38411, 38451, 38492, 38533, 38573, 38614, 38655, 38695,
-	38736, 38776, 38817, 38857, 38898, 38938, 38979, 39019,
-	39059, 39100, 39140, 39180, 39221, 39261, 39301, 39341,
-	39382, 39422, 39462, 39502, 39542, 39582, 39622, 39662,
-	39702, 39742, 39782, 39822, 39862, 39902, 39942, 39982,
-	40021, 40061, 40101, 40141, 40180, 40220, 40260, 40300,
-	40339, 40379, 40418, 40458, 40497, 40537, 40576, 40616,
-	40655, 40695, 40734, 40773, 40813, 40852, 40891, 40931,
-	40970, 41009, 41048, 41087, 41127, 41166, 41205, 41244,
-	41283, 41322, 41361, 41400, 41439, 41478, 41517, 41556,
-	41595, 41633, 41672, 41711, 41750, 41788, 41827, 41866,
-	41904, 41943, 41982, 42020, 42059, 42097, 42136, 42174,
-	42213, 42251, 42290, 42328, 42366, 42405, 42443, 42481,
-	42520, 42558, 42596, 42634, 42672, 42711, 42749, 42787,
-	42825, 42863, 42901, 42939, 42977, 43015, 43053, 43091,
-	43128, 43166, 43204, 43242, 43280, 43317, 43355, 43393,
-	43430, 43468, 43506, 43543, 43581, 43618, 43656, 43693,
-	43731, 43768, 43806, 43843, 43880, 43918, 43955, 43992,
-	44029, 44067, 44104, 44141, 44178, 44215, 44252, 44289,
-	44326, 44363, 44400, 44437, 44474, 44511, 44548, 44585,
-	44622, 44659, 44695, 44732, 44769, 44806, 44842, 44879,
-	44915, 44952, 44989, 45025, 45062, 45098, 45135, 45171,
-	45207, 45244, 45280, 45316, 45353, 45389, 45425, 45462,
-	45498, 45534, 45570, 45606, 45642, 45678, 45714, 45750,
-	45786, 45822, 45858, 45894, 45930, 45966, 46002, 46037,
-	46073, 46109, 46145, 46180, 46216, 46252, 46287, 46323,
-	46358, 46394, 46429, 46465, 46500, 46536, 46571, 46606,
-	46642, 46677, 46712, 46747, 46783, 46818, 46853, 46888,
-	46923, 46958, 46993, 47028, 47063, 47098, 47133, 47168,
-	47203, 47238, 47273, 47308, 47342, 47377, 47412, 47446,
-	47481, 47516, 47550, 47585, 47619, 47654, 47688, 47723,
-	47757, 47792, 47826, 47860, 47895, 47929, 47963, 47998,
-	48032, 48066, 48100, 48134, 48168, 48202, 48237, 48271,
-	48305, 48338, 48372, 48406, 48440, 48474, 48508, 48542,
-	48575, 48609, 48643, 48676, 48710, 48744, 48777, 48811,
-	48844, 48878, 48911, 48945, 48978, 49012, 49045, 49078,
-	49112, 49145, 49178, 49211, 49244, 49278, 49311, 49344,
-	49377, 49410, 49443, 49476, 49509, 49542, 49575, 49608,
-	49640, 49673, 49706, 49739, 49771, 49804, 49837, 49869,
-	49902, 49935, 49967, 50000, 50032, 50065, 50097, 50129,
-	50162, 50194, 50226, 50259, 50291, 50323, 50355, 50387,
-	50420, 50452, 50484, 50516, 50548, 50580, 50612, 50644,
-	50675, 50707, 50739, 50771, 50803, 50834, 50866, 50898,
-	50929, 50961, 50993, 51024, 51056, 51087, 51119, 51150,
-	51182, 51213, 51244, 51276, 51307, 51338, 51369, 51401,
-	51432, 51463, 51494, 51525, 51556, 51587, 51618, 51649,
-	51680, 51711, 51742, 51773, 51803, 51834, 51865, 51896,
-	51926, 51957, 51988, 52018, 52049, 52079, 52110, 52140,
-	52171, 52201, 52231, 52262, 52292, 52322, 52353, 52383,
-	52413, 52443, 52473, 52503, 52534, 52564, 52594, 52624,
-	52653, 52683, 52713, 52743, 52773, 52803, 52832, 52862,
-	52892, 52922, 52951, 52981, 53010, 53040, 53069, 53099,
-	53128, 53158, 53187, 53216, 53246, 53275, 53304, 53334,
-	53363, 53392, 53421, 53450, 53479, 53508, 53537, 53566,
-	53595, 53624, 53653, 53682, 53711, 53739, 53768, 53797,
-	53826, 53854, 53883, 53911, 53940, 53969, 53997, 54026,
-	54054, 54082, 54111, 54139, 54167, 54196, 54224, 54252,
-	54280, 54308, 54337, 54365, 54393, 54421, 54449, 54477,
-	54505, 54533, 54560, 54588, 54616, 54644, 54672, 54699,
-	54727, 54755, 54782, 54810, 54837, 54865, 54892, 54920,
-	54947, 54974, 55002, 55029, 55056, 55084, 55111, 55138,
-	55165, 55192, 55219, 55246, 55274, 55300, 55327, 55354,
-	55381, 55408, 55435, 55462, 55489, 55515, 55542, 55569,
-	55595, 55622, 55648, 55675, 55701, 55728, 55754, 55781,
-	55807, 55833, 55860, 55886, 55912, 55938, 55965, 55991,
-	56017, 56043, 56069, 56095, 56121, 56147, 56173, 56199,
-	56225, 56250, 56276, 56302, 56328, 56353, 56379, 56404,
-	56430, 56456, 56481, 56507, 56532, 56557, 56583, 56608,
-	56633, 56659, 56684, 56709, 56734, 56760, 56785, 56810,
-	56835, 56860, 56885, 56910, 56935, 56959, 56984, 57009,
-	57034, 57059, 57083, 57108, 57133, 57157, 57182, 57206,
-	57231, 57255, 57280, 57304, 57329, 57353, 57377, 57402,
-	57426, 57450, 57474, 57498, 57522, 57546, 57570, 57594,
-	57618, 57642, 57666, 57690, 57714, 57738, 57762, 57785,
-	57809, 57833, 57856, 57880, 57903, 57927, 57950, 57974,
-	57997, 58021, 58044, 58067, 58091, 58114, 58137, 58160,
-	58183, 58207, 58230, 58253, 58276, 58299, 58322, 58345,
-	58367, 58390, 58413, 58436, 58459, 58481, 58504, 58527,
-	58549, 58572, 58594, 58617, 58639, 58662, 58684, 58706,
-	58729, 58751, 58773, 58795, 58818, 58840, 58862, 58884,
-	58906, 58928, 58950, 58972, 58994, 59016, 59038, 59059,
-	59081, 59103, 59125, 59146, 59168, 59190, 59211, 59233,
-	59254, 59276, 59297, 59318, 59340, 59361, 59382, 59404,
-	59425, 59446, 59467, 59488, 59509, 59530, 59551, 59572,
-	59593, 59614, 59635, 59656, 59677, 59697, 59718, 59739,
-	59759, 59780, 59801, 59821, 59842, 59862, 59883, 59903,
-	59923, 59944, 59964, 59984, 60004, 60025, 60045, 60065,
-	60085, 60105, 60125, 60145, 60165, 60185, 60205, 60225,
-	60244, 60264, 60284, 60304, 60323, 60343, 60363, 60382,
-	60402, 60421, 60441, 60460, 60479, 60499, 60518, 60537,
-	60556, 60576, 60595, 60614, 60633, 60652, 60671, 60690,
-	60709, 60728, 60747, 60766, 60785, 60803, 60822, 60841,
-	60859, 60878, 60897, 60915, 60934, 60952, 60971, 60989,
-	61007, 61026, 61044, 61062, 61081, 61099, 61117, 61135,
-	61153, 61171, 61189, 61207, 61225, 61243, 61261, 61279,
-	61297, 61314, 61332, 61350, 61367, 61385, 61403, 61420,
-	61438, 61455, 61473, 61490, 61507, 61525, 61542, 61559,
-	61577, 61594, 61611, 61628, 61645, 61662, 61679, 61696,
-	61713, 61730, 61747, 61764, 61780, 61797, 61814, 61831,
-	61847, 61864, 61880, 61897, 61913, 61930, 61946, 61963,
-	61979, 61995, 62012, 62028, 62044, 62060, 62076, 62092,
-	62108, 62125, 62141, 62156, 62172, 62188, 62204, 62220,
-	62236, 62251, 62267, 62283, 62298, 62314, 62329, 62345,
-	62360, 62376, 62391, 62407, 62422, 62437, 62453, 62468,
-	62483, 62498, 62513, 62528, 62543, 62558, 62573, 62588,
-	62603, 62618, 62633, 62648, 62662, 62677, 62692, 62706,
-	62721, 62735, 62750, 62764, 62779, 62793, 62808, 62822,
-	62836, 62850, 62865, 62879, 62893, 62907, 62921, 62935,
-	62949, 62963, 62977, 62991, 63005, 63019, 63032, 63046,
-	63060, 63074, 63087, 63101, 63114, 63128, 63141, 63155,
-	63168, 63182, 63195, 63208, 63221, 63235, 63248, 63261,
-	63274, 63287, 63300, 63313, 63326, 63339, 63352, 63365,
-	63378, 63390, 63403, 63416, 63429, 63441, 63454, 63466,
-	63479, 63491, 63504, 63516, 63528, 63541, 63553, 63565,
-	63578, 63590, 63602, 63614, 63626, 63638, 63650, 63662,
-	63674, 63686, 63698, 63709, 63721, 63733, 63745, 63756,
-	63768, 63779, 63791, 63803, 63814, 63825, 63837, 63848,
-	63859, 63871, 63882, 63893, 63904, 63915, 63927, 63938,
-	63949, 63960, 63971, 63981, 63992, 64003, 64014, 64025,
-	64035, 64046, 64057, 64067, 64078, 64088, 64099, 64109,
-	64120, 64130, 64140, 64151, 64161, 64171, 64181, 64192,
-	64202, 64212, 64222, 64232, 64242, 64252, 64261, 64271,
-	64281, 64291, 64301, 64310, 64320, 64330, 64339, 64349,
-	64358, 64368, 64377, 64387, 64396, 64405, 64414, 64424,
-	64433, 64442, 64451, 64460, 64469, 64478, 64487, 64496,
-	64505, 64514, 64523, 64532, 64540, 64549, 64558, 64566,
-	64575, 64584, 64592, 64601, 64609, 64617, 64626, 64634,
-	64642, 64651, 64659, 64667, 64675, 64683, 64691, 64699,
-	64707, 64715, 64723, 64731, 64739, 64747, 64754, 64762,
-	64770, 64777, 64785, 64793, 64800, 64808, 64815, 64822,
-	64830, 64837, 64844, 64852, 64859, 64866, 64873, 64880,
-	64887, 64895, 64902, 64908, 64915, 64922, 64929, 64936,
-	64943, 64949, 64956, 64963, 64969, 64976, 64982, 64989,
-	64995, 65002, 65008, 65015, 65021, 65027, 65033, 65040,
-	65046, 65052, 65058, 65064, 65070, 65076, 65082, 65088,
-	65094, 65099, 65105, 65111, 65117, 65122, 65128, 65133,
-	65139, 65144, 65150, 65155, 65161, 65166, 65171, 65177,
-	65182, 65187, 65192, 65197, 65202, 65207, 65212, 65217,
-	65222, 65227, 65232, 65237, 65242, 65246, 65251, 65256,
-	65260, 65265, 65270, 65274, 65279, 65283, 65287, 65292,
-	65296, 65300, 65305, 65309, 65313, 65317, 65321, 65325,
-	65329, 65333, 65337, 65341, 65345, 65349, 65352, 65356,
-	65360, 65363, 65367, 65371, 65374, 65378, 65381, 65385,
-	65388, 65391, 65395, 65398, 65401, 65404, 65408, 65411,
-	65414, 65417, 65420, 65423, 65426, 65429, 65431, 65434,
-	65437, 65440, 65442, 65445, 65448, 65450, 65453, 65455,
-	65458, 65460, 65463, 65465, 65467, 65470, 65472, 65474,
-	65476, 65478, 65480, 65482, 65484, 65486, 65488, 65490,
-	65492, 65494, 65496, 65497, 65499, 65501, 65502, 65504,
-	65505, 65507, 65508, 65510, 65511, 65513, 65514, 65515,
-	65516, 65518, 65519, 65520, 65521, 65522, 65523, 65524,
-	65525, 65526, 65527, 65527, 65528, 65529, 65530, 65530,
+	0, 50, 100, 150, 201, 251, 301, 351,
+	402, 452, 502, 552, 603, 653, 703, 753,
+	804, 854, 904, 955, 1005, 1055, 1105, 1156,
+	1206, 1256, 1306, 1357, 1407, 1457, 1507, 1558,
+	1608, 1658, 1708, 1759, 1809, 1859, 1909, 1960,
+	2010, 2060, 2110, 2161, 2211, 2261, 2311, 2361,
+	2412, 2462, 2512, 2562, 2613, 2663, 2713, 2763,
+	2814, 2864, 2914, 2964, 3014, 3065, 3115, 3165,
+	3215, 3265, 3316, 3366, 3416, 3466, 3516, 3567,
+	3617, 3667, 3717, 3767, 3818, 3868, 3918, 3968,
+	4018, 4068, 4119, 4169, 4219, 4269, 4319, 4369,
+	4420, 4470, 4520, 4570, 4620, 4670, 4720, 4770,
+	4821, 4871, 4921, 4971, 5021, 5071, 5121, 5171,
+	5222, 5272, 5322, 5372, 5422, 5472, 5522, 5572,
+	5622, 5672, 5722, 5773, 5823, 5873, 5923, 5973,
+	6023, 6073, 6123, 6173, 6223, 6273, 6323, 6373,
+	6423, 6473, 6523, 6573, 6623, 6673, 6723, 6773,
+	6823, 6873, 6923, 6973, 7023, 7073, 7123, 7173,
+	7223, 7273, 7323, 7373, 7423, 7473, 7523, 7573,
+	7623, 7672, 7722, 7772, 7822, 7872, 7922, 7972,
+	8022, 8072, 8122, 8171, 8221, 8271, 8321, 8371,
+	8421, 8471, 8520, 8570, 8620, 8670, 8720, 8770,
+	8819, 8869, 8919, 8969, 9019, 9068, 9118, 9168,
+	9218, 9267, 9317, 9367, 9417, 9466, 9516, 9566,
+	9616, 9665, 9715, 9765, 9814, 9864, 9914, 9964,
+	10013, 10063, 10113, 10162, 10212, 10262, 10311, 10361,
+	10410, 10460, 10510, 10559, 10609, 10658, 10708, 10758,
+	10807, 10857, 10906, 10956, 11006, 11055, 11105, 11154,
+	11204, 11253, 11303, 11352, 11402, 11451, 11501, 11550,
+	11600, 11649, 11699, 11748, 11797, 11847, 11896, 11946,
+	11995, 12045, 12094, 12143, 12193, 12242, 12292, 12341,
+	12390, 12440, 12489, 12538, 12588, 12637, 12686, 12736,
+	12785, 12834, 12884, 12933, 12982, 13031, 13081, 13130,
+	13179, 13228, 13278, 13327, 13376, 13425, 13474, 13524,
+	13573, 13622, 13671, 13720, 13769, 13819, 13868, 13917,
+	13966, 14015, 14064, 14113, 14162, 14211, 14260, 14309,
+	14359, 14408, 14457, 14506, 14555, 14604, 14653, 14702,
+	14751, 14800, 14849, 14897, 14946, 14995, 15044, 15093,
+	15142, 15191, 15240, 15289, 15338, 15387, 15435, 15484,
+	15533, 15582, 15631, 15680, 15728, 15777, 15826, 15875,
+	15923, 15972, 16021, 16070, 16118, 16167, 16216, 16265,
+	16313, 16362, 16411, 16459, 16508, 16557, 16605, 16654,
+	16702, 16751, 16800, 16848, 16897, 16945, 16994, 17042,
+	17091, 17139, 17188, 17236, 17285, 17333, 17382, 17430,
+	17479, 17527, 17576, 17624, 17672, 17721, 17769, 17818,
+	17866, 17914, 17963, 18011, 18059, 18108, 18156, 18204,
+	18253, 18301, 18349, 18397, 18446, 18494, 18542, 18590,
+	18638, 18687, 18735, 18783, 18831, 18879, 18927, 18975,
+	19024, 19072, 19120, 19168, 19216, 19264, 19312, 19360,
+	19408, 19456, 19504, 19552, 19600, 19648, 19696, 19744,
+	19792, 19840, 19888, 19935, 19983, 20031, 20079, 20127,
+	20175, 20223, 20270, 20318, 20366, 20414, 20461, 20509,
+	20557, 20605, 20652, 20700, 20748, 20795, 20843, 20891,
+	20938, 20986, 21034, 21081, 21129, 21176, 21224, 21271,
+	21319, 21367, 21414, 21462, 21509, 21557, 21604, 21651,
+	21699, 21746, 21794, 21841, 21889, 21936, 21983, 22031,
+	22078, 22125, 22173, 22220, 22267, 22314, 22362, 22409,
+	22456, 22503, 22551, 22598, 22645, 22692, 22739, 22786,
+	22833, 22881, 22928, 22975, 23022, 23069, 23116, 23163,
+	23210, 23257, 23304, 23351, 23398, 23445, 23492, 23539,
+	23586, 23632, 23679, 23726, 23773, 23820, 23867, 23914,
+	23960, 24007, 24054, 24101, 24147, 24194, 24241, 24287,
+	24334, 24381, 24427, 24474, 24521, 24567, 24614, 24660,
+	24707, 24754, 24800, 24847, 24893, 24940, 24986, 25033,
+	25079, 25125, 25172, 25218, 25265, 25311, 25357, 25404,
+	25450, 25496, 25543, 25589, 25635, 25681, 25728, 25774,
+	25820, 25866, 25913, 25959, 26005, 26051, 26097, 26143,
+	26189, 26235, 26281, 26327, 26373, 26419, 26465, 26511,
+	26557, 26603, 26649, 26695, 26741, 26787, 26833, 26879,
+	26925, 26970, 27016, 27062, 27108, 27153, 27199, 27245,
+	27291, 27336, 27382, 27428, 27473, 27519, 27565, 27610,
+	27656, 27701, 27747, 27792, 27838, 27883, 27929, 27974,
+	28020, 28065, 28111, 28156, 28201, 28247, 28292, 28337,
+	28383, 28428, 28473, 28519, 28564, 28609, 28654, 28699,
+	28745, 28790, 28835, 28880, 28925, 28970, 29015, 29060,
+	29105, 29151, 29196, 29241, 29285, 29330, 29375, 29420,
+	29465, 29510, 29555, 29600, 29645, 29690, 29734, 29779,
+	29824, 29869, 29913, 29958, 30003, 30047, 30092, 30137,
+	30181, 30226, 30271, 30315, 30360, 30404, 30449, 30493,
+	30538, 30582, 30627, 30671, 30715, 30760, 30804, 30849,
+	30893, 30937, 30982, 31026, 31070, 31114, 31159, 31203,
+	31247, 31291, 31335, 31379, 31424, 31468, 31512, 31556,
+	31600, 31644, 31688, 31732, 31776, 31820, 31864, 31908,
+	31952, 31995, 32039, 32083, 32127, 32171, 32215, 32258,
+	32302, 32346, 32390, 32433, 32477, 32521, 32564, 32608,
+	32651, 32695, 32738, 32782, 32826, 32869, 32912, 32956,
+	32999, 33043, 33086, 33130, 33173, 33216, 33260, 33303,
+	33346, 33389, 33433, 33476, 33519, 33562, 33605, 33649,
+	33692, 33735, 33778, 33821, 33864, 33907, 33950, 33993,
+	34036, 34079, 34122, 34165, 34208, 34251, 34293, 34336,
+	34379, 34422, 34465, 34507, 34550, 34593, 34635, 34678,
+	34721, 34763, 34806, 34849, 34891, 34934, 34976, 35019,
+	35061, 35104, 35146, 35188, 35231, 35273, 35316, 35358,
+	35400, 35442, 35485, 35527, 35569, 35611, 35654, 35696,
+	35738, 35780, 35822, 35864, 35906, 35948, 35990, 36032,
+	36074, 36116, 36158, 36200, 36242, 36284, 36326, 36368,
+	36409, 36451, 36493, 36535, 36576, 36618, 36660, 36701,
+	36743, 36785, 36826, 36868, 36909, 36951, 36992, 37034,
+	37075, 37117, 37158, 37200, 37241, 37282, 37324, 37365,
+	37406, 37447, 37489, 37530, 37571, 37612, 37653, 37695,
+	37736, 37777, 37818, 37859, 37900, 37941, 37982, 38023,
+	38064, 38105, 38146, 38186, 38227, 38268, 38309, 38350,
+	38390, 38431, 38472, 38512, 38553, 38594, 38634, 38675,
+	38716, 38756, 38797, 38837, 38878, 38918, 38958, 38999,
+	39039, 39080, 39120, 39160, 39201, 39241, 39281, 39321,
+	39362, 39402, 39442, 39482, 39522, 39562, 39602, 39642,
+	39682, 39722, 39762, 39802, 39842, 39882, 39922, 39962,
+	40002, 40041, 40081, 40121, 40161, 40200, 40240, 40280,
+	40319, 40359, 40399, 40438, 40478, 40517, 40557, 40596,
+	40636, 40675, 40714, 40754, 40793, 40832, 40872, 40911,
+	40950, 40990, 41029, 41068, 41107, 41146, 41185, 41224,
+	41263, 41303, 41342, 41381, 41419, 41458, 41497, 41536,
+	41575, 41614, 41653, 41692, 41730, 41769, 41808, 41846,
+	41885, 41924, 41962, 42001, 42040, 42078, 42117, 42155,
+	42194, 42232, 42271, 42309, 42347, 42386, 42424, 42462,
+	42501, 42539, 42577, 42615, 42653, 42692, 42730, 42768,
+	42806, 42844, 42882, 42920, 42958, 42996, 43034, 43072,
+	43110, 43147, 43185, 43223, 43261, 43298, 43336, 43374,
+	43412, 43449, 43487, 43524, 43562, 43600, 43637, 43675,
+	43712, 43749, 43787, 43824, 43862, 43899, 43936, 43974,
+	44011, 44048, 44085, 44122, 44160, 44197, 44234, 44271,
+	44308, 44345, 44382, 44419, 44456, 44493, 44530, 44567,
+	44603, 44640, 44677, 44714, 44750, 44787, 44824, 44861,
+	44897, 44934, 44970, 45007, 45043, 45080, 45116, 45153,
+	45189, 45226, 45262, 45298, 45335, 45371, 45407, 45443,
+	45480, 45516, 45552, 45588, 45624, 45660, 45696, 45732,
+	45768, 45804, 45840, 45876, 45912, 45948, 45984, 46019,
+	46055, 46091, 46127, 46162, 46198, 46234, 46269, 46305,
+	46340, 46376, 46411, 46447, 46482, 46518, 46553, 46589,
+	46624, 46659, 46695, 46730, 46765, 46800, 46835, 46871,
+	46906, 46941, 46976, 47011, 47046, 47081, 47116, 47151,
+	47186, 47220, 47255, 47290, 47325, 47360, 47394, 47429,
+	47464, 47498, 47533, 47568, 47602, 47637, 47671, 47706,
+	47740, 47775, 47809, 47843, 47878, 47912, 47946, 47981,
+	48015, 48049, 48083, 48117, 48151, 48185, 48219, 48254,
+	48288, 48321, 48355, 48389, 48423, 48457, 48491, 48525,
+	48558, 48592, 48626, 48660, 48693, 48727, 48760, 48794,
+	48828, 48861, 48895, 48928, 48961, 48995, 49028, 49062,
+	49095, 49128, 49161, 49195, 49228, 49261, 49294, 49327,
+	49360, 49393, 49426, 49459, 49492, 49525, 49558, 49591,
+	49624, 49657, 49690, 49722, 49755, 49788, 49820, 49853,
+	49886, 49918, 49951, 49983, 50016, 50048, 50081, 50113,
+	50146, 50178, 50210, 50242, 50275, 50307, 50339, 50371,
+	50403, 50436, 50468, 50500, 50532, 50564, 50596, 50628,
+	50660, 50691, 50723, 50755, 50787, 50819, 50850, 50882,
+	50914, 50945, 50977, 51008, 51040, 51072, 51103, 51134,
+	51166, 51197, 51229, 51260, 51291, 51323, 51354, 51385,
+	51416, 51447, 51478, 51510, 51541, 51572, 51603, 51634,
+	51665, 51695, 51726, 51757, 51788, 51819, 51850, 51880,
+	51911, 51942, 51972, 52003, 52033, 52064, 52095, 52125,
+	52155, 52186, 52216, 52247, 52277, 52307, 52338, 52368,
+	52398, 52428, 52458, 52488, 52518, 52549, 52579, 52609,
+	52639, 52668, 52698, 52728, 52758, 52788, 52818, 52847,
+	52877, 52907, 52936, 52966, 52996, 53025, 53055, 53084,
+	53114, 53143, 53172, 53202, 53231, 53260, 53290, 53319,
+	53348, 53377, 53407, 53436, 53465, 53494, 53523, 53552,
+	53581, 53610, 53639, 53667, 53696, 53725, 53754, 53783,
+	53811, 53840, 53869, 53897, 53926, 53954, 53983, 54011,
+	54040, 54068, 54097, 54125, 54153, 54182, 54210, 54238,
+	54266, 54294, 54323, 54351, 54379, 54407, 54435, 54463,
+	54491, 54519, 54546, 54574, 54602, 54630, 54658, 54685,
+	54713, 54741, 54768, 54796, 54823, 54851, 54879, 54906,
+	54933, 54961, 54988, 55015, 55043, 55070, 55097, 55124,
+	55152, 55179, 55206, 55233, 55260, 55287, 55314, 55341,
+	55368, 55395, 55422, 55448, 55475, 55502, 55529, 55555,
+	55582, 55609, 55635, 55662, 55688, 55715, 55741, 55768,
+	55794, 55820, 55847, 55873, 55899, 55925, 55952, 55978,
+	56004, 56030, 56056, 56082, 56108, 56134, 56160, 56186,
+	56212, 56237, 56263, 56289, 56315, 56340, 56366, 56392,
+	56417, 56443, 56468, 56494, 56519, 56545, 56570, 56595,
+	56621, 56646, 56671, 56697, 56722, 56747, 56772, 56797,
+	56822, 56847, 56872, 56897, 56922, 56947, 56972, 56997,
+	57022, 57046, 57071, 57096, 57120, 57145, 57170, 57194,
+	57219, 57243, 57268, 57292, 57316, 57341, 57365, 57389,
+	57414, 57438, 57462, 57486, 57510, 57534, 57558, 57582,
+	57606, 57630, 57654, 57678, 57702, 57726, 57750, 57773,
+	57797, 57821, 57844, 57868, 57892, 57915, 57939, 57962,
+	57986, 58009, 58032, 58056, 58079, 58102, 58125, 58149,
+	58172, 58195, 58218, 58241, 58264, 58287, 58310, 58333,
+	58356, 58379, 58402, 58424, 58447, 58470, 58493, 58515,
+	58538, 58560, 58583, 58605, 58628, 58650, 58673, 58695,
+	58718, 58740, 58762, 58784, 58807, 58829, 58851, 58873,
+	58895, 58917, 58939, 58961, 58983, 59005, 59027, 59049,
+	59070, 59092, 59114, 59135, 59157, 59179, 59200, 59222,
+	59243, 59265, 59286, 59308, 59329, 59350, 59372, 59393,
+	59414, 59435, 59457, 59478, 59499, 59520, 59541, 59562,
+	59583, 59604, 59625, 59645, 59666, 59687, 59708, 59728,
+	59749, 59770, 59790, 59811, 59831, 59852, 59872, 59893,
+	59913, 59934, 59954, 59974, 59994, 60015, 60035, 60055,
+	60075, 60095, 60115, 60135, 60155, 60175, 60195, 60215,
+	60235, 60254, 60274, 60294, 60313, 60333, 60353, 60372,
+	60392, 60411, 60431, 60450, 60470, 60489, 60508, 60528,
+	60547, 60566, 60585, 60604, 60624, 60643, 60662, 60681,
+	60700, 60719, 60737, 60756, 60775, 60794, 60813, 60831,
+	60850, 60869, 60887, 60906, 60924, 60943, 60961, 60980,
+	60998, 61017, 61035, 61053, 61071, 61090, 61108, 61126,
+	61144, 61162, 61180, 61198, 61216, 61234, 61252, 61270,
+	61288, 61305, 61323, 61341, 61359, 61376, 61394, 61411,
+	61429, 61446, 61464, 61481, 61499, 61516, 61533, 61551,
+	61568, 61585, 61602, 61619, 61637, 61654, 61671, 61688,
+	61705, 61721, 61738, 61755, 61772, 61789, 61805, 61822,
+	61839, 61855, 61872, 61889, 61905, 61922, 61938, 61954,
+	61971, 61987, 62003, 62020, 62036, 62052, 62068, 62084,
+	62100, 62117, 62133, 62148, 62164, 62180, 62196, 62212,
+	62228, 62244, 62259, 62275, 62291, 62306, 62322, 62337,
+	62353, 62368, 62384, 62399, 62414, 62430, 62445, 62460,
+	62475, 62491, 62506, 62521, 62536, 62551, 62566, 62581,
+	62596, 62610, 62625, 62640, 62655, 62670, 62684, 62699,
+	62714, 62728, 62743, 62757, 62772, 62786, 62800, 62815,
+	62829, 62843, 62858, 62872, 62886, 62900, 62914, 62928,
+	62942, 62956, 62970, 62984, 62998, 63012, 63026, 63039,
+	63053, 63067, 63080, 63094, 63108, 63121, 63135, 63148,
+	63162, 63175, 63188, 63202, 63215, 63228, 63241, 63254,
+	63268, 63281, 63294, 63307, 63320, 63333, 63346, 63358,
+	63371, 63384, 63397, 63410, 63422, 63435, 63447, 63460,
+	63473, 63485, 63498, 63510, 63522, 63535, 63547, 63559,
+	63571, 63584, 63596, 63608, 63620, 63632, 63644, 63656,
+	63668, 63680, 63692, 63704, 63715, 63727, 63739, 63750,
+	63762, 63774, 63785, 63797, 63808, 63820, 63831, 63842,
+	63854, 63865, 63876, 63888, 63899, 63910, 63921, 63932,
+	63943, 63954, 63965, 63976, 63987, 63998, 64009, 64019,
+	64030, 64041, 64051, 64062, 64073, 64083, 64094, 64104,
+	64115, 64125, 64135, 64146, 64156, 64166, 64176, 64186,
+	64197, 64207, 64217, 64227, 64237, 64247, 64257, 64266,
+	64276, 64286, 64296, 64305, 64315, 64325, 64334, 64344,
+	64353, 64363, 64372, 64382, 64391, 64401, 64410, 64419,
+	64428, 64437, 64447, 64456, 64465, 64474, 64483, 64492,
+	64501, 64510, 64518, 64527, 64536, 64545, 64553, 64562,
+	64571, 64579, 64588, 64596, 64605, 64613, 64622, 64630,
+	64638, 64646, 64655, 64663, 64671, 64679, 64687, 64695,
+	64703, 64711, 64719, 64727, 64735, 64743, 64751, 64758,
+	64766, 64774, 64781, 64789, 64796, 64804, 64811, 64819,
+	64826, 64834, 64841, 64848, 64855, 64863, 64870, 64877,
+	64884, 64891, 64898, 64905, 64912, 64919, 64926, 64933,
+	64939, 64946, 64953, 64959, 64966, 64973, 64979, 64986,
+	64992, 64999, 65005, 65011, 65018, 65024, 65030, 65036,
+	65043, 65049, 65055, 65061, 65067, 65073, 65079, 65085,
+	65091, 65096, 65102, 65108, 65114, 65119, 65125, 65131,
+	65136, 65142, 65147, 65153, 65158, 65163, 65169, 65174,
+	65179, 65184, 65190, 65195, 65200, 65205, 65210, 65215,
+	65220, 65225, 65230, 65235, 65239, 65244, 65249, 65253,
+	65258, 65263, 65267, 65272, 65276, 65281, 65285, 65290,
+	65294, 65298, 65302, 65307, 65311, 65315, 65319, 65323,
+	65327, 65331, 65335, 65339, 65343, 65347, 65350, 65354,
+	65358, 65362, 65365, 65369, 65372, 65376, 65379, 65383,
+	65386, 65390, 65393, 65396, 65400, 65403, 65406, 65409,
+	65412, 65415, 65418, 65421, 65424, 65427, 65430, 65433,
+	65436, 65438, 65441, 65444, 65446, 65449, 65452, 65454,
+	65457, 65459, 65461, 65464, 65466, 65468, 65471, 65473,
+	65475, 65477, 65479, 65481, 65483, 65485, 65487, 65489,
+	65491, 65493, 65495, 65496, 65498, 65500, 65501, 65503,
+	65505, 65506, 65508, 65509, 65511, 65512, 65513, 65515,
+	65516, 65517, 65518, 65519, 65520, 65521, 65522, 65523,
+	65524, 65525, 65526, 65527, 65528, 65529, 65529, 65530,
 	65531, 65531, 65532, 65532, 65533, 65533, 65534, 65534,
 	65534, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
-	65535, 65535, 65535, 65535, 65535, 65535, 65535, 65534,
-	65534, 65534, 65533, 65533, 65532, 65532, 65531, 65531,
-	65530, 65530, 65529, 65528, 65527, 65527, 65526, 65525,
-	65524, 65523, 65522, 65521, 65520, 65519, 65518, 65516,
-	65515, 65514, 65513, 65511, 65510, 65508, 65507, 65505,
-	65504, 65502, 65501, 65499, 65497, 65496, 65494, 65492,
-	65490, 65488, 65486, 65484, 65482, 65480, 65478, 65476,
-	65474, 65472, 65470, 65467, 65465, 65463, 65460, 65458,
-	65455, 65453, 65450, 65448, 65445, 65442, 65440, 65437,
-	65434, 65431, 65429, 65426, 65423, 65420, 65417, 65414,
-	65411, 65408, 65404, 65401, 65398, 65395, 65391, 65388,
-	65385, 65381, 65378, 65374, 65371, 65367, 65363, 65360,
-	65356, 65352, 65349, 65345, 65341, 65337, 65333, 65329,
-	65325, 65321, 65317, 65313, 65309, 65305, 65300, 65296,
-	65292, 65287, 65283, 65279, 65274, 65270, 65265, 65260,
-	65256, 65251, 65246, 65242, 65237, 65232, 65227, 65222,
-	65217, 65212, 65207, 65202, 65197, 65192, 65187, 65182,
-	65177, 65171, 65166, 65161, 65155, 65150, 65144, 65139,
-	65133, 65128, 65122, 65117, 65111, 65105, 65099, 65094,
-	65088, 65082, 65076, 65070, 65064, 65058, 65052, 65046,
-	65040, 65033, 65027, 65021, 65015, 65008, 65002, 64995,
-	64989, 64982, 64976, 64969, 64963, 64956, 64949, 64943,
-	64936, 64929, 64922, 64915, 64908, 64902, 64895, 64887,
-	64880, 64873, 64866, 64859, 64852, 64844, 64837, 64830,
-	64822, 64815, 64808, 64800, 64793, 64785, 64777, 64770,
-	64762, 64754, 64747, 64739, 64731, 64723, 64715, 64707,
-	64699, 64691, 64683, 64675, 64667, 64659, 64651, 64642,
-	64634, 64626, 64617, 64609, 64600, 64592, 64584, 64575,
-	64566, 64558, 64549, 64540, 64532, 64523, 64514, 64505,
-	64496, 64487, 64478, 64469, 64460, 64451, 64442, 64433,
-	64424, 64414, 64405, 64396, 64387, 64377, 64368, 64358,
-	64349, 64339, 64330, 64320, 64310, 64301, 64291, 64281,
-	64271, 64261, 64252, 64242, 64232, 64222, 64212, 64202,
-	64192, 64181, 64171, 64161, 64151, 64140, 64130, 64120,
-	64109, 64099, 64088, 64078, 64067, 64057, 64046, 64035,
-	64025, 64014, 64003, 63992, 63981, 63971, 63960, 63949,
-	63938, 63927, 63915, 63904, 63893, 63882, 63871, 63859,
-	63848, 63837, 63825, 63814, 63803, 63791, 63779, 63768,
-	63756, 63745, 63733, 63721, 63709, 63698, 63686, 63674,
-	63662, 63650, 63638, 63626, 63614, 63602, 63590, 63578,
-	63565, 63553, 63541, 63528, 63516, 63504, 63491, 63479,
-	63466, 63454, 63441, 63429, 63416, 63403, 63390, 63378,
-	63365, 63352, 63339, 63326, 63313, 63300, 63287, 63274,
-	63261, 63248, 63235, 63221, 63208, 63195, 63182, 63168,
-	63155, 63141, 63128, 63114, 63101, 63087, 63074, 63060,
-	63046, 63032, 63019, 63005, 62991, 62977, 62963, 62949,
-	62935, 62921, 62907, 62893, 62879, 62865, 62850, 62836,
-	62822, 62808, 62793, 62779, 62764, 62750, 62735, 62721,
-	62706, 62692, 62677, 62662, 62648, 62633, 62618, 62603,
-	62588, 62573, 62558, 62543, 62528, 62513, 62498, 62483,
-	62468, 62453, 62437, 62422, 62407, 62391, 62376, 62360,
-	62345, 62329, 62314, 62298, 62283, 62267, 62251, 62236,
-	62220, 62204, 62188, 62172, 62156, 62141, 62125, 62108,
-	62092, 62076, 62060, 62044, 62028, 62012, 61995, 61979,
-	61963, 61946, 61930, 61913, 61897, 61880, 61864, 61847,
-	61831, 61814, 61797, 61780, 61764, 61747, 61730, 61713,
-	61696, 61679, 61662, 61645, 61628, 61611, 61594, 61577,
-	61559, 61542, 61525, 61507, 61490, 61473, 61455, 61438,
-	61420, 61403, 61385, 61367, 61350, 61332, 61314, 61297,
-	61279, 61261, 61243, 61225, 61207, 61189, 61171, 61153,
-	61135, 61117, 61099, 61081, 61062, 61044, 61026, 61007,
-	60989, 60971, 60952, 60934, 60915, 60897, 60878, 60859,
-	60841, 60822, 60803, 60785, 60766, 60747, 60728, 60709,
-	60690, 60671, 60652, 60633, 60614, 60595, 60576, 60556,
-	60537, 60518, 60499, 60479, 60460, 60441, 60421, 60402,
-	60382, 60363, 60343, 60323, 60304, 60284, 60264, 60244,
-	60225, 60205, 60185, 60165, 60145, 60125, 60105, 60085,
-	60065, 60045, 60025, 60004, 59984, 59964, 59944, 59923,
-	59903, 59883, 59862, 59842, 59821, 59801, 59780, 59759,
-	59739, 59718, 59697, 59677, 59656, 59635, 59614, 59593,
-	59572, 59551, 59530, 59509, 59488, 59467, 59446, 59425,
-	59404, 59382, 59361, 59340, 59318, 59297, 59276, 59254,
-	59233, 59211, 59190, 59168, 59146, 59125, 59103, 59081,
-	59059, 59038, 59016, 58994, 58972, 58950, 58928, 58906,
-	58884, 58862, 58840, 58818, 58795, 58773, 58751, 58729,
-	58706, 58684, 58662, 58639, 58617, 58594, 58572, 58549,
-	58527, 58504, 58481, 58459, 58436, 58413, 58390, 58367,
-	58345, 58322, 58299, 58276, 58253, 58230, 58207, 58183,
-	58160, 58137, 58114, 58091, 58067, 58044, 58021, 57997,
-	57974, 57950, 57927, 57903, 57880, 57856, 57833, 57809,
-	57785, 57762, 57738, 57714, 57690, 57666, 57642, 57618,
-	57594, 57570, 57546, 57522, 57498, 57474, 57450, 57426,
-	57402, 57377, 57353, 57329, 57304, 57280, 57255, 57231,
-	57206, 57182, 57157, 57133, 57108, 57083, 57059, 57034,
-	57009, 56984, 56959, 56935, 56910, 56885, 56860, 56835,
-	56810, 56785, 56760, 56734, 56709, 56684, 56659, 56633,
-	56608, 56583, 56557, 56532, 56507, 56481, 56456, 56430,
-	56404, 56379, 56353, 56328, 56302, 56276, 56250, 56225,
-	56199, 56173, 56147, 56121, 56095, 56069, 56043, 56017,
-	55991, 55965, 55938, 55912, 55886, 55860, 55833, 55807,
-	55781, 55754, 55728, 55701, 55675, 55648, 55622, 55595,
-	55569, 55542, 55515, 55489, 55462, 55435, 55408, 55381,
-	55354, 55327, 55300, 55274, 55246, 55219, 55192, 55165,
-	55138, 55111, 55084, 55056, 55029, 55002, 54974, 54947,
-	54920, 54892, 54865, 54837, 54810, 54782, 54755, 54727,
-	54699, 54672, 54644, 54616, 54588, 54560, 54533, 54505,
-	54477, 54449, 54421, 54393, 54365, 54337, 54308, 54280,
-	54252, 54224, 54196, 54167, 54139, 54111, 54082, 54054,
-	54026, 53997, 53969, 53940, 53911, 53883, 53854, 53826,
-	53797, 53768, 53739, 53711, 53682, 53653, 53624, 53595,
-	53566, 53537, 53508, 53479, 53450, 53421, 53392, 53363,
-	53334, 53304, 53275, 53246, 53216, 53187, 53158, 53128,
-	53099, 53069, 53040, 53010, 52981, 52951, 52922, 52892,
-	52862, 52832, 52803, 52773, 52743, 52713, 52683, 52653,
-	52624, 52594, 52564, 52534, 52503, 52473, 52443, 52413,
-	52383, 52353, 52322, 52292, 52262, 52231, 52201, 52171,
-	52140, 52110, 52079, 52049, 52018, 51988, 51957, 51926,
-	51896, 51865, 51834, 51803, 51773, 51742, 51711, 51680,
-	51649, 51618, 51587, 51556, 51525, 51494, 51463, 51432,
-	51401, 51369, 51338, 51307, 51276, 51244, 51213, 51182,
-	51150, 51119, 51087, 51056, 51024, 50993, 50961, 50929,
-	50898, 50866, 50834, 50803, 50771, 50739, 50707, 50675,
-	50644, 50612, 50580, 50548, 50516, 50484, 50452, 50420,
-	50387, 50355, 50323, 50291, 50259, 50226, 50194, 50162,
-	50129, 50097, 50065, 50032, 50000, 49967, 49935, 49902,
-	49869, 49837, 49804, 49771, 49739, 49706, 49673, 49640,
-	49608, 49575, 49542, 49509, 49476, 49443, 49410, 49377,
-	49344, 49311, 49278, 49244, 49211, 49178, 49145, 49112,
-	49078, 49045, 49012, 48978, 48945, 48911, 48878, 48844,
-	48811, 48777, 48744, 48710, 48676, 48643, 48609, 48575,
-	48542, 48508, 48474, 48440, 48406, 48372, 48338, 48304,
-	48271, 48237, 48202, 48168, 48134, 48100, 48066, 48032,
-	47998, 47963, 47929, 47895, 47860, 47826, 47792, 47757,
-	47723, 47688, 47654, 47619, 47585, 47550, 47516, 47481,
-	47446, 47412, 47377, 47342, 47308, 47273, 47238, 47203,
-	47168, 47133, 47098, 47063, 47028, 46993, 46958, 46923,
-	46888, 46853, 46818, 46783, 46747, 46712, 46677, 46642,
-	46606, 46571, 46536, 46500, 46465, 46429, 46394, 46358,
-	46323, 46287, 46252, 46216, 46180, 46145, 46109, 46073,
-	46037, 46002, 45966, 45930, 45894, 45858, 45822, 45786,
-	45750, 45714, 45678, 45642, 45606, 45570, 45534, 45498,
-	45462, 45425, 45389, 45353, 45316, 45280, 45244, 45207,
-	45171, 45135, 45098, 45062, 45025, 44989, 44952, 44915,
-	44879, 44842, 44806, 44769, 44732, 44695, 44659, 44622,
-	44585, 44548, 44511, 44474, 44437, 44400, 44363, 44326,
-	44289, 44252, 44215, 44178, 44141, 44104, 44067, 44029,
-	43992, 43955, 43918, 43880, 43843, 43806, 43768, 43731,
-	43693, 43656, 43618, 43581, 43543, 43506, 43468, 43430,
-	43393, 43355, 43317, 43280, 43242, 43204, 43166, 43128,
-	43091, 43053, 43015, 42977, 42939, 42901, 42863, 42825,
-	42787, 42749, 42711, 42672, 42634, 42596, 42558, 42520,
-	42481, 42443, 42405, 42366, 42328, 42290, 42251, 42213,
-	42174, 42136, 42097, 42059, 42020, 41982, 41943, 41904,
-	41866, 41827, 41788, 41750, 41711, 41672, 41633, 41595,
-	41556, 41517, 41478, 41439, 41400, 41361, 41322, 41283,
-	41244, 41205, 41166, 41127, 41088, 41048, 41009, 40970,
-	40931, 40891, 40852, 40813, 40773, 40734, 40695, 40655,
-	40616, 40576, 40537, 40497, 40458, 40418, 40379, 40339,
-	40300, 40260, 40220, 40180, 40141, 40101, 40061, 40021,
-	39982, 39942, 39902, 39862, 39822, 39782, 39742, 39702,
-	39662, 39622, 39582, 39542, 39502, 39462, 39422, 39382,
-	39341, 39301, 39261, 39221, 39180, 39140, 39100, 39059,
-	39019, 38979, 38938, 38898, 38857, 38817, 38776, 38736,
-	38695, 38655, 38614, 38573, 38533, 38492, 38451, 38411,
-	38370, 38329, 38288, 38248, 38207, 38166, 38125, 38084,
-	38043, 38002, 37961, 37920, 37879, 37838, 37797, 37756,
-	37715, 37674, 37633, 37592, 37551, 37509, 37468, 37427,
-	37386, 37344, 37303, 37262, 37220, 37179, 37137, 37096,
-	37055, 37013, 36972, 36930, 36889, 36847, 36805, 36764,
-	36722, 36681, 36639, 36597, 36556, 36514, 36472, 36430,
-	36388, 36347, 36305, 36263, 36221, 36179, 36137, 36095,
-	36053, 36011, 35969, 35927, 35885, 35843, 35801, 35759,
-	35717, 35675, 35633, 35590, 35548, 35506, 35464, 35421,
-	35379, 35337, 35294, 35252, 35210, 35167, 35125, 35082,
-	35040, 34997, 34955, 34912, 34870, 34827, 34785, 34742,
-	34699, 34657, 34614, 34571, 34529, 34486, 34443, 34400,
-	34358, 34315, 34272, 34229, 34186, 34143, 34100, 34057,
-	34015, 33972, 33929, 33886, 33843, 33799, 33756, 33713,
-	33670, 33627, 33584, 33541, 33498, 33454, 33411, 33368,
-	33325, 33281, 33238, 33195, 33151, 33108, 33065, 33021,
-	32978, 32934, 32891, 32847, 32804, 32760, 32717, 32673,
-	32630, 32586, 32542, 32499, 32455, 32411, 32368, 32324,
-	32280, 32236, 32193, 32149, 32105, 32061, 32017, 31974,
-	31930, 31886, 31842, 31798, 31754, 31710, 31666, 31622,
-	31578, 31534, 31490, 31446, 31402, 31357, 31313, 31269,
-	31225, 31181, 31136, 31092, 31048, 31004, 30959, 30915,
-	30871, 30826, 30782, 30738, 30693, 30649, 30604, 30560,
-	30515, 30471, 30426, 30382, 30337, 30293, 30248, 30204,
-	30159, 30114, 30070, 30025, 29980, 29936, 29891, 29846,
-	29801, 29757, 29712, 29667, 29622, 29577, 29533, 29488,
-	29443, 29398, 29353, 29308, 29263, 29218, 29173, 29128,
-	29083, 29038, 28993, 28948, 28903, 28858, 28812, 28767,
-	28722, 28677, 28632, 28586, 28541, 28496, 28451, 28405,
-	28360, 28315, 28269, 28224, 28179, 28133, 28088, 28042,
-	27997, 27952, 27906, 27861, 27815, 27770, 27724, 27678,
-	27633, 27587, 27542, 27496, 27450, 27405, 27359, 27313,
-	27268, 27222, 27176, 27131, 27085, 27039, 26993, 26947,
-	26902, 26856, 26810, 26764, 26718, 26672, 26626, 26580,
-	26534, 26488, 26442, 26396, 26350, 26304, 26258, 26212,
-	26166, 26120, 26074, 26028, 25982, 25936, 25889, 25843,
-	25797, 25751, 25705, 25658, 25612, 25566, 25520, 25473,
-	25427, 25381, 25334, 25288, 25241, 25195, 25149, 25102,
-	25056, 25009, 24963, 24916, 24870, 24823, 24777, 24730,
-	24684, 24637, 24591, 24544, 24497, 24451, 24404, 24357,
-	24311, 24264, 24217, 24171, 24124, 24077, 24030, 23984,
-	23937, 23890, 23843, 23796, 23750, 23703, 23656, 23609,
-	23562, 23515, 23468, 23421, 23374, 23327, 23280, 23233,
-	23186, 23139, 23092, 23045, 22998, 22951, 22904, 22857,
-	22810, 22763, 22716, 22668, 22621, 22574, 22527, 22480,
-	22433, 22385, 22338, 22291, 22243, 22196, 22149, 22102,
-	22054, 22007, 21960, 21912, 21865, 21817, 21770, 21723,
-	21675, 21628, 21580, 21533, 21485, 21438, 21390, 21343,
-	21295, 21248, 21200, 21153, 21105, 21057, 21010, 20962,
-	20915, 20867, 20819, 20772, 20724, 20676, 20629, 20581,
-	20533, 20485, 20438, 20390, 20342, 20294, 20246, 20199,
-	20151, 20103, 20055, 20007, 19959, 19912, 19864, 19816,
-	19768, 19720, 19672, 19624, 19576, 19528, 19480, 19432,
-	19384, 19336, 19288, 19240, 19192, 19144, 19096, 19048,
-	19000, 18951, 18903, 18855, 18807, 18759, 18711, 18663,
-	18614, 18566, 18518, 18470, 18421, 18373, 18325, 18277,
-	18228, 18180, 18132, 18084, 18035, 17987, 17939, 17890,
-	17842, 17793, 17745, 17697, 17648, 17600, 17551, 17503,
-	17455, 17406, 17358, 17309, 17261, 17212, 17164, 17115,
-	17067, 17018, 16970, 16921, 16872, 16824, 16775, 16727,
-	16678, 16629, 16581, 16532, 16484, 16435, 16386, 16338,
-	16289, 16240, 16191, 16143, 16094, 16045, 15997, 15948,
-	15899, 15850, 15802, 15753, 15704, 15655, 15606, 15557,
-	15509, 15460, 15411, 15362, 15313, 15264, 15215, 15167,
-	15118, 15069, 15020, 14971, 14922, 14873, 14824, 14775,
-	14726, 14677, 14628, 14579, 14530, 14481, 14432, 14383,
-	14334, 14285, 14236, 14187, 14138, 14089, 14040, 13990,
-	13941, 13892, 13843, 13794, 13745, 13696, 13646, 13597,
-	13548, 13499, 13450, 13401, 13351, 13302, 13253, 13204,
-	13154, 13105, 13056, 13007, 12957, 12908, 12859, 12810,
-	12760, 12711, 12662, 12612, 12563, 12514, 12464, 12415,
-	12366, 12316, 12267, 12218, 12168, 12119, 12069, 12020,
-	11970, 11921, 11872, 11822, 11773, 11723, 11674, 11624,
-	11575, 11525, 11476, 11426, 11377, 11327, 11278, 11228,
-	11179, 11129, 11080, 11030, 10981, 10931, 10882, 10832,
-	10782, 10733, 10683, 10634, 10584, 10534, 10485, 10435,
-	10386, 10336, 10286, 10237, 10187, 10137, 10088, 10038,
-	9988, 9939, 9889, 9839, 9790, 9740, 9690, 9640,
-	9591, 9541, 9491, 9442, 9392, 9342, 9292, 9243,
-	9193, 9143, 9093, 9043, 8994, 8944, 8894, 8844,
-	8794, 8745, 8695, 8645, 8595, 8545, 8496, 8446,
-	8396, 8346, 8296, 8246, 8196, 8147, 8097, 8047,
-	7997, 7947, 7897, 7847, 7797, 7747, 7697, 7648,
-	7598, 7548, 7498, 7448, 7398, 7348, 7298, 7248,
-	7198, 7148, 7098, 7048, 6998, 6948, 6898, 6848,
-	6798, 6748, 6698, 6648, 6598, 6548, 6498, 6448,
-	6398, 6348, 6298, 6248, 6198, 6148, 6098, 6048,
-	5998, 5948, 5898, 5848, 5798, 5748, 5697, 5647,
-	5597, 5547, 5497, 5447, 5397, 5347, 5297, 5247,
-	5197, 5146, 5096, 5046, 4996, 4946, 4896, 4846,
-	4796, 4745, 4695, 4645, 4595, 4545, 4495, 4445,
-	4394, 4344, 4294, 4244, 4194, 4144, 4093, 4043,
-	3993, 3943, 3893, 3843, 3792, 3742, 3692, 3642,
-	3592, 3541, 3491, 3441, 3391, 3341, 3291, 3240,
-	3190, 3140, 3090, 3039, 2989, 2939, 2889, 2839,
-	2788, 2738, 2688, 2638, 2587, 2537, 2487, 2437,
-	2387, 2336, 2286, 2236, 2186, 2135, 2085, 2035,
-	1985, 1934, 1884, 1834, 1784, 1733, 1683, 1633,
-	1583, 1532, 1482, 1432, 1382, 1331, 1281, 1231,
-	1181, 1130, 1080, 1030, 980, 929, 879, 829,
-	779, 728, 678, 628, 578, 527, 477, 427,
-	376, 326, 276, 226, 175, 125, 75, 25,
-	-25, -75, -125, -175, -226, -276, -326, -376,
-	-427, -477, -527, -578, -628, -678, -728, -779,
-	-829, -879, -929, -980, -1030, -1080, -1130, -1181,
-	-1231, -1281, -1331, -1382, -1432, -1482, -1532, -1583,
-	-1633, -1683, -1733, -1784, -1834, -1884, -1934, -1985,
-	-2035, -2085, -2135, -2186, -2236, -2286, -2336, -2387,
-	-2437, -2487, -2537, -2588, -2638, -2688, -2738, -2788,
-	-2839, -2889, -2939, -2989, -3039, -3090, -3140, -3190,
-	-3240, -3291, -3341, -3391, -3441, -3491, -3541, -3592,
-	-3642, -3692, -3742, -3792, -3843, -3893, -3943, -3993,
-	-4043, -4093, -4144, -4194, -4244, -4294, -4344, -4394,
-	-4445, -4495, -4545, -4595, -4645, -4695, -4745, -4796,
-	-4846, -4896, -4946, -4996, -5046, -5096, -5146, -5197,
-	-5247, -5297, -5347, -5397, -5447, -5497, -5547, -5597,
-	-5647, -5697, -5748, -5798, -5848, -5898, -5948, -5998,
-	-6048, -6098, -6148, -6198, -6248, -6298, -6348, -6398,
-	-6448, -6498, -6548, -6598, -6648, -6698, -6748, -6798,
-	-6848, -6898, -6948, -6998, -7048, -7098, -7148, -7198,
-	-7248, -7298, -7348, -7398, -7448, -7498, -7548, -7598,
-	-7648, -7697, -7747, -7797, -7847, -7897, -7947, -7997,
-	-8047, -8097, -8147, -8196, -8246, -8296, -8346, -8396,
-	-8446, -8496, -8545, -8595, -8645, -8695, -8745, -8794,
-	-8844, -8894, -8944, -8994, -9043, -9093, -9143, -9193,
-	-9243, -9292, -9342, -9392, -9442, -9491, -9541, -9591,
-	-9640, -9690, -9740, -9790, -9839, -9889, -9939, -9988,
-	-10038, -10088, -10137, -10187, -10237, -10286, -10336, -10386,
-	-10435, -10485, -10534, -10584, -10634, -10683, -10733, -10782,
-	-10832, -10882, -10931, -10981, -11030, -11080, -11129, -11179,
-	-11228, -11278, -11327, -11377, -11426, -11476, -11525, -11575,
-	-11624, -11674, -11723, -11773, -11822, -11872, -11921, -11970,
-	-12020, -12069, -12119, -12168, -12218, -12267, -12316, -12366,
-	-12415, -12464, -12514, -12563, -12612, -12662, -12711, -12760,
-	-12810, -12859, -12908, -12957, -13007, -13056, -13105, -13154,
-	-13204, -13253, -13302, -13351, -13401, -13450, -13499, -13548,
-	-13597, -13647, -13696, -13745, -13794, -13843, -13892, -13941,
-	-13990, -14040, -14089, -14138, -14187, -14236, -14285, -14334,
-	-14383, -14432, -14481, -14530, -14579, -14628, -14677, -14726,
-	-14775, -14824, -14873, -14922, -14971, -15020, -15069, -15118,
-	-15167, -15215, -15264, -15313, -15362, -15411, -15460, -15509,
-	-15557, -15606, -15655, -15704, -15753, -15802, -15850, -15899,
-	-15948, -15997, -16045, -16094, -16143, -16191, -16240, -16289,
-	-16338, -16386, -16435, -16484, -16532, -16581, -16629, -16678,
-	-16727, -16775, -16824, -16872, -16921, -16970, -17018, -17067,
-	-17115, -17164, -17212, -17261, -17309, -17358, -17406, -17455,
-	-17503, -17551, -17600, -17648, -17697, -17745, -17793, -17842,
-	-17890, -17939, -17987, -18035, -18084, -18132, -18180, -18228,
-	-18277, -18325, -18373, -18421, -18470, -18518, -18566, -18614,
-	-18663, -18711, -18759, -18807, -18855, -18903, -18951, -19000,
-	-19048, -19096, -19144, -19192, -19240, -19288, -19336, -19384,
-	-19432, -19480, -19528, -19576, -19624, -19672, -19720, -19768,
-	-19816, -19864, -19912, -19959, -20007, -20055, -20103, -20151,
-	-20199, -20246, -20294, -20342, -20390, -20438, -20485, -20533,
-	-20581, -20629, -20676, -20724, -20772, -20819, -20867, -20915,
-	-20962, -21010, -21057, -21105, -21153, -21200, -21248, -21295,
-	-21343, -21390, -21438, -21485, -21533, -21580, -21628, -21675,
-	-21723, -21770, -21817, -21865, -21912, -21960, -22007, -22054,
-	-22102, -22149, -22196, -22243, -22291, -22338, -22385, -22433,
-	-22480, -22527, -22574, -22621, -22668, -22716, -22763, -22810,
-	-22857, -22904, -22951, -22998, -23045, -23092, -23139, -23186,
-	-23233, -23280, -23327, -23374, -23421, -23468, -23515, -23562,
-	-23609, -23656, -23703, -23750, -23796, -23843, -23890, -23937,
-	-23984, -24030, -24077, -24124, -24171, -24217, -24264, -24311,
-	-24357, -24404, -24451, -24497, -24544, -24591, -24637, -24684,
-	-24730, -24777, -24823, -24870, -24916, -24963, -25009, -25056,
-	-25102, -25149, -25195, -25241, -25288, -25334, -25381, -25427,
-	-25473, -25520, -25566, -25612, -25658, -25705, -25751, -25797,
-	-25843, -25889, -25936, -25982, -26028, -26074, -26120, -26166,
-	-26212, -26258, -26304, -26350, -26396, -26442, -26488, -26534,
-	-26580, -26626, -26672, -26718, -26764, -26810, -26856, -26902,
-	-26947, -26993, -27039, -27085, -27131, -27176, -27222, -27268,
-	-27313, -27359, -27405, -27450, -27496, -27542, -27587, -27633,
-	-27678, -27724, -27770, -27815, -27861, -27906, -27952, -27997,
-	-28042, -28088, -28133, -28179, -28224, -28269, -28315, -28360,
-	-28405, -28451, -28496, -28541, -28586, -28632, -28677, -28722,
-	-28767, -28812, -28858, -28903, -28948, -28993, -29038, -29083,
-	-29128, -29173, -29218, -29263, -29308, -29353, -29398, -29443,
-	-29488, -29533, -29577, -29622, -29667, -29712, -29757, -29801,
-	-29846, -29891, -29936, -29980, -30025, -30070, -30114, -30159,
-	-30204, -30248, -30293, -30337, -30382, -30426, -30471, -30515,
-	-30560, -30604, -30649, -30693, -30738, -30782, -30826, -30871,
-	-30915, -30959, -31004, -31048, -31092, -31136, -31181, -31225,
-	-31269, -31313, -31357, -31402, -31446, -31490, -31534, -31578,
-	-31622, -31666, -31710, -31754, -31798, -31842, -31886, -31930,
-	-31974, -32017, -32061, -32105, -32149, -32193, -32236, -32280,
-	-32324, -32368, -32411, -32455, -32499, -32542, -32586, -32630,
-	-32673, -32717, -32760, -32804, -32847, -32891, -32934, -32978,
-	-33021, -33065, -33108, -33151, -33195, -33238, -33281, -33325,
-	-33368, -33411, -33454, -33498, -33541, -33584, -33627, -33670,
-	-33713, -33756, -33799, -33843, -33886, -33929, -33972, -34015,
-	-34057, -34100, -34143, -34186, -34229, -34272, -34315, -34358,
-	-34400, -34443, -34486, -34529, -34571, -34614, -34657, -34699,
-	-34742, -34785, -34827, -34870, -34912, -34955, -34997, -35040,
-	-35082, -35125, -35167, -35210, -35252, -35294, -35337, -35379,
-	-35421, -35464, -35506, -35548, -35590, -35633, -35675, -35717,
-	-35759, -35801, -35843, -35885, -35927, -35969, -36011, -36053,
-	-36095, -36137, -36179, -36221, -36263, -36305, -36347, -36388,
-	-36430, -36472, -36514, -36555, -36597, -36639, -36681, -36722,
-	-36764, -36805, -36847, -36889, -36930, -36972, -37013, -37055,
-	-37096, -37137, -37179, -37220, -37262, -37303, -37344, -37386,
-	-37427, -37468, -37509, -37551, -37592, -37633, -37674, -37715,
-	-37756, -37797, -37838, -37879, -37920, -37961, -38002, -38043,
-	-38084, -38125, -38166, -38207, -38248, -38288, -38329, -38370,
-	-38411, -38451, -38492, -38533, -38573, -38614, -38655, -38695,
-	-38736, -38776, -38817, -38857, -38898, -38938, -38979, -39019,
-	-39059, -39100, -39140, -39180, -39221, -39261, -39301, -39341,
-	-39382, -39422, -39462, -39502, -39542, -39582, -39622, -39662,
-	-39702, -39742, -39782, -39822, -39862, -39902, -39942, -39982,
-	-40021, -40061, -40101, -40141, -40180, -40220, -40260, -40299,
-	-40339, -40379, -40418, -40458, -40497, -40537, -40576, -40616,
-	-40655, -40695, -40734, -40773, -40813, -40852, -40891, -40931,
-	-40970, -41009, -41048, -41087, -41127, -41166, -41205, -41244,
-	-41283, -41322, -41361, -41400, -41439, -41478, -41517, -41556,
-	-41595, -41633, -41672, -41711, -41750, -41788, -41827, -41866,
-	-41904, -41943, -41982, -42020, -42059, -42097, -42136, -42174,
-	-42213, -42251, -42290, -42328, -42366, -42405, -42443, -42481,
-	-42520, -42558, -42596, -42634, -42672, -42711, -42749, -42787,
-	-42825, -42863, -42901, -42939, -42977, -43015, -43053, -43091,
-	-43128, -43166, -43204, -43242, -43280, -43317, -43355, -43393,
-	-43430, -43468, -43506, -43543, -43581, -43618, -43656, -43693,
-	-43731, -43768, -43806, -43843, -43880, -43918, -43955, -43992,
-	-44029, -44067, -44104, -44141, -44178, -44215, -44252, -44289,
-	-44326, -44363, -44400, -44437, -44474, -44511, -44548, -44585,
-	-44622, -44659, -44695, -44732, -44769, -44806, -44842, -44879,
-	-44915, -44952, -44989, -45025, -45062, -45098, -45135, -45171,
-	-45207, -45244, -45280, -45316, -45353, -45389, -45425, -45462,
-	-45498, -45534, -45570, -45606, -45642, -45678, -45714, -45750,
-	-45786, -45822, -45858, -45894, -45930, -45966, -46002, -46037,
-	-46073, -46109, -46145, -46180, -46216, -46252, -46287, -46323,
-	-46358, -46394, -46429, -46465, -46500, -46536, -46571, -46606,
-	-46642, -46677, -46712, -46747, -46783, -46818, -46853, -46888,
-	-46923, -46958, -46993, -47028, -47063, -47098, -47133, -47168,
-	-47203, -47238, -47273, -47308, -47342, -47377, -47412, -47446,
-	-47481, -47516, -47550, -47585, -47619, -47654, -47688, -47723,
-	-47757, -47792, -47826, -47860, -47895, -47929, -47963, -47998,
-	-48032, -48066, -48100, -48134, -48168, -48202, -48236, -48271,
-	-48304, -48338, -48372, -48406, -48440, -48474, -48508, -48542,
-	-48575, -48609, -48643, -48676, -48710, -48744, -48777, -48811,
-	-48844, -48878, -48911, -48945, -48978, -49012, -49045, -49078,
-	-49112, -49145, -49178, -49211, -49244, -49278, -49311, -49344,
-	-49377, -49410, -49443, -49476, -49509, -49542, -49575, -49608,
-	-49640, -49673, -49706, -49739, -49771, -49804, -49837, -49869,
-	-49902, -49935, -49967, -50000, -50032, -50065, -50097, -50129,
-	-50162, -50194, -50226, -50259, -50291, -50323, -50355, -50387,
-	-50420, -50452, -50484, -50516, -50548, -50580, -50612, -50644,
-	-50675, -50707, -50739, -50771, -50803, -50834, -50866, -50898,
-	-50929, -50961, -50993, -51024, -51056, -51087, -51119, -51150,
-	-51182, -51213, -51244, -51276, -51307, -51338, -51369, -51401,
-	-51432, -51463, -51494, -51525, -51556, -51587, -51618, -51649,
-	-51680, -51711, -51742, -51773, -51803, -51834, -51865, -51896,
-	-51926, -51957, -51988, -52018, -52049, -52079, -52110, -52140,
-	-52171, -52201, -52231, -52262, -52292, -52322, -52353, -52383,
-	-52413, -52443, -52473, -52503, -52534, -52564, -52594, -52624,
-	-52653, -52683, -52713, -52743, -52773, -52803, -52832, -52862,
-	-52892, -52922, -52951, -52981, -53010, -53040, -53069, -53099,
-	-53128, -53158, -53187, -53216, -53246, -53275, -53304, -53334,
-	-53363, -53392, -53421, -53450, -53479, -53508, -53537, -53566,
-	-53595, -53624, -53653, -53682, -53711, -53739, -53768, -53797,
-	-53826, -53854, -53883, -53911, -53940, -53969, -53997, -54026,
-	-54054, -54082, -54111, -54139, -54167, -54196, -54224, -54252,
-	-54280, -54308, -54337, -54365, -54393, -54421, -54449, -54477,
-	-54505, -54533, -54560, -54588, -54616, -54644, -54672, -54699,
-	-54727, -54755, -54782, -54810, -54837, -54865, -54892, -54920,
-	-54947, -54974, -55002, -55029, -55056, -55084, -55111, -55138,
-	-55165, -55192, -55219, -55246, -55274, -55300, -55327, -55354,
-	-55381, -55408, -55435, -55462, -55489, -55515, -55542, -55569,
-	-55595, -55622, -55648, -55675, -55701, -55728, -55754, -55781,
-	-55807, -55833, -55860, -55886, -55912, -55938, -55965, -55991,
-	-56017, -56043, -56069, -56095, -56121, -56147, -56173, -56199,
-	-56225, -56250, -56276, -56302, -56328, -56353, -56379, -56404,
-	-56430, -56456, -56481, -56507, -56532, -56557, -56583, -56608,
-	-56633, -56659, -56684, -56709, -56734, -56760, -56785, -56810,
-	-56835, -56860, -56885, -56910, -56935, -56959, -56984, -57009,
-	-57034, -57059, -57083, -57108, -57133, -57157, -57182, -57206,
-	-57231, -57255, -57280, -57304, -57329, -57353, -57377, -57402,
-	-57426, -57450, -57474, -57498, -57522, -57546, -57570, -57594,
-	-57618, -57642, -57666, -57690, -57714, -57738, -57762, -57785,
-	-57809, -57833, -57856, -57880, -57903, -57927, -57950, -57974,
-	-57997, -58021, -58044, -58067, -58091, -58114, -58137, -58160,
-	-58183, -58207, -58230, -58253, -58276, -58299, -58322, -58345,
-	-58367, -58390, -58413, -58436, -58459, -58481, -58504, -58527,
-	-58549, -58572, -58594, -58617, -58639, -58662, -58684, -58706,
-	-58729, -58751, -58773, -58795, -58818, -58840, -58862, -58884,
-	-58906, -58928, -58950, -58972, -58994, -59016, -59038, -59059,
-	-59081, -59103, -59125, -59146, -59168, -59190, -59211, -59233,
-	-59254, -59276, -59297, -59318, -59340, -59361, -59382, -59404,
-	-59425, -59446, -59467, -59488, -59509, -59530, -59551, -59572,
-	-59593, -59614, -59635, -59656, -59677, -59697, -59718, -59739,
-	-59759, -59780, -59801, -59821, -59842, -59862, -59883, -59903,
-	-59923, -59944, -59964, -59984, -60004, -60025, -60045, -60065,
-	-60085, -60105, -60125, -60145, -60165, -60185, -60205, -60225,
-	-60244, -60264, -60284, -60304, -60323, -60343, -60363, -60382,
-	-60402, -60421, -60441, -60460, -60479, -60499, -60518, -60537,
-	-60556, -60576, -60595, -60614, -60633, -60652, -60671, -60690,
-	-60709, -60728, -60747, -60766, -60785, -60803, -60822, -60841,
-	-60859, -60878, -60897, -60915, -60934, -60952, -60971, -60989,
-	-61007, -61026, -61044, -61062, -61081, -61099, -61117, -61135,
-	-61153, -61171, -61189, -61207, -61225, -61243, -61261, -61279,
-	-61297, -61314, -61332, -61350, -61367, -61385, -61403, -61420,
-	-61438, -61455, -61473, -61490, -61507, -61525, -61542, -61559,
-	-61577, -61594, -61611, -61628, -61645, -61662, -61679, -61696,
-	-61713, -61730, -61747, -61764, -61780, -61797, -61814, -61831,
-	-61847, -61864, -61880, -61897, -61913, -61930, -61946, -61963,
-	-61979, -61995, -62012, -62028, -62044, -62060, -62076, -62092,
-	-62108, -62125, -62141, -62156, -62172, -62188, -62204, -62220,
-	-62236, -62251, -62267, -62283, -62298, -62314, -62329, -62345,
-	-62360, -62376, -62391, -62407, -62422, -62437, -62453, -62468,
-	-62483, -62498, -62513, -62528, -62543, -62558, -62573, -62588,
-	-62603, -62618, -62633, -62648, -62662, -62677, -62692, -62706,
-	-62721, -62735, -62750, -62764, -62779, -62793, -62808, -62822,
-	-62836, -62850, -62865, -62879, -62893, -62907, -62921, -62935,
-	-62949, -62963, -62977, -62991, -63005, -63019, -63032, -63046,
-	-63060, -63074, -63087, -63101, -63114, -63128, -63141, -63155,
-	-63168, -63182, -63195, -63208, -63221, -63235, -63248, -63261,
-	-63274, -63287, -63300, -63313, -63326, -63339, -63352, -63365,
-	-63378, -63390, -63403, -63416, -63429, -63441, -63454, -63466,
-	-63479, -63491, -63504, -63516, -63528, -63541, -63553, -63565,
-	-63578, -63590, -63602, -63614, -63626, -63638, -63650, -63662,
-	-63674, -63686, -63698, -63709, -63721, -63733, -63745, -63756,
-	-63768, -63779, -63791, -63803, -63814, -63825, -63837, -63848,
-	-63859, -63871, -63882, -63893, -63904, -63915, -63927, -63938,
-	-63949, -63960, -63971, -63981, -63992, -64003, -64014, -64025,
-	-64035, -64046, -64057, -64067, -64078, -64088, -64099, -64109,
-	-64120, -64130, -64140, -64151, -64161, -64171, -64181, -64192,
-	-64202, -64212, -64222, -64232, -64242, -64252, -64261, -64271,
-	-64281, -64291, -64301, -64310, -64320, -64330, -64339, -64349,
-	-64358, -64368, -64377, -64387, -64396, -64405, -64414, -64424,
-	-64433, -64442, -64451, -64460, -64469, -64478, -64487, -64496,
-	-64505, -64514, -64523, -64532, -64540, -64549, -64558, -64566,
-	-64575, -64584, -64592, -64601, -64609, -64617, -64626, -64634,
-	-64642, -64651, -64659, -64667, -64675, -64683, -64691, -64699,
-	-64707, -64715, -64723, -64731, -64739, -64747, -64754, -64762,
-	-64770, -64777, -64785, -64793, -64800, -64808, -64815, -64822,
-	-64830, -64837, -64844, -64852, -64859, -64866, -64873, -64880,
-	-64887, -64895, -64902, -64908, -64915, -64922, -64929, -64936,
-	-64943, -64949, -64956, -64963, -64969, -64976, -64982, -64989,
-	-64995, -65002, -65008, -65015, -65021, -65027, -65033, -65040,
-	-65046, -65052, -65058, -65064, -65070, -65076, -65082, -65088,
-	-65094, -65099, -65105, -65111, -65117, -65122, -65128, -65133,
-	-65139, -65144, -65150, -65155, -65161, -65166, -65171, -65177,
-	-65182, -65187, -65192, -65197, -65202, -65207, -65212, -65217,
-	-65222, -65227, -65232, -65237, -65242, -65246, -65251, -65256,
-	-65260, -65265, -65270, -65274, -65279, -65283, -65287, -65292,
-	-65296, -65300, -65305, -65309, -65313, -65317, -65321, -65325,
-	-65329, -65333, -65337, -65341, -65345, -65349, -65352, -65356,
-	-65360, -65363, -65367, -65371, -65374, -65378, -65381, -65385,
-	-65388, -65391, -65395, -65398, -65401, -65404, -65408, -65411,
-	-65414, -65417, -65420, -65423, -65426, -65429, -65431, -65434,
-	-65437, -65440, -65442, -65445, -65448, -65450, -65453, -65455,
-	-65458, -65460, -65463, -65465, -65467, -65470, -65472, -65474,
-	-65476, -65478, -65480, -65482, -65484, -65486, -65488, -65490,
-	-65492, -65494, -65496, -65497, -65499, -65501, -65502, -65504,
-	-65505, -65507, -65508, -65510, -65511, -65513, -65514, -65515,
-	-65516, -65518, -65519, -65520, -65521, -65522, -65523, -65524,
-	-65525, -65526, -65527, -65527, -65528, -65529, -65530, -65530,
+	65536, 65535, 65535, 65535, 65535, 65535, 65535, 65535,
+	65534, 65534, 65534, 65533, 65533, 65532, 65532, 65531,
+	65531, 65530, 65529, 65529, 65528, 65527, 65526, 65525,
+	65524, 65523, 65522, 65521, 65520, 65519, 65518, 65517,
+	65516, 65515, 65513, 65512, 65511, 65509, 65508, 65506,
+	65505, 65503, 65501, 65500, 65498, 65496, 65495, 65493,
+	65491, 65489, 65487, 65485, 65483, 65481, 65479, 65477,
+	65475, 65473, 65471, 65468, 65466, 65464, 65461, 65459,
+	65457, 65454, 65452, 65449, 65446, 65444, 65441, 65438,
+	65436, 65433, 65430, 65427, 65424, 65421, 65418, 65415,
+	65412, 65409, 65406, 65403, 65400, 65396, 65393, 65390,
+	65386, 65383, 65379, 65376, 65372, 65369, 65365, 65362,
+	65358, 65354, 65350, 65347, 65343, 65339, 65335, 65331,
+	65327, 65323, 65319, 65315, 65311, 65307, 65302, 65298,
+	65294, 65290, 65285, 65281, 65276, 65272, 65267, 65263,
+	65258, 65253, 65249, 65244, 65239, 65235, 65230, 65225,
+	65220, 65215, 65210, 65205, 65200, 65195, 65190, 65184,
+	65179, 65174, 65169, 65163, 65158, 65153, 65147, 65142,
+	65136, 65131, 65125, 65119, 65114, 65108, 65102, 65096,
+	65091, 65085, 65079, 65073, 65067, 65061, 65055, 65049,
+	65043, 65036, 65030, 65024, 65018, 65011, 65005, 64999,
+	64992, 64986, 64979, 64973, 64966, 64959, 64953, 64946,
+	64939, 64933, 64926, 64919, 64912, 64905, 64898, 64891,
+	64884, 64877, 64870, 64863, 64855, 64848, 64841, 64834,
+	64826, 64819, 64811, 64804, 64796, 64789, 64781, 64774,
+	64766, 64758, 64751, 64743, 64735, 64727, 64719, 64711,
+	64703, 64695, 64687, 64679, 64671, 64663, 64655, 64646,
+	64638, 64630, 64622, 64613, 64605, 64596, 64588, 64579,
+	64571, 64562, 64553, 64545, 64536, 64527, 64518, 64510,
+	64501, 64492, 64483, 64474, 64465, 64456, 64447, 64437,
+	64428, 64419, 64410, 64401, 64391, 64382, 64372, 64363,
+	64353, 64344, 64334, 64325, 64315, 64305, 64296, 64286,
+	64276, 64266, 64257, 64247, 64237, 64227, 64217, 64207,
+	64197, 64186, 64176, 64166, 64156, 64146, 64135, 64125,
+	64115, 64104, 64094, 64083, 64073, 64062, 64051, 64041,
+	64030, 64019, 64009, 63998, 63987, 63976, 63965, 63954,
+	63943, 63932, 63921, 63910, 63899, 63888, 63876, 63865,
+	63854, 63842, 63831, 63820, 63808, 63797, 63785, 63774,
+	63762, 63750, 63739, 63727, 63715, 63704, 63692, 63680,
+	63668, 63656, 63644, 63632, 63620, 63608, 63596, 63584,
+	63571, 63559, 63547, 63535, 63522, 63510, 63498, 63485,
+	63473, 63460, 63447, 63435, 63422, 63410, 63397, 63384,
+	63371, 63358, 63346, 63333, 63320, 63307, 63294, 63281,
+	63268, 63254, 63241, 63228, 63215, 63202, 63188, 63175,
+	63162, 63148, 63135, 63121, 63108, 63094, 63080, 63067,
+	63053, 63039, 63026, 63012, 62998, 62984, 62970, 62956,
+	62942, 62928, 62914, 62900, 62886, 62872, 62858, 62843,
+	62829, 62815, 62800, 62786, 62772, 62757, 62743, 62728,
+	62714, 62699, 62684, 62670, 62655, 62640, 62625, 62610,
+	62596, 62581, 62566, 62551, 62536, 62521, 62506, 62491,
+	62475, 62460, 62445, 62430, 62414, 62399, 62384, 62368,
+	62353, 62337, 62322, 62306, 62291, 62275, 62259, 62244,
+	62228, 62212, 62196, 62180, 62164, 62148, 62133, 62117,
+	62100, 62084, 62068, 62052, 62036, 62020, 62003, 61987,
+	61971, 61954, 61938, 61922, 61905, 61889, 61872, 61855,
+	61839, 61822, 61805, 61789, 61772, 61755, 61738, 61721,
+	61705, 61688, 61671, 61654, 61637, 61619, 61602, 61585,
+	61568, 61551, 61533, 61516, 61499, 61481, 61464, 61446,
+	61429, 61411, 61394, 61376, 61359, 61341, 61323, 61305,
+	61288, 61270, 61252, 61234, 61216, 61198, 61180, 61162,
+	61144, 61126, 61108, 61090, 61071, 61053, 61035, 61017,
+	60998, 60980, 60961, 60943, 60924, 60906, 60887, 60869,
+	60850, 60831, 60813, 60794, 60775, 60756, 60737, 60719,
+	60700, 60681, 60662, 60643, 60624, 60604, 60585, 60566,
+	60547, 60528, 60508, 60489, 60470, 60450, 60431, 60411,
+	60392, 60372, 60353, 60333, 60313, 60294, 60274, 60254,
+	60235, 60215, 60195, 60175, 60155, 60135, 60115, 60095,
+	60075, 60055, 60035, 60015, 59994, 59974, 59954, 59934,
+	59913, 59893, 59872, 59852, 59831, 59811, 59790, 59770,
+	59749, 59728, 59708, 59687, 59666, 59645, 59625, 59604,
+	59583, 59562, 59541, 59520, 59499, 59478, 59457, 59435,
+	59414, 59393, 59372, 59350, 59329, 59308, 59286, 59265,
+	59243, 59222, 59200, 59179, 59157, 59135, 59114, 59092,
+	59070, 59049, 59027, 59005, 58983, 58961, 58939, 58917,
+	58895, 58873, 58851, 58829, 58807, 58784, 58762, 58740,
+	58718, 58695, 58673, 58650, 58628, 58605, 58583, 58560,
+	58538, 58515, 58493, 58470, 58447, 58424, 58402, 58379,
+	58356, 58333, 58310, 58287, 58264, 58241, 58218, 58195,
+	58172, 58149, 58125, 58102, 58079, 58056, 58032, 58009,
+	57986, 57962, 57939, 57915, 57892, 57868, 57844, 57821,
+	57797, 57773, 57750, 57726, 57702, 57678, 57654, 57630,
+	57606, 57582, 57558, 57534, 57510, 57486, 57462, 57438,
+	57414, 57389, 57365, 57341, 57316, 57292, 57268, 57243,
+	57219, 57194, 57170, 57145, 57120, 57096, 57071, 57046,
+	57022, 56997, 56972, 56947, 56922, 56897, 56872, 56847,
+	56822, 56797, 56772, 56747, 56722, 56697, 56671, 56646,
+	56621, 56595, 56570, 56545, 56519, 56494, 56468, 56443,
+	56417, 56392, 56366, 56340, 56315, 56289, 56263, 56237,
+	56212, 56186, 56160, 56134, 56108, 56082, 56056, 56030,
+	56004, 55978, 55952, 55925, 55899, 55873, 55847, 55820,
+	55794, 55768, 55741, 55715, 55688, 55662, 55635, 55609,
+	55582, 55555, 55529, 55502, 55475, 55448, 55422, 55395,
+	55368, 55341, 55314, 55287, 55260, 55233, 55206, 55179,
+	55152, 55124, 55097, 55070, 55043, 55015, 54988, 54961,
+	54933, 54906, 54879, 54851, 54823, 54796, 54768, 54741,
+	54713, 54685, 54658, 54630, 54602, 54574, 54546, 54519,
+	54491, 54463, 54435, 54407, 54379, 54351, 54323, 54294,
+	54266, 54238, 54210, 54182, 54153, 54125, 54097, 54068,
+	54040, 54011, 53983, 53954, 53926, 53897, 53869, 53840,
+	53811, 53783, 53754, 53725, 53696, 53667, 53639, 53610,
+	53581, 53552, 53523, 53494, 53465, 53436, 53407, 53377,
+	53348, 53319, 53290, 53260, 53231, 53202, 53172, 53143,
+	53114, 53084, 53055, 53025, 52996, 52966, 52936, 52907,
+	52877, 52847, 52818, 52788, 52758, 52728, 52698, 52668,
+	52639, 52609, 52579, 52549, 52518, 52488, 52458, 52428,
+	52398, 52368, 52338, 52307, 52277, 52247, 52216, 52186,
+	52155, 52125, 52095, 52064, 52033, 52003, 51972, 51942,
+	51911, 51880, 51850, 51819, 51788, 51757, 51726, 51695,
+	51665, 51634, 51603, 51572, 51541, 51510, 51478, 51447,
+	51416, 51385, 51354, 51323, 51291, 51260, 51229, 51197,
+	51166, 51134, 51103, 51072, 51040, 51008, 50977, 50945,
+	50914, 50882, 50850, 50819, 50787, 50755, 50723, 50691,
+	50660, 50628, 50596, 50564, 50532, 50500, 50468, 50436,
+	50403, 50371, 50339, 50307, 50275, 50242, 50210, 50178,
+	50146, 50113, 50081, 50048, 50016, 49983, 49951, 49918,
+	49886, 49853, 49820, 49788, 49755, 49722, 49690, 49657,
+	49624, 49591, 49558, 49525, 49492, 49459, 49426, 49393,
+	49360, 49327, 49294, 49261, 49228, 49195, 49161, 49128,
+	49095, 49062, 49028, 48995, 48961, 48928, 48895, 48861,
+	48828, 48794, 48760, 48727, 48693, 48660, 48626, 48592,
+	48558, 48525, 48491, 48457, 48423, 48389, 48355, 48321,
+	48288, 48254, 48219, 48185, 48151, 48117, 48083, 48049,
+	48015, 47981, 47946, 47912, 47878, 47843, 47809, 47775,
+	47740, 47706, 47671, 47637, 47602, 47568, 47533, 47498,
+	47464, 47429, 47394, 47360, 47325, 47290, 47255, 47220,
+	47186, 47151, 47116, 47081, 47046, 47011, 46976, 46941,
+	46906, 46871, 46835, 46800, 46765, 46730, 46695, 46659,
+	46624, 46589, 46553, 46518, 46482, 46447, 46411, 46376,
+	46340, 46305, 46269, 46234, 46198, 46162, 46127, 46091,
+	46055, 46019, 45984, 45948, 45912, 45876, 45840, 45804,
+	45768, 45732, 45696, 45660, 45624, 45588, 45552, 45516,
+	45480, 45443, 45407, 45371, 45335, 45298, 45262, 45226,
+	45189, 45153, 45116, 45080, 45043, 45007, 44970, 44934,
+	44897, 44861, 44824, 44787, 44750, 44714, 44677, 44640,
+	44603, 44567, 44530, 44493, 44456, 44419, 44382, 44345,
+	44308, 44271, 44234, 44197, 44160, 44122, 44085, 44048,
+	44011, 43974, 43936, 43899, 43862, 43824, 43787, 43749,
+	43712, 43675, 43637, 43600, 43562, 43524, 43487, 43449,
+	43412, 43374, 43336, 43298, 43261, 43223, 43185, 43147,
+	43110, 43072, 43034, 42996, 42958, 42920, 42882, 42844,
+	42806, 42768, 42730, 42692, 42653, 42615, 42577, 42539,
+	42501, 42462, 42424, 42386, 42347, 42309, 42271, 42232,
+	42194, 42155, 42117, 42078, 42040, 42001, 41962, 41924,
+	41885, 41846, 41808, 41769, 41730, 41692, 41653, 41614,
+	41575, 41536, 41497, 41458, 41419, 41381, 41342, 41303,
+	41263, 41224, 41185, 41146, 41107, 41068, 41029, 40990,
+	40950, 40911, 40872, 40832, 40793, 40754, 40714, 40675,
+	40636, 40596, 40557, 40517, 40478, 40438, 40399, 40359,
+	40319, 40280, 40240, 40200, 40161, 40121, 40081, 40041,
+	40002, 39962, 39922, 39882, 39842, 39802, 39762, 39722,
+	39682, 39642, 39602, 39562, 39522, 39482, 39442, 39402,
+	39362, 39321, 39281, 39241, 39201, 39160, 39120, 39080,
+	39039, 38999, 38958, 38918, 38878, 38837, 38797, 38756,
+	38716, 38675, 38634, 38594, 38553, 38512, 38472, 38431,
+	38390, 38350, 38309, 38268, 38227, 38186, 38146, 38105,
+	38064, 38023, 37982, 37941, 37900, 37859, 37818, 37777,
+	37736, 37695, 37653, 37612, 37571, 37530, 37489, 37447,
+	37406, 37365, 37324, 37282, 37241, 37200, 37158, 37117,
+	37075, 37034, 36992, 36951, 36909, 36868, 36826, 36785,
+	36743, 36701, 36660, 36618, 36576, 36535, 36493, 36451,
+	36409, 36368, 36326, 36284, 36242, 36200, 36158, 36116,
+	36074, 36032, 35990, 35948, 35906, 35864, 35822, 35780,
+	35738, 35696, 35654, 35611, 35569, 35527, 35485, 35442,
+	35400, 35358, 35316, 35273, 35231, 35188, 35146, 35104,
+	35061, 35019, 34976, 34934, 34891, 34849, 34806, 34763,
+	34721, 34678, 34635, 34593, 34550, 34507, 34465, 34422,
+	34379, 34336, 34293, 34251, 34208, 34165, 34122, 34079,
+	34036, 33993, 33950, 33907, 33864, 33821, 33778, 33735,
+	33692, 33649, 33605, 33562, 33519, 33476, 33433, 33389,
+	33346, 33303, 33260, 33216, 33173, 33130, 33086, 33043,
+	32999, 32956, 32912, 32869, 32826, 32782, 32738, 32695,
+	32651, 32608, 32564, 32521, 32477, 32433, 32390, 32346,
+	32302, 32258, 32215, 32171, 32127, 32083, 32039, 31995,
+	31952, 31908, 31864, 31820, 31776, 31732, 31688, 31644,
+	31600, 31556, 31512, 31468, 31424, 31379, 31335, 31291,
+	31247, 31203, 31159, 31114, 31070, 31026, 30982, 30937,
+	30893, 30849, 30804, 30760, 30715, 30671, 30627, 30582,
+	30538, 30493, 30449, 30404, 30360, 30315, 30271, 30226,
+	30181, 30137, 30092, 30047, 30003, 29958, 29913, 29869,
+	29824, 29779, 29734, 29690, 29645, 29600, 29555, 29510,
+	29465, 29420, 29375, 29330, 29285, 29241, 29196, 29151,
+	29105, 29060, 29015, 28970, 28925, 28880, 28835, 28790,
+	28745, 28699, 28654, 28609, 28564, 28519, 28473, 28428,
+	28383, 28337, 28292, 28247, 28201, 28156, 28111, 28065,
+	28020, 27974, 27929, 27883, 27838, 27792, 27747, 27701,
+	27656, 27610, 27565, 27519, 27473, 27428, 27382, 27336,
+	27291, 27245, 27199, 27153, 27108, 27062, 27016, 26970,
+	26925, 26879, 26833, 26787, 26741, 26695, 26649, 26603,
+	26557, 26511, 26465, 26419, 26373, 26327, 26281, 26235,
+	26189, 26143, 26097, 26051, 26005, 25959, 25913, 25866,
+	25820, 25774, 25728, 25681, 25635, 25589, 25543, 25496,
+	25450, 25404, 25357, 25311, 25265, 25218, 25172, 25125,
+	25079, 25033, 24986, 24940, 24893, 24847, 24800, 24754,
+	24707, 24660, 24614, 24567, 24521, 24474, 24427, 24381,
+	24334, 24287, 24241, 24194, 24147, 24101, 24054, 24007,
+	23960, 23914, 23867, 23820, 23773, 23726, 23679, 23632,
+	23586, 23539, 23492, 23445, 23398, 23351, 23304, 23257,
+	23210, 23163, 23116, 23069, 23022, 22975, 22928, 22881,
+	22833, 22786, 22739, 22692, 22645, 22598, 22551, 22503,
+	22456, 22409, 22362, 22314, 22267, 22220, 22173, 22125,
+	22078, 22031, 21983, 21936, 21889, 21841, 21794, 21746,
+	21699, 21651, 21604, 21557, 21509, 21462, 21414, 21367,
+	21319, 21271, 21224, 21176, 21129, 21081, 21034, 20986,
+	20938, 20891, 20843, 20795, 20748, 20700, 20652, 20605,
+	20557, 20509, 20461, 20414, 20366, 20318, 20270, 20223,
+	20175, 20127, 20079, 20031, 19983, 19935, 19888, 19840,
+	19792, 19744, 19696, 19648, 19600, 19552, 19504, 19456,
+	19408, 19360, 19312, 19264, 19216, 19168, 19120, 19072,
+	19024, 18975, 18927, 18879, 18831, 18783, 18735, 18687,
+	18638, 18590, 18542, 18494, 18446, 18397, 18349, 18301,
+	18253, 18204, 18156, 18108, 18059, 18011, 17963, 17914,
+	17866, 17818, 17769, 17721, 17672, 17624, 17576, 17527,
+	17479, 17430, 17382, 17333, 17285, 17236, 17188, 17139,
+	17091, 17042, 16994, 16945, 16897, 16848, 16800, 16751,
+	16702, 16654, 16605, 16557, 16508, 16459, 16411, 16362,
+	16313, 16265, 16216, 16167, 16118, 16070, 16021, 15972,
+	15923, 15875, 15826, 15777, 15728, 15680, 15631, 15582,
+	15533, 15484, 15435, 15387, 15338, 15289, 15240, 15191,
+	15142, 15093, 15044, 14995, 14946, 14897, 14849, 14800,
+	14751, 14702, 14653, 14604, 14555, 14506, 14457, 14408,
+	14359, 14309, 14260, 14211, 14162, 14113, 14064, 14015,
+	13966, 13917, 13868, 13819, 13769, 13720, 13671, 13622,
+	13573, 13524, 13474, 13425, 13376, 13327, 13278, 13228,
+	13179, 13130, 13081, 13031, 12982, 12933, 12884, 12834,
+	12785, 12736, 12686, 12637, 12588, 12538, 12489, 12440,
+	12390, 12341, 12292, 12242, 12193, 12143, 12094, 12045,
+	11995, 11946, 11896, 11847, 11797, 11748, 11699, 11649,
+	11600, 11550, 11501, 11451, 11402, 11352, 11303, 11253,
+	11204, 11154, 11105, 11055, 11006, 10956, 10906, 10857,
+	10807, 10758, 10708, 10658, 10609, 10559, 10510, 10460,
+	10410, 10361, 10311, 10262, 10212, 10162, 10113, 10063,
+	10013, 9964, 9914, 9864, 9814, 9765, 9715, 9665,
+	9616, 9566, 9516, 9466, 9417, 9367, 9317, 9267,
+	9218, 9168, 9118, 9068, 9019, 8969, 8919, 8869,
+	8819, 8770, 8720, 8670, 8620, 8570, 8520, 8471,
+	8421, 8371, 8321, 8271, 8221, 8171, 8122, 8072,
+	8022, 7972, 7922, 7872, 7822, 7772, 7722, 7672,
+	7623, 7573, 7523, 7473, 7423, 7373, 7323, 7273,
+	7223, 7173, 7123, 7073, 7023, 6973, 6923, 6873,
+	6823, 6773, 6723, 6673, 6623, 6573, 6523, 6473,
+	6423, 6373, 6323, 6273, 6223, 6173, 6123, 6073,
+	6023, 5973, 5923, 5873, 5823, 5773, 5722, 5672,
+	5622, 5572, 5522, 5472, 5422, 5372, 5322, 5272,
+	5222, 5171, 5121, 5071, 5021, 4971, 4921, 4871,
+	4821, 4770, 4720, 4670, 4620, 4570, 4520, 4470,
+	4420, 4369, 4319, 4269, 4219, 4169, 4119, 4068,
+	4018, 3968, 3918, 3868, 3818, 3767, 3717, 3667,
+	3617, 3567, 3516, 3466, 3416, 3366, 3316, 3265,
+	3215, 3165, 3115, 3065, 3014, 2964, 2914, 2864,
+	2814, 2763, 2713, 2663, 2613, 2562, 2512, 2462,
+	2412, 2361, 2311, 2261, 2211, 2161, 2110, 2060,
+	2010, 1960, 1909, 1859, 1809, 1759, 1708, 1658,
+	1608, 1558, 1507, 1457, 1407, 1357, 1306, 1256,
+	1206, 1156, 1105, 1055, 1005, 955, 904, 854,
+	804, 753, 703, 653, 603, 552, 502, 452,
+	402, 351, 301, 251, 201, 150, 100, 50,
+	0, -50, -100, -150, -201, -251, -301, -351,
+	-402, -452, -502, -552, -603, -653, -703, -753,
+	-804, -854, -904, -955, -1005, -1055, -1105, -1156,
+	-1206, -1256, -1306, -1357, -1407, -1457, -1507, -1558,
+	-1608, -1658, -1708, -1759, -1809, -1859, -1909, -1960,
+	-2010, -2060, -2110, -2161, -2211, -2261, -2311, -2361,
+	-2412, -2462, -2512, -2562, -2613, -2663, -2713, -2763,
+	-2814, -2864, -2914, -2964, -3014, -3065, -3115, -3165,
+	-3215, -3265, -3316, -3366, -3416, -3466, -3516, -3567,
+	-3617, -3667, -3717, -3767, -3818, -3868, -3918, -3968,
+	-4018, -4068, -4119, -4169, -4219, -4269, -4319, -4369,
+	-4420, -4470, -4520, -4570, -4620, -4670, -4720, -4770,
+	-4821, -4871, -4921, -4971, -5021, -5071, -5121, -5171,
+	-5222, -5272, -5322, -5372, -5422, -5472, -5522, -5572,
+	-5622, -5672, -5722, -5773, -5823, -5873, -5923, -5973,
+	-6023, -6073, -6123, -6173, -6223, -6273, -6323, -6373,
+	-6423, -6473, -6523, -6573, -6623, -6673, -6723, -6773,
+	-6823, -6873, -6923, -6973, -7023, -7073, -7123, -7173,
+	-7223, -7273, -7323, -7373, -7423, -7473, -7523, -7573,
+	-7623, -7672, -7722, -7772, -7822, -7872, -7922, -7972,
+	-8022, -8072, -8122, -8171, -8221, -8271, -8321, -8371,
+	-8421, -8471, -8520, -8570, -8620, -8670, -8720, -8770,
+	-8819, -8869, -8919, -8969, -9019, -9068, -9118, -9168,
+	-9218, -9267, -9317, -9367, -9417, -9466, -9516, -9566,
+	-9616, -9665, -9715, -9765, -9814, -9864, -9914, -9964,
+	-10013, -10063, -10113, -10162, -10212, -10262, -10311, -10361,
+	-10410, -10460, -10510, -10559, -10609, -10658, -10708, -10758,
+	-10807, -10857, -10906, -10956, -11006, -11055, -11105, -11154,
+	-11204, -11253, -11303, -11352, -11402, -11451, -11501, -11550,
+	-11600, -11649, -11699, -11748, -11797, -11847, -11896, -11946,
+	-11995, -12045, -12094, -12143, -12193, -12242, -12292, -12341,
+	-12390, -12440, -12489, -12538, -12588, -12637, -12686, -12736,
+	-12785, -12834, -12884, -12933, -12982, -13031, -13081, -13130,
+	-13179, -13228, -13278, -13327, -13376, -13425, -13474, -13524,
+	-13573, -13622, -13671, -13720, -13769, -13819, -13868, -13917,
+	-13966, -14015, -14064, -14113, -14162, -14211, -14260, -14309,
+	-14359, -14408, -14457, -14506, -14555, -14604, -14653, -14702,
+	-14751, -14800, -14849, -14897, -14946, -14995, -15044, -15093,
+	-15142, -15191, -15240, -15289, -15338, -15387, -15435, -15484,
+	-15533, -15582, -15631, -15680, -15728, -15777, -15826, -15875,
+	-15923, -15972, -16021, -16070, -16118, -16167, -16216, -16265,
+	-16313, -16362, -16411, -16459, -16508, -16557, -16605, -16654,
+	-16702, -16751, -16800, -16848, -16897, -16945, -16994, -17042,
+	-17091, -17139, -17188, -17236, -17285, -17333, -17382, -17430,
+	-17479, -17527, -17576, -17624, -17672, -17721, -17769, -17818,
+	-17866, -17914, -17963, -18011, -18059, -18108, -18156, -18204,
+	-18253, -18301, -18349, -18397, -18446, -18494, -18542, -18590,
+	-18638, -18687, -18735, -18783, -18831, -18879, -18927, -18975,
+	-19024, -19072, -19120, -19168, -19216, -19264, -19312, -19360,
+	-19408, -19456, -19504, -19552, -19600, -19648, -19696, -19744,
+	-19792, -19840, -19888, -19935, -19983, -20031, -20079, -20127,
+	-20175, -20223, -20270, -20318, -20366, -20414, -20461, -20509,
+	-20557, -20605, -20652, -20700, -20748, -20795, -20843, -20891,
+	-20938, -20986, -21034, -21081, -21129, -21176, -21224, -21271,
+	-21319, -21367, -21414, -21462, -21509, -21557, -21604, -21651,
+	-21699, -21746, -21794, -21841, -21889, -21936, -21983, -22031,
+	-22078, -22125, -22173, -22220, -22267, -22314, -22362, -22409,
+	-22456, -22503, -22551, -22598, -22645, -22692, -22739, -22786,
+	-22833, -22881, -22928, -22975, -23022, -23069, -23116, -23163,
+	-23210, -23257, -23304, -23351, -23398, -23445, -23492, -23539,
+	-23586, -23632, -23679, -23726, -23773, -23820, -23867, -23914,
+	-23960, -24007, -24054, -24101, -24147, -24194, -24241, -24287,
+	-24334, -24381, -24427, -24474, -24521, -24567, -24614, -24660,
+	-24707, -24754, -24800, -24847, -24893, -24940, -24986, -25033,
+	-25079, -25125, -25172, -25218, -25265, -25311, -25357, -25404,
+	-25450, -25496, -25543, -25589, -25635, -25681, -25728, -25774,
+	-25820, -25866, -25913, -25959, -26005, -26051, -26097, -26143,
+	-26189, -26235, -26281, -26327, -26373, -26419, -26465, -26511,
+	-26557, -26603, -26649, -26695, -26741, -26787, -26833, -26879,
+	-26925, -26970, -27016, -27062, -27108, -27153, -27199, -27245,
+	-27291, -27336, -27382, -27428, -27473, -27519, -27565, -27610,
+	-27656, -27701, -27747, -27792, -27838, -27883, -27929, -27974,
+	-28020, -28065, -28111, -28156, -28201, -28247, -28292, -28337,
+	-28383, -28428, -28473, -28519, -28564, -28609, -28654, -28699,
+	-28745, -28790, -28835, -28880, -28925, -28970, -29015, -29060,
+	-29105, -29151, -29196, -29241, -29285, -29330, -29375, -29420,
+	-29465, -29510, -29555, -29600, -29645, -29690, -29734, -29779,
+	-29824, -29869, -29913, -29958, -30003, -30047, -30092, -30137,
+	-30181, -30226, -30271, -30315, -30360, -30404, -30449, -30493,
+	-30538, -30582, -30627, -30671, -30715, -30760, -30804, -30849,
+	-30893, -30937, -30982, -31026, -31070, -31114, -31159, -31203,
+	-31247, -31291, -31335, -31379, -31424, -31468, -31512, -31556,
+	-31600, -31644, -31688, -31732, -31776, -31820, -31864, -31908,
+	-31952, -31995, -32039, -32083, -32127, -32171, -32215, -32258,
+	-32302, -32346, -32390, -32433, -32477, -32521, -32564, -32608,
+	-32651, -32695, -32738, -32782, -32826, -32869, -32912, -32956,
+	-32999, -33043, -33086, -33130, -33173, -33216, -33260, -33303,
+	-33346, -33389, -33433, -33476, -33519, -33562, -33605, -33649,
+	-33692, -33735, -33778, -33821, -33864, -33907, -33950, -33993,
+	-34036, -34079, -34122, -34165, -34208, -34251, -34293, -34336,
+	-34379, -34422, -34465, -34507, -34550, -34593, -34635, -34678,
+	-34721, -34763, -34806, -34849, -34891, -34934, -34976, -35019,
+	-35061, -35104, -35146, -35188, -35231, -35273, -35316, -35358,
+	-35400, -35442, -35485, -35527, -35569, -35611, -35654, -35696,
+	-35738, -35780, -35822, -35864, -35906, -35948, -35990, -36032,
+	-36074, -36116, -36158, -36200, -36242, -36284, -36326, -36368,
+	-36409, -36451, -36493, -36535, -36576, -36618, -36660, -36701,
+	-36743, -36785, -36826, -36868, -36909, -36951, -36992, -37034,
+	-37075, -37117, -37158, -37200, -37241, -37282, -37324, -37365,
+	-37406, -37447, -37489, -37530, -37571, -37612, -37653, -37695,
+	-37736, -37777, -37818, -37859, -37900, -37941, -37982, -38023,
+	-38064, -38105, -38146, -38186, -38227, -38268, -38309, -38350,
+	-38390, -38431, -38472, -38512, -38553, -38594, -38634, -38675,
+	-38716, -38756, -38797, -38837, -38878, -38918, -38958, -38999,
+	-39039, -39080, -39120, -39160, -39201, -39241, -39281, -39321,
+	-39362, -39402, -39442, -39482, -39522, -39562, -39602, -39642,
+	-39682, -39722, -39762, -39802, -39842, -39882, -39922, -39962,
+	-40002, -40041, -40081, -40121, -40161, -40200, -40240, -40280,
+	-40319, -40359, -40399, -40438, -40478, -40517, -40557, -40596,
+	-40636, -40675, -40714, -40754, -40793, -40832, -40872, -40911,
+	-40950, -40990, -41029, -41068, -41107, -41146, -41185, -41224,
+	-41263, -41303, -41342, -41381, -41419, -41458, -41497, -41536,
+	-41575, -41614, -41653, -41692, -41730, -41769, -41808, -41846,
+	-41885, -41924, -41962, -42001, -42040, -42078, -42117, -42155,
+	-42194, -42232, -42271, -42309, -42347, -42386, -42424, -42462,
+	-42501, -42539, -42577, -42615, -42653, -42692, -42730, -42768,
+	-42806, -42844, -42882, -42920, -42958, -42996, -43034, -43072,
+	-43110, -43147, -43185, -43223, -43261, -43298, -43336, -43374,
+	-43412, -43449, -43487, -43524, -43562, -43600, -43637, -43675,
+	-43712, -43749, -43787, -43824, -43862, -43899, -43936, -43974,
+	-44011, -44048, -44085, -44122, -44160, -44197, -44234, -44271,
+	-44308, -44345, -44382, -44419, -44456, -44493, -44530, -44567,
+	-44603, -44640, -44677, -44714, -44750, -44787, -44824, -44861,
+	-44897, -44934, -44970, -45007, -45043, -45080, -45116, -45153,
+	-45189, -45226, -45262, -45298, -45335, -45371, -45407, -45443,
+	-45480, -45516, -45552, -45588, -45624, -45660, -45696, -45732,
+	-45768, -45804, -45840, -45876, -45912, -45948, -45984, -46019,
+	-46055, -46091, -46127, -46162, -46198, -46234, -46269, -46305,
+	-46340, -46376, -46411, -46447, -46482, -46518, -46553, -46589,
+	-46624, -46659, -46695, -46730, -46765, -46800, -46835, -46871,
+	-46906, -46941, -46976, -47011, -47046, -47081, -47116, -47151,
+	-47186, -47220, -47255, -47290, -47325, -47360, -47394, -47429,
+	-47464, -47498, -47533, -47568, -47602, -47637, -47671, -47706,
+	-47740, -47775, -47809, -47843, -47878, -47912, -47946, -47981,
+	-48015, -48049, -48083, -48117, -48151, -48185, -48219, -48254,
+	-48288, -48321, -48355, -48389, -48423, -48457, -48491, -48525,
+	-48558, -48592, -48626, -48660, -48693, -48727, -48760, -48794,
+	-48828, -48861, -48895, -48928, -48961, -48995, -49028, -49062,
+	-49095, -49128, -49161, -49195, -49228, -49261, -49294, -49327,
+	-49360, -49393, -49426, -49459, -49492, -49525, -49558, -49591,
+	-49624, -49657, -49690, -49722, -49755, -49788, -49820, -49853,
+	-49886, -49918, -49951, -49983, -50016, -50048, -50081, -50113,
+	-50146, -50178, -50210, -50242, -50275, -50307, -50339, -50371,
+	-50403, -50436, -50468, -50500, -50532, -50564, -50596, -50628,
+	-50660, -50691, -50723, -50755, -50787, -50819, -50850, -50882,
+	-50914, -50945, -50977, -51008, -51040, -51072, -51103, -51134,
+	-51166, -51197, -51229, -51260, -51291, -51323, -51354, -51385,
+	-51416, -51447, -51478, -51510, -51541, -51572, -51603, -51634,
+	-51665, -51695, -51726, -51757, -51788, -51819, -51850, -51880,
+	-51911, -51942, -51972, -52003, -52033, -52064, -52095, -52125,
+	-52155, -52186, -52216, -52247, -52277, -52307, -52338, -52368,
+	-52398, -52428, -52458, -52488, -52518, -52549, -52579, -52609,
+	-52639, -52668, -52698, -52728, -52758, -52788, -52818, -52847,
+	-52877, -52907, -52936, -52966, -52996, -53025, -53055, -53084,
+	-53114, -53143, -53172, -53202, -53231, -53260, -53290, -53319,
+	-53348, -53377, -53407, -53436, -53465, -53494, -53523, -53552,
+	-53581, -53610, -53639, -53667, -53696, -53725, -53754, -53783,
+	-53811, -53840, -53869, -53897, -53926, -53954, -53983, -54011,
+	-54040, -54068, -54097, -54125, -54153, -54182, -54210, -54238,
+	-54266, -54294, -54323, -54351, -54379, -54407, -54435, -54463,
+	-54491, -54519, -54546, -54574, -54602, -54630, -54658, -54685,
+	-54713, -54741, -54768, -54796, -54823, -54851, -54879, -54906,
+	-54933, -54961, -54988, -55015, -55043, -55070, -55097, -55124,
+	-55152, -55179, -55206, -55233, -55260, -55287, -55314, -55341,
+	-55368, -55395, -55422, -55448, -55475, -55502, -55529, -55555,
+	-55582, -55609, -55635, -55662, -55688, -55715, -55741, -55768,
+	-55794, -55820, -55847, -55873, -55899, -55925, -55952, -55978,
+	-56004, -56030, -56056, -56082, -56108, -56134, -56160, -56186,
+	-56212, -56237, -56263, -56289, -56315, -56340, -56366, -56392,
+	-56417, -56443, -56468, -56494, -56519, -56545, -56570, -56595,
+	-56621, -56646, -56671, -56697, -56722, -56747, -56772, -56797,
+	-56822, -56847, -56872, -56897, -56922, -56947, -56972, -56997,
+	-57022, -57046, -57071, -57096, -57120, -57145, -57170, -57194,
+	-57219, -57243, -57268, -57292, -57316, -57341, -57365, -57389,
+	-57414, -57438, -57462, -57486, -57510, -57534, -57558, -57582,
+	-57606, -57630, -57654, -57678, -57702, -57726, -57750, -57773,
+	-57797, -57821, -57844, -57868, -57892, -57915, -57939, -57962,
+	-57986, -58009, -58032, -58056, -58079, -58102, -58125, -58149,
+	-58172, -58195, -58218, -58241, -58264, -58287, -58310, -58333,
+	-58356, -58379, -58402, -58424, -58447, -58470, -58493, -58515,
+	-58538, -58560, -58583, -58605, -58628, -58650, -58673, -58695,
+	-58718, -58740, -58762, -58784, -58807, -58829, -58851, -58873,
+	-58895, -58917, -58939, -58961, -58983, -59005, -59027, -59049,
+	-59070, -59092, -59114, -59135, -59157, -59179, -59200, -59222,
+	-59243, -59265, -59286, -59308, -59329, -59350, -59372, -59393,
+	-59414, -59435, -59457, -59478, -59499, -59520, -59541, -59562,
+	-59583, -59604, -59625, -59645, -59666, -59687, -59708, -59728,
+	-59749, -59770, -59790, -59811, -59831, -59852, -59872, -59893,
+	-59913, -59934, -59954, -59974, -59994, -60015, -60035, -60055,
+	-60075, -60095, -60115, -60135, -60155, -60175, -60195, -60215,
+	-60235, -60254, -60274, -60294, -60313, -60333, -60353, -60372,
+	-60392, -60411, -60431, -60450, -60470, -60489, -60508, -60528,
+	-60547, -60566, -60585, -60604, -60624, -60643, -60662, -60681,
+	-60700, -60719, -60737, -60756, -60775, -60794, -60813, -60831,
+	-60850, -60869, -60887, -60906, -60924, -60943, -60961, -60980,
+	-60998, -61017, -61035, -61053, -61071, -61090, -61108, -61126,
+	-61144, -61162, -61180, -61198, -61216, -61234, -61252, -61270,
+	-61288, -61305, -61323, -61341, -61359, -61376, -61394, -61411,
+	-61429, -61446, -61464, -61481, -61499, -61516, -61533, -61551,
+	-61568, -61585, -61602, -61619, -61637, -61654, -61671, -61688,
+	-61705, -61721, -61738, -61755, -61772, -61789, -61805, -61822,
+	-61839, -61855, -61872, -61889, -61905, -61922, -61938, -61954,
+	-61971, -61987, -62003, -62020, -62036, -62052, -62068, -62084,
+	-62100, -62117, -62133, -62148, -62164, -62180, -62196, -62212,
+	-62228, -62244, -62259, -62275, -62291, -62306, -62322, -62337,
+	-62353, -62368, -62384, -62399, -62414, -62430, -62445, -62460,
+	-62475, -62491, -62506, -62521, -62536, -62551, -62566, -62581,
+	-62596, -62610, -62625, -62640, -62655, -62670, -62684, -62699,
+	-62714, -62728, -62743, -62757, -62772, -62786, -62800, -62815,
+	-62829, -62843, -62858, -62872, -62886, -62900, -62914, -62928,
+	-62942, -62956, -62970, -62984, -62998, -63012, -63026, -63039,
+	-63053, -63067, -63080, -63094, -63108, -63121, -63135, -63148,
+	-63162, -63175, -63188, -63202, -63215, -63228, -63241, -63254,
+	-63268, -63281, -63294, -63307, -63320, -63333, -63346, -63358,
+	-63371, -63384, -63397, -63410, -63422, -63435, -63447, -63460,
+	-63473, -63485, -63498, -63510, -63522, -63535, -63547, -63559,
+	-63571, -63584, -63596, -63608, -63620, -63632, -63644, -63656,
+	-63668, -63680, -63692, -63704, -63715, -63727, -63739, -63750,
+	-63762, -63774, -63785, -63797, -63808, -63820, -63831, -63842,
+	-63854, -63865, -63876, -63888, -63899, -63910, -63921, -63932,
+	-63943, -63954, -63965, -63976, -63987, -63998, -64009, -64019,
+	-64030, -64041, -64051, -64062, -64073, -64083, -64094, -64104,
+	-64115, -64125, -64135, -64146, -64156, -64166, -64176, -64186,
+	-64197, -64207, -64217, -64227, -64237, -64247, -64257, -64266,
+	-64276, -64286, -64296, -64305, -64315, -64325, -64334, -64344,
+	-64353, -64363, -64372, -64382, -64391, -64401, -64410, -64419,
+	-64428, -64437, -64447, -64456, -64465, -64474, -64483, -64492,
+	-64501, -64510, -64518, -64527, -64536, -64545, -64553, -64562,
+	-64571, -64579, -64588, -64596, -64605, -64613, -64622, -64630,
+	-64638, -64646, -64655, -64663, -64671, -64679, -64687, -64695,
+	-64703, -64711, -64719, -64727, -64735, -64743, -64751, -64758,
+	-64766, -64774, -64781, -64789, -64796, -64804, -64811, -64819,
+	-64826, -64834, -64841, -64848, -64855, -64863, -64870, -64877,
+	-64884, -64891, -64898, -64905, -64912, -64919, -64926, -64933,
+	-64939, -64946, -64953, -64959, -64966, -64973, -64979, -64986,
+	-64992, -64999, -65005, -65011, -65018, -65024, -65030, -65036,
+	-65043, -65049, -65055, -65061, -65067, -65073, -65079, -65085,
+	-65091, -65096, -65102, -65108, -65114, -65119, -65125, -65131,
+	-65136, -65142, -65147, -65153, -65158, -65163, -65169, -65174,
+	-65179, -65184, -65190, -65195, -65200, -65205, -65210, -65215,
+	-65220, -65225, -65230, -65235, -65239, -65244, -65249, -65253,
+	-65258, -65263, -65267, -65272, -65276, -65281, -65285, -65290,
+	-65294, -65298, -65302, -65307, -65311, -65315, -65319, -65323,
+	-65327, -65331, -65335, -65339, -65343, -65347, -65350, -65354,
+	-65358, -65362, -65365, -65369, -65372, -65376, -65379, -65383,
+	-65386, -65390, -65393, -65396, -65400, -65403, -65406, -65409,
+	-65412, -65415, -65418, -65421, -65424, -65427, -65430, -65433,
+	-65436, -65438, -65441, -65444, -65446, -65449, -65452, -65454,
+	-65457, -65459, -65461, -65464, -65466, -65468, -65471, -65473,
+	-65475, -65477, -65479, -65481, -65483, -65485, -65487, -65489,
+	-65491, -65493, -65495, -65496, -65498, -65500, -65501, -65503,
+	-65505, -65506, -65508, -65509, -65511, -65512, -65513, -65515,
+	-65516, -65517, -65518, -65519, -65520, -65521, -65522, -65523,
+	-65524, -65525, -65526, -65527, -65528, -65529, -65529, -65530,
 	-65531, -65531, -65532, -65532, -65533, -65533, -65534, -65534,
 	-65534, -65535, -65535, -65535, -65535, -65535, -65535, -65535,
-	-65535, -65535, -65535, -65535, -65535, -65535, -65535, -65534,
-	-65534, -65534, -65533, -65533, -65532, -65532, -65531, -65531,
-	-65530, -65530, -65529, -65528, -65527, -65527, -65526, -65525,
-	-65524, -65523, -65522, -65521, -65520, -65519, -65518, -65516,
-	-65515, -65514, -65513, -65511, -65510, -65508, -65507, -65505,
-	-65504, -65502, -65501, -65499, -65497, -65496, -65494, -65492,
-	-65490, -65488, -65486, -65484, -65482, -65480, -65478, -65476,
-	-65474, -65472, -65470, -65467, -65465, -65463, -65460, -65458,
-	-65455, -65453, -65450, -65448, -65445, -65442, -65440, -65437,
-	-65434, -65431, -65429, -65426, -65423, -65420, -65417, -65414,
-	-65411, -65408, -65404, -65401, -65398, -65395, -65391, -65388,
-	-65385, -65381, -65378, -65374, -65371, -65367, -65363, -65360,
-	-65356, -65352, -65349, -65345, -65341, -65337, -65333, -65329,
-	-65325, -65321, -65317, -65313, -65309, -65305, -65300, -65296,
-	-65292, -65287, -65283, -65279, -65274, -65270, -65265, -65260,
-	-65256, -65251, -65246, -65242, -65237, -65232, -65227, -65222,
-	-65217, -65212, -65207, -65202, -65197, -65192, -65187, -65182,
-	-65177, -65171, -65166, -65161, -65155, -65150, -65144, -65139,
-	-65133, -65128, -65122, -65117, -65111, -65105, -65099, -65094,
-	-65088, -65082, -65076, -65070, -65064, -65058, -65052, -65046,
-	-65040, -65033, -65027, -65021, -65015, -65008, -65002, -64995,
-	-64989, -64982, -64976, -64969, -64963, -64956, -64949, -64943,
-	-64936, -64929, -64922, -64915, -64908, -64902, -64895, -64887,
-	-64880, -64873, -64866, -64859, -64852, -64844, -64837, -64830,
-	-64822, -64815, -64808, -64800, -64793, -64785, -64777, -64770,
-	-64762, -64754, -64747, -64739, -64731, -64723, -64715, -64707,
-	-64699, -64691, -64683, -64675, -64667, -64659, -64651, -64642,
-	-64634, -64626, -64617, -64609, -64601, -64592, -64584, -64575,
-	-64566, -64558, -64549, -64540, -64532, -64523, -64514, -64505,
-	-64496, -64487, -64478, -64469, -64460, -64451, -64442, -64433,
-	-64424, -64414, -64405, -64396, -64387, -64377, -64368, -64358,
-	-64349, -64339, -64330, -64320, -64310, -64301, -64291, -64281,
-	-64271, -64261, -64252, -64242, -64232, -64222, -64212, -64202,
-	-64192, -64181, -64171, -64161, -64151, -64140, -64130, -64120,
-	-64109, -64099, -64088, -64078, -64067, -64057, -64046, -64035,
-	-64025, -64014, -64003, -63992, -63981, -63971, -63960, -63949,
-	-63938, -63927, -63915, -63904, -63893, -63882, -63871, -63859,
-	-63848, -63837, -63825, -63814, -63803, -63791, -63779, -63768,
-	-63756, -63745, -63733, -63721, -63709, -63698, -63686, -63674,
-	-63662, -63650, -63638, -63626, -63614, -63602, -63590, -63578,
-	-63565, -63553, -63541, -63528, -63516, -63504, -63491, -63479,
-	-63466, -63454, -63441, -63429, -63416, -63403, -63390, -63378,
-	-63365, -63352, -63339, -63326, -63313, -63300, -63287, -63274,
-	-63261, -63248, -63235, -63221, -63208, -63195, -63182, -63168,
-	-63155, -63141, -63128, -63114, -63101, -63087, -63074, -63060,
-	-63046, -63032, -63019, -63005, -62991, -62977, -62963, -62949,
-	-62935, -62921, -62907, -62893, -62879, -62865, -62850, -62836,
-	-62822, -62808, -62793, -62779, -62764, -62750, -62735, -62721,
-	-62706, -62692, -62677, -62662, -62648, -62633, -62618, -62603,
-	-62588, -62573, -62558, -62543, -62528, -62513, -62498, -62483,
-	-62468, -62453, -62437, -62422, -62407, -62391, -62376, -62360,
-	-62345, -62329, -62314, -62298, -62283, -62267, -62251, -62236,
-	-62220, -62204, -62188, -62172, -62156, -62141, -62125, -62108,
-	-62092, -62076, -62060, -62044, -62028, -62012, -61995, -61979,
-	-61963, -61946, -61930, -61913, -61897, -61880, -61864, -61847,
-	-61831, -61814, -61797, -61780, -61764, -61747, -61730, -61713,
-	-61696, -61679, -61662, -61645, -61628, -61611, -61594, -61577,
-	-61559, -61542, -61525, -61507, -61490, -61473, -61455, -61438,
-	-61420, -61403, -61385, -61367, -61350, -61332, -61314, -61297,
-	-61279, -61261, -61243, -61225, -61207, -61189, -61171, -61153,
-	-61135, -61117, -61099, -61081, -61062, -61044, -61026, -61007,
-	-60989, -60971, -60952, -60934, -60915, -60897, -60878, -60859,
-	-60841, -60822, -60803, -60785, -60766, -60747, -60728, -60709,
-	-60690, -60671, -60652, -60633, -60614, -60595, -60576, -60556,
-	-60537, -60518, -60499, -60479, -60460, -60441, -60421, -60402,
-	-60382, -60363, -60343, -60323, -60304, -60284, -60264, -60244,
-	-60225, -60205, -60185, -60165, -60145, -60125, -60105, -60085,
-	-60065, -60045, -60025, -60004, -59984, -59964, -59944, -59923,
-	-59903, -59883, -59862, -59842, -59821, -59801, -59780, -59759,
-	-59739, -59718, -59697, -59677, -59656, -59635, -59614, -59593,
-	-59572, -59551, -59530, -59509, -59488, -59467, -59446, -59425,
-	-59404, -59382, -59361, -59340, -59318, -59297, -59276, -59254,
-	-59233, -59211, -59189, -59168, -59146, -59125, -59103, -59081,
-	-59059, -59038, -59016, -58994, -58972, -58950, -58928, -58906,
-	-58884, -58862, -58840, -58818, -58795, -58773, -58751, -58729,
-	-58706, -58684, -58662, -58639, -58617, -58594, -58572, -58549,
-	-58527, -58504, -58481, -58459, -58436, -58413, -58390, -58367,
-	-58345, -58322, -58299, -58276, -58253, -58230, -58207, -58183,
-	-58160, -58137, -58114, -58091, -58067, -58044, -58021, -57997,
-	-57974, -57950, -57927, -57903, -57880, -57856, -57833, -57809,
-	-57785, -57762, -57738, -57714, -57690, -57666, -57642, -57618,
-	-57594, -57570, -57546, -57522, -57498, -57474, -57450, -57426,
-	-57402, -57377, -57353, -57329, -57304, -57280, -57255, -57231,
-	-57206, -57182, -57157, -57133, -57108, -57083, -57059, -57034,
-	-57009, -56984, -56959, -56935, -56910, -56885, -56860, -56835,
-	-56810, -56785, -56760, -56734, -56709, -56684, -56659, -56633,
-	-56608, -56583, -56557, -56532, -56507, -56481, -56456, -56430,
-	-56404, -56379, -56353, -56328, -56302, -56276, -56250, -56225,
-	-56199, -56173, -56147, -56121, -56095, -56069, -56043, -56017,
-	-55991, -55965, -55938, -55912, -55886, -55860, -55833, -55807,
-	-55781, -55754, -55728, -55701, -55675, -55648, -55622, -55595,
-	-55569, -55542, -55515, -55489, -55462, -55435, -55408, -55381,
-	-55354, -55327, -55300, -55274, -55246, -55219, -55192, -55165,
-	-55138, -55111, -55084, -55056, -55029, -55002, -54974, -54947,
-	-54920, -54892, -54865, -54837, -54810, -54782, -54755, -54727,
-	-54699, -54672, -54644, -54616, -54588, -54560, -54533, -54505,
-	-54477, -54449, -54421, -54393, -54365, -54337, -54308, -54280,
-	-54252, -54224, -54196, -54167, -54139, -54111, -54082, -54054,
-	-54026, -53997, -53969, -53940, -53911, -53883, -53854, -53826,
-	-53797, -53768, -53739, -53711, -53682, -53653, -53624, -53595,
-	-53566, -53537, -53508, -53479, -53450, -53421, -53392, -53363,
-	-53334, -53304, -53275, -53246, -53216, -53187, -53158, -53128,
-	-53099, -53069, -53040, -53010, -52981, -52951, -52922, -52892,
-	-52862, -52832, -52803, -52773, -52743, -52713, -52683, -52653,
-	-52624, -52594, -52564, -52534, -52503, -52473, -52443, -52413,
-	-52383, -52353, -52322, -52292, -52262, -52231, -52201, -52171,
-	-52140, -52110, -52079, -52049, -52018, -51988, -51957, -51926,
-	-51896, -51865, -51834, -51803, -51773, -51742, -51711, -51680,
-	-51649, -51618, -51587, -51556, -51525, -51494, -51463, -51432,
-	-51401, -51369, -51338, -51307, -51276, -51244, -51213, -51182,
-	-51150, -51119, -51087, -51056, -51024, -50993, -50961, -50929,
-	-50898, -50866, -50834, -50803, -50771, -50739, -50707, -50675,
-	-50644, -50612, -50580, -50548, -50516, -50484, -50452, -50420,
-	-50387, -50355, -50323, -50291, -50259, -50226, -50194, -50162,
-	-50129, -50097, -50065, -50032, -50000, -49967, -49935, -49902,
-	-49869, -49837, -49804, -49771, -49739, -49706, -49673, -49640,
-	-49608, -49575, -49542, -49509, -49476, -49443, -49410, -49377,
-	-49344, -49311, -49278, -49244, -49211, -49178, -49145, -49112,
-	-49078, -49045, -49012, -48978, -48945, -48911, -48878, -48844,
-	-48811, -48777, -48744, -48710, -48676, -48643, -48609, -48575,
-	-48542, -48508, -48474, -48440, -48406, -48372, -48338, -48305,
-	-48271, -48237, -48202, -48168, -48134, -48100, -48066, -48032,
-	-47998, -47963, -47929, -47895, -47860, -47826, -47792, -47757,
-	-47723, -47688, -47654, -47619, -47585, -47550, -47516, -47481,
-	-47446, -47412, -47377, -47342, -47307, -47273, -47238, -47203,
-	-47168, -47133, -47098, -47063, -47028, -46993, -46958, -46923,
-	-46888, -46853, -46818, -46783, -46747, -46712, -46677, -46642,
-	-46606, -46571, -46536, -46500, -46465, -46429, -46394, -46358,
-	-46323, -46287, -46251, -46216, -46180, -46145, -46109, -46073,
-	-46037, -46002, -45966, -45930, -45894, -45858, -45822, -45786,
-	-45750, -45714, -45678, -45642, -45606, -45570, -45534, -45498,
-	-45462, -45425, -45389, -45353, -45316, -45280, -45244, -45207,
-	-45171, -45135, -45098, -45062, -45025, -44989, -44952, -44915,
-	-44879, -44842, -44806, -44769, -44732, -44695, -44659, -44622,
-	-44585, -44548, -44511, -44474, -44437, -44400, -44363, -44326,
-	-44289, -44252, -44215, -44178, -44141, -44104, -44067, -44029,
-	-43992, -43955, -43918, -43880, -43843, -43806, -43768, -43731,
-	-43693, -43656, -43618, -43581, -43543, -43506, -43468, -43430,
-	-43393, -43355, -43317, -43280, -43242, -43204, -43166, -43128,
-	-43091, -43053, -43015, -42977, -42939, -42901, -42863, -42825,
-	-42787, -42749, -42711, -42672, -42634, -42596, -42558, -42520,
-	-42481, -42443, -42405, -42366, -42328, -42290, -42251, -42213,
-	-42174, -42136, -42097, -42059, -42020, -41982, -41943, -41904,
-	-41866, -41827, -41788, -41750, -41711, -41672, -41633, -41595,
-	-41556, -41517, -41478, -41439, -41400, -41361, -41322, -41283,
-	-41244, -41205, -41166, -41127, -41087, -41048, -41009, -40970,
-	-40931, -40891, -40852, -40813, -40773, -40734, -40695, -40655,
-	-40616, -40576, -40537, -40497, -40458, -40418, -40379, -40339,
-	-40299, -40260, -40220, -40180, -40141, -40101, -40061, -40021,
-	-39982, -39942, -39902, -39862, -39822, -39782, -39742, -39702,
-	-39662, -39622, -39582, -39542, -39502, -39462, -39422, -39382,
-	-39341, -39301, -39261, -39221, -39180, -39140, -39100, -39059,
-	-39019, -38979, -38938, -38898, -38857, -38817, -38776, -38736,
-	-38695, -38655, -38614, -38573, -38533, -38492, -38451, -38411,
-	-38370, -38329, -38288, -38248, -38207, -38166, -38125, -38084,
-	-38043, -38002, -37961, -37920, -37879, -37838, -37797, -37756,
-	-37715, -37674, -37633, -37592, -37550, -37509, -37468, -37427,
-	-37386, -37344, -37303, -37262, -37220, -37179, -37137, -37096,
-	-37055, -37013, -36972, -36930, -36889, -36847, -36805, -36764,
-	-36722, -36681, -36639, -36597, -36556, -36514, -36472, -36430,
-	-36388, -36347, -36305, -36263, -36221, -36179, -36137, -36095,
-	-36053, -36011, -35969, -35927, -35885, -35843, -35801, -35759,
-	-35717, -35675, -35633, -35590, -35548, -35506, -35464, -35421,
-	-35379, -35337, -35294, -35252, -35210, -35167, -35125, -35082,
-	-35040, -34997, -34955, -34912, -34870, -34827, -34785, -34742,
-	-34699, -34657, -34614, -34571, -34529, -34486, -34443, -34400,
-	-34358, -34315, -34272, -34229, -34186, -34143, -34100, -34057,
-	-34015, -33972, -33929, -33886, -33843, -33799, -33756, -33713,
-	-33670, -33627, -33584, -33541, -33498, -33454, -33411, -33368,
-	-33325, -33281, -33238, -33195, -33151, -33108, -33065, -33021,
-	-32978, -32934, -32891, -32847, -32804, -32760, -32717, -32673,
-	-32630, -32586, -32542, -32499, -32455, -32411, -32368, -32324,
-	-32280, -32236, -32193, -32149, -32105, -32061, -32017, -31974,
-	-31930, -31886, -31842, -31798, -31754, -31710, -31666, -31622,
-	-31578, -31534, -31490, -31446, -31402, -31357, -31313, -31269,
-	-31225, -31181, -31136, -31092, -31048, -31004, -30959, -30915,
-	-30871, -30826, -30782, -30738, -30693, -30649, -30604, -30560,
-	-30515, -30471, -30426, -30382, -30337, -30293, -30248, -30204,
-	-30159, -30114, -30070, -30025, -29980, -29936, -29891, -29846,
-	-29801, -29757, -29712, -29667, -29622, -29577, -29533, -29488,
-	-29443, -29398, -29353, -29308, -29263, -29218, -29173, -29128,
-	-29083, -29038, -28993, -28948, -28903, -28858, -28812, -28767,
-	-28722, -28677, -28632, -28586, -28541, -28496, -28451, -28405,
-	-28360, -28315, -28269, -28224, -28179, -28133, -28088, -28042,
-	-27997, -27952, -27906, -27861, -27815, -27770, -27724, -27678,
-	-27633, -27587, -27542, -27496, -27450, -27405, -27359, -27313,
-	-27268, -27222, -27176, -27131, -27085, -27039, -26993, -26947,
-	-26902, -26856, -26810, -26764, -26718, -26672, -26626, -26580,
-	-26534, -26488, -26442, -26396, -26350, -26304, -26258, -26212,
-	-26166, -26120, -26074, -26028, -25982, -25936, -25889, -25843,
-	-25797, -25751, -25705, -25658, -25612, -25566, -25520, -25473,
-	-25427, -25381, -25334, -25288, -25241, -25195, -25149, -25102,
-	-25056, -25009, -24963, -24916, -24870, -24823, -24777, -24730,
-	-24684, -24637, -24591, -24544, -24497, -24451, -24404, -24357,
-	-24311, -24264, -24217, -24171, -24124, -24077, -24030, -23984,
-	-23937, -23890, -23843, -23796, -23750, -23703, -23656, -23609,
-	-23562, -23515, -23468, -23421, -23374, -23327, -23280, -23233,
-	-23186, -23139, -23092, -23045, -22998, -22951, -22904, -22857,
-	-22810, -22763, -22716, -22668, -22621, -22574, -22527, -22480,
-	-22432, -22385, -22338, -22291, -22243, -22196, -22149, -22102,
-	-22054, -22007, -21960, -21912, -21865, -21817, -21770, -21723,
-	-21675, -21628, -21580, -21533, -21485, -21438, -21390, -21343,
-	-21295, -21248, -21200, -21153, -21105, -21057, -21010, -20962,
-	-20915, -20867, -20819, -20772, -20724, -20676, -20629, -20581,
-	-20533, -20485, -20438, -20390, -20342, -20294, -20246, -20199,
-	-20151, -20103, -20055, -20007, -19959, -19912, -19864, -19816,
-	-19768, -19720, -19672, -19624, -19576, -19528, -19480, -19432,
-	-19384, -19336, -19288, -19240, -19192, -19144, -19096, -19048,
-	-19000, -18951, -18903, -18855, -18807, -18759, -18711, -18663,
-	-18614, -18566, -18518, -18470, -18421, -18373, -18325, -18277,
-	-18228, -18180, -18132, -18084, -18035, -17987, -17939, -17890,
-	-17842, -17793, -17745, -17697, -17648, -17600, -17551, -17503,
-	-17455, -17406, -17358, -17309, -17261, -17212, -17164, -17115,
-	-17067, -17018, -16970, -16921, -16872, -16824, -16775, -16727,
-	-16678, -16629, -16581, -16532, -16484, -16435, -16386, -16338,
-	-16289, -16240, -16191, -16143, -16094, -16045, -15997, -15948,
-	-15899, -15850, -15802, -15753, -15704, -15655, -15606, -15557,
-	-15509, -15460, -15411, -15362, -15313, -15264, -15215, -15167,
-	-15118, -15069, -15020, -14971, -14922, -14873, -14824, -14775,
-	-14726, -14677, -14628, -14579, -14530, -14481, -14432, -14383,
-	-14334, -14285, -14236, -14187, -14138, -14089, -14040, -13990,
-	-13941, -13892, -13843, -13794, -13745, -13696, -13647, -13597,
-	-13548, -13499, -13450, -13401, -13351, -13302, -13253, -13204,
-	-13154, -13105, -13056, -13007, -12957, -12908, -12859, -12810,
-	-12760, -12711, -12662, -12612, -12563, -12514, -12464, -12415,
-	-12366, -12316, -12267, -12217, -12168, -12119, -12069, -12020,
-	-11970, -11921, -11872, -11822, -11773, -11723, -11674, -11624,
-	-11575, -11525, -11476, -11426, -11377, -11327, -11278, -11228,
-	-11179, -11129, -11080, -11030, -10981, -10931, -10882, -10832,
-	-10782, -10733, -10683, -10634, -10584, -10534, -10485, -10435,
-	-10386, -10336, -10286, -10237, -10187, -10137, -10088, -10038,
-	-9988, -9939, -9889, -9839, -9790, -9740, -9690, -9640,
-	-9591, -9541, -9491, -9442, -9392, -9342, -9292, -9243,
-	-9193, -9143, -9093, -9043, -8994, -8944, -8894, -8844,
-	-8794, -8745, -8695, -8645, -8595, -8545, -8496, -8446,
-	-8396, -8346, -8296, -8246, -8196, -8147, -8097, -8047,
-	-7997, -7947, -7897, -7847, -7797, -7747, -7697, -7648,
-	-7598, -7548, -7498, -7448, -7398, -7348, -7298, -7248,
-	-7198, -7148, -7098, -7048, -6998, -6948, -6898, -6848,
-	-6798, -6748, -6698, -6648, -6598, -6548, -6498, -6448,
-	-6398, -6348, -6298, -6248, -6198, -6148, -6098, -6048,
-	-5998, -5948, -5898, -5848, -5798, -5747, -5697, -5647,
-	-5597, -5547, -5497, -5447, -5397, -5347, -5297, -5247,
-	-5197, -5146, -5096, -5046, -4996, -4946, -4896, -4846,
-	-4796, -4745, -4695, -4645, -4595, -4545, -4495, -4445,
-	-4394, -4344, -4294, -4244, -4194, -4144, -4093, -4043,
-	-3993, -3943, -3893, -3843, -3792, -3742, -3692, -3642,
-	-3592, -3541, -3491, -3441, -3391, -3341, -3291, -3240,
-	-3190, -3140, -3090, -3039, -2989, -2939, -2889, -2839,
-	-2788, -2738, -2688, -2638, -2588, -2537, -2487, -2437,
-	-2387, -2336, -2286, -2236, -2186, -2135, -2085, -2035,
-	-1985, -1934, -1884, -1834, -1784, -1733, -1683, -1633,
-	-1583, -1532, -1482, -1432, -1382, -1331, -1281, -1231,
-	-1181, -1130, -1080, -1030, -980, -929, -879, -829,
-	-779, -728, -678, -628, -578, -527, -477, -427,
-	-376, -326, -276, -226, -175, -125, -75, -25,
-	25, 75, 125, 175, 226, 276, 326, 376,
-	427, 477, 527, 578, 628, 678, 728, 779,
-	829, 879, 929, 980, 1030, 1080, 1130, 1181,
-	1231, 1281, 1331, 1382, 1432, 1482, 1532, 1583,
-	1633, 1683, 1733, 1784, 1834, 1884, 1934, 1985,
-	2035, 2085, 2135, 2186, 2236, 2286, 2336, 2387,
-	2437, 2487, 2537, 2587, 2638, 2688, 2738, 2788,
-	2839, 2889, 2939, 2989, 3039, 3090, 3140, 3190,
-	3240, 3291, 3341, 3391, 3441, 3491, 3542, 3592,
-	3642, 3692, 3742, 3792, 3843, 3893, 3943, 3993,
-	4043, 4093, 4144, 4194, 4244, 4294, 4344, 4394,
-	4445, 4495, 4545, 4595, 4645, 4695, 4745, 4796,
-	4846, 4896, 4946, 4996, 5046, 5096, 5146, 5197,
-	5247, 5297, 5347, 5397, 5447, 5497, 5547, 5597,
-	5647, 5697, 5747, 5798, 5848, 5898, 5948, 5998,
-	6048, 6098, 6148, 6198, 6248, 6298, 6348, 6398,
-	6448, 6498, 6548, 6598, 6648, 6698, 6748, 6798,
-	6848, 6898, 6948, 6998, 7048, 7098, 7148, 7198,
-	7248, 7298, 7348, 7398, 7448, 7498, 7548, 7598,
-	7648, 7697, 7747, 7797, 7847, 7897, 7947, 7997,
-	8047, 8097, 8147, 8196, 8246, 8296, 8346, 8396,
-	8446, 8496, 8545, 8595, 8645, 8695, 8745, 8794,
-	8844, 8894, 8944, 8994, 9043, 9093, 9143, 9193,
-	9243, 9292, 9342, 9392, 9442, 9491, 9541, 9591,
-	9640, 9690, 9740, 9790, 9839, 9889, 9939, 9988,
-	10038, 10088, 10137, 10187, 10237, 10286, 10336, 10386,
-	10435, 10485, 10534, 10584, 10634, 10683, 10733, 10782,
-	10832, 10882, 10931, 10981, 11030, 11080, 11129, 11179,
-	11228, 11278, 11327, 11377, 11426, 11476, 11525, 11575,
-	11624, 11674, 11723, 11773, 11822, 11872, 11921, 11970,
-	12020, 12069, 12119, 12168, 12218, 12267, 12316, 12366,
-	12415, 12464, 12514, 12563, 12612, 12662, 12711, 12760,
-	12810, 12859, 12908, 12957, 13007, 13056, 13105, 13154,
-	13204, 13253, 13302, 13351, 13401, 13450, 13499, 13548,
-	13597, 13647, 13696, 13745, 13794, 13843, 13892, 13941,
-	13990, 14040, 14089, 14138, 14187, 14236, 14285, 14334,
-	14383, 14432, 14481, 14530, 14579, 14628, 14677, 14726,
-	14775, 14824, 14873, 14922, 14971, 15020, 15069, 15118,
-	15167, 15215, 15264, 15313, 15362, 15411, 15460, 15509,
-	15557, 15606, 15655, 15704, 15753, 15802, 15850, 15899,
-	15948, 15997, 16045, 16094, 16143, 16191, 16240, 16289,
-	16338, 16386, 16435, 16484, 16532, 16581, 16629, 16678,
-	16727, 16775, 16824, 16872, 16921, 16970, 17018, 17067,
-	17115, 17164, 17212, 17261, 17309, 17358, 17406, 17455,
-	17503, 17551, 17600, 17648, 17697, 17745, 17793, 17842,
-	17890, 17939, 17987, 18035, 18084, 18132, 18180, 18228,
-	18277, 18325, 18373, 18421, 18470, 18518, 18566, 18614,
-	18663, 18711, 18759, 18807, 18855, 18903, 18951, 19000,
-	19048, 19096, 19144, 19192, 19240, 19288, 19336, 19384,
-	19432, 19480, 19528, 19576, 19624, 19672, 19720, 19768,
-	19816, 19864, 19912, 19959, 20007, 20055, 20103, 20151,
-	20199, 20246, 20294, 20342, 20390, 20438, 20485, 20533,
-	20581, 20629, 20676, 20724, 20772, 20819, 20867, 20915,
-	20962, 21010, 21057, 21105, 21153, 21200, 21248, 21295,
-	21343, 21390, 21438, 21485, 21533, 21580, 21628, 21675,
-	21723, 21770, 21817, 21865, 21912, 21960, 22007, 22054,
-	22102, 22149, 22196, 22243, 22291, 22338, 22385, 22432,
-	22480, 22527, 22574, 22621, 22668, 22716, 22763, 22810,
-	22857, 22904, 22951, 22998, 23045, 23092, 23139, 23186,
-	23233, 23280, 23327, 23374, 23421, 23468, 23515, 23562,
-	23609, 23656, 23703, 23750, 23796, 23843, 23890, 23937,
-	23984, 24030, 24077, 24124, 24171, 24217, 24264, 24311,
-	24357, 24404, 24451, 24497, 24544, 24591, 24637, 24684,
-	24730, 24777, 24823, 24870, 24916, 24963, 25009, 25056,
-	25102, 25149, 25195, 25241, 25288, 25334, 25381, 25427,
-	25473, 25520, 25566, 25612, 25658, 25705, 25751, 25797,
-	25843, 25889, 25936, 25982, 26028, 26074, 26120, 26166,
-	26212, 26258, 26304, 26350, 26396, 26442, 26488, 26534,
-	26580, 26626, 26672, 26718, 26764, 26810, 26856, 26902,
-	26947, 26993, 27039, 27085, 27131, 27176, 27222, 27268,
-	27313, 27359, 27405, 27450, 27496, 27542, 27587, 27633,
-	27678, 27724, 27770, 27815, 27861, 27906, 27952, 27997,
-	28042, 28088, 28133, 28179, 28224, 28269, 28315, 28360,
-	28405, 28451, 28496, 28541, 28586, 28632, 28677, 28722,
-	28767, 28812, 28858, 28903, 28948, 28993, 29038, 29083,
-	29128, 29173, 29218, 29263, 29308, 29353, 29398, 29443,
-	29488, 29533, 29577, 29622, 29667, 29712, 29757, 29801,
-	29846, 29891, 29936, 29980, 30025, 30070, 30114, 30159,
-	30204, 30248, 30293, 30337, 30382, 30427, 30471, 30516,
-	30560, 30604, 30649, 30693, 30738, 30782, 30826, 30871,
-	30915, 30959, 31004, 31048, 31092, 31136, 31181, 31225,
-	31269, 31313, 31357, 31402, 31446, 31490, 31534, 31578,
-	31622, 31666, 31710, 31754, 31798, 31842, 31886, 31930,
-	31974, 32017, 32061, 32105, 32149, 32193, 32236, 32280,
-	32324, 32368, 32411, 32455, 32499, 32542, 32586, 32630,
-	32673, 32717, 32760, 32804, 32847, 32891, 32934, 32978,
-	33021, 33065, 33108, 33151, 33195, 33238, 33281, 33325,
-	33368, 33411, 33454, 33498, 33541, 33584, 33627, 33670,
-	33713, 33756, 33799, 33843, 33886, 33929, 33972, 34015,
-	34057, 34100, 34143, 34186, 34229, 34272, 34315, 34358,
-	34400, 34443, 34486, 34529, 34571, 34614, 34657, 34699,
-	34742, 34785, 34827, 34870, 34912, 34955, 34997, 35040,
-	35082, 35125, 35167, 35210, 35252, 35294, 35337, 35379,
-	35421, 35464, 35506, 35548, 35590, 35633, 35675, 35717,
-	35759, 35801, 35843, 35885, 35927, 35969, 36011, 36053,
-	36095, 36137, 36179, 36221, 36263, 36305, 36347, 36388,
-	36430, 36472, 36514, 36556, 36597, 36639, 36681, 36722,
-	36764, 36805, 36847, 36889, 36930, 36972, 37013, 37055,
-	37096, 37137, 37179, 37220, 37262, 37303, 37344, 37386,
-	37427, 37468, 37509, 37551, 37592, 37633, 37674, 37715,
-	37756, 37797, 37838, 37879, 37920, 37961, 38002, 38043,
-	38084, 38125, 38166, 38207, 38248, 38288, 38329, 38370,
-	38411, 38451, 38492, 38533, 38573, 38614, 38655, 38695,
-	38736, 38776, 38817, 38857, 38898, 38938, 38979, 39019,
-	39059, 39100, 39140, 39180, 39221, 39261, 39301, 39341,
-	39382, 39422, 39462, 39502, 39542, 39582, 39622, 39662,
-	39702, 39742, 39782, 39822, 39862, 39902, 39942, 39982,
-	40021, 40061, 40101, 40141, 40180, 40220, 40260, 40299,
-	40339, 40379, 40418, 40458, 40497, 40537, 40576, 40616,
-	40655, 40695, 40734, 40773, 40813, 40852, 40891, 40931,
-	40970, 41009, 41048, 41087, 41127, 41166, 41205, 41244,
-	41283, 41322, 41361, 41400, 41439, 41478, 41517, 41556,
-	41595, 41633, 41672, 41711, 41750, 41788, 41827, 41866,
-	41904, 41943, 41982, 42020, 42059, 42097, 42136, 42174,
-	42213, 42251, 42290, 42328, 42366, 42405, 42443, 42481,
-	42520, 42558, 42596, 42634, 42672, 42711, 42749, 42787,
-	42825, 42863, 42901, 42939, 42977, 43015, 43053, 43091,
-	43128, 43166, 43204, 43242, 43280, 43317, 43355, 43393,
-	43430, 43468, 43506, 43543, 43581, 43618, 43656, 43693,
-	43731, 43768, 43806, 43843, 43880, 43918, 43955, 43992,
-	44029, 44067, 44104, 44141, 44178, 44215, 44252, 44289,
-	44326, 44363, 44400, 44437, 44474, 44511, 44548, 44585,
-	44622, 44659, 44695, 44732, 44769, 44806, 44842, 44879,
-	44915, 44952, 44989, 45025, 45062, 45098, 45135, 45171,
-	45207, 45244, 45280, 45316, 45353, 45389, 45425, 45462,
-	45498, 45534, 45570, 45606, 45642, 45678, 45714, 45750,
-	45786, 45822, 45858, 45894, 45930, 45966, 46002, 46037,
-	46073, 46109, 46145, 46180, 46216, 46252, 46287, 46323,
-	46358, 46394, 46429, 46465, 46500, 46536, 46571, 46606,
-	46642, 46677, 46712, 46747, 46783, 46818, 46853, 46888,
-	46923, 46958, 46993, 47028, 47063, 47098, 47133, 47168,
-	47203, 47238, 47273, 47308, 47342, 47377, 47412, 47446,
-	47481, 47516, 47550, 47585, 47619, 47654, 47688, 47723,
-	47757, 47792, 47826, 47861, 47895, 47929, 47963, 47998,
-	48032, 48066, 48100, 48134, 48168, 48202, 48237, 48271,
-	48305, 48338, 48372, 48406, 48440, 48474, 48508, 48542,
-	48575, 48609, 48643, 48676, 48710, 48744, 48777, 48811,
-	48844, 48878, 48911, 48945, 48978, 49012, 49045, 49078,
-	49112, 49145, 49178, 49211, 49244, 49278, 49311, 49344,
-	49377, 49410, 49443, 49476, 49509, 49542, 49575, 49608,
-	49640, 49673, 49706, 49739, 49771, 49804, 49837, 49869,
-	49902, 49935, 49967, 50000, 50032, 50064, 50097, 50129,
-	50162, 50194, 50226, 50259, 50291, 50323, 50355, 50387,
-	50420, 50452, 50484, 50516, 50548, 50580, 50612, 50644,
-	50675, 50707, 50739, 50771, 50803, 50834, 50866, 50898,
-	50929, 50961, 50993, 51024, 51056, 51087, 51119, 51150,
-	51182, 51213, 51244, 51276, 51307, 51338, 51369, 51401,
-	51432, 51463, 51494, 51525, 51556, 51587, 51618, 51649,
-	51680, 51711, 51742, 51773, 51803, 51834, 51865, 51896,
-	51926, 51957, 51988, 52018, 52049, 52079, 52110, 52140,
-	52171, 52201, 52231, 52262, 52292, 52322, 52353, 52383,
-	52413, 52443, 52473, 52503, 52534, 52564, 52594, 52624,
-	52653, 52683, 52713, 52743, 52773, 52803, 52832, 52862,
-	52892, 52922, 52951, 52981, 53010, 53040, 53069, 53099,
-	53128, 53158, 53187, 53216, 53246, 53275, 53304, 53334,
-	53363, 53392, 53421, 53450, 53479, 53508, 53537, 53566,
-	53595, 53624, 53653, 53682, 53711, 53739, 53768, 53797,
-	53826, 53854, 53883, 53912, 53940, 53969, 53997, 54026,
-	54054, 54082, 54111, 54139, 54167, 54196, 54224, 54252,
-	54280, 54309, 54337, 54365, 54393, 54421, 54449, 54477,
-	54505, 54533, 54560, 54588, 54616, 54644, 54672, 54699,
-	54727, 54755, 54782, 54810, 54837, 54865, 54892, 54920,
-	54947, 54974, 55002, 55029, 55056, 55084, 55111, 55138,
-	55165, 55192, 55219, 55246, 55274, 55300, 55327, 55354,
-	55381, 55408, 55435, 55462, 55489, 55515, 55542, 55569,
-	55595, 55622, 55648, 55675, 55701, 55728, 55754, 55781,
-	55807, 55833, 55860, 55886, 55912, 55938, 55965, 55991,
-	56017, 56043, 56069, 56095, 56121, 56147, 56173, 56199,
-	56225, 56250, 56276, 56302, 56328, 56353, 56379, 56404,
-	56430, 56456, 56481, 56507, 56532, 56557, 56583, 56608,
-	56633, 56659, 56684, 56709, 56734, 56760, 56785, 56810,
-	56835, 56860, 56885, 56910, 56935, 56959, 56984, 57009,
-	57034, 57059, 57083, 57108, 57133, 57157, 57182, 57206,
-	57231, 57255, 57280, 57304, 57329, 57353, 57377, 57402,
-	57426, 57450, 57474, 57498, 57522, 57546, 57570, 57594,
-	57618, 57642, 57666, 57690, 57714, 57738, 57762, 57785,
-	57809, 57833, 57856, 57880, 57903, 57927, 57950, 57974,
-	57997, 58021, 58044, 58067, 58091, 58114, 58137, 58160,
-	58183, 58207, 58230, 58253, 58276, 58299, 58322, 58345,
-	58367, 58390, 58413, 58436, 58459, 58481, 58504, 58527,
-	58549, 58572, 58594, 58617, 58639, 58662, 58684, 58706,
-	58729, 58751, 58773, 58795, 58818, 58840, 58862, 58884,
-	58906, 58928, 58950, 58972, 58994, 59016, 59038, 59059,
-	59081, 59103, 59125, 59146, 59168, 59190, 59211, 59233,
-	59254, 59276, 59297, 59318, 59340, 59361, 59382, 59404,
-	59425, 59446, 59467, 59488, 59509, 59530, 59551, 59572,
-	59593, 59614, 59635, 59656, 59677, 59697, 59718, 59739,
-	59759, 59780, 59801, 59821, 59842, 59862, 59883, 59903,
-	59923, 59944, 59964, 59984, 60004, 60025, 60045, 60065,
-	60085, 60105, 60125, 60145, 60165, 60185, 60205, 60225,
-	60244, 60264, 60284, 60304, 60323, 60343, 60363, 60382,
-	60402, 60421, 60441, 60460, 60479, 60499, 60518, 60537,
-	60556, 60576, 60595, 60614, 60633, 60652, 60671, 60690,
-	60709, 60728, 60747, 60766, 60785, 60803, 60822, 60841,
-	60859, 60878, 60897, 60915, 60934, 60952, 60971, 60989,
-	61007, 61026, 61044, 61062, 61081, 61099, 61117, 61135,
-	61153, 61171, 61189, 61207, 61225, 61243, 61261, 61279,
-	61297, 61314, 61332, 61350, 61367, 61385, 61403, 61420,
-	61438, 61455, 61473, 61490, 61507, 61525, 61542, 61559,
-	61577, 61594, 61611, 61628, 61645, 61662, 61679, 61696,
-	61713, 61730, 61747, 61764, 61780, 61797, 61814, 61831,
-	61847, 61864, 61880, 61897, 61913, 61930, 61946, 61963,
-	61979, 61995, 62012, 62028, 62044, 62060, 62076, 62092,
-	62108, 62125, 62141, 62156, 62172, 62188, 62204, 62220,
-	62236, 62251, 62267, 62283, 62298, 62314, 62329, 62345,
-	62360, 62376, 62391, 62407, 62422, 62437, 62453, 62468,
-	62483, 62498, 62513, 62528, 62543, 62558, 62573, 62588,
-	62603, 62618, 62633, 62648, 62662, 62677, 62692, 62706,
-	62721, 62735, 62750, 62764, 62779, 62793, 62808, 62822,
-	62836, 62850, 62865, 62879, 62893, 62907, 62921, 62935,
-	62949, 62963, 62977, 62991, 63005, 63019, 63032, 63046,
-	63060, 63074, 63087, 63101, 63114, 63128, 63141, 63155,
-	63168, 63182, 63195, 63208, 63221, 63235, 63248, 63261,
-	63274, 63287, 63300, 63313, 63326, 63339, 63352, 63365,
-	63378, 63390, 63403, 63416, 63429, 63441, 63454, 63466,
-	63479, 63491, 63504, 63516, 63528, 63541, 63553, 63565,
-	63578, 63590, 63602, 63614, 63626, 63638, 63650, 63662,
-	63674, 63686, 63698, 63709, 63721, 63733, 63745, 63756,
-	63768, 63779, 63791, 63803, 63814, 63825, 63837, 63848,
-	63859, 63871, 63882, 63893, 63904, 63915, 63927, 63938,
-	63949, 63960, 63971, 63981, 63992, 64003, 64014, 64025,
-	64035, 64046, 64057, 64067, 64078, 64088, 64099, 64109,
-	64120, 64130, 64140, 64151, 64161, 64171, 64181, 64192,
-	64202, 64212, 64222, 64232, 64242, 64252, 64261, 64271,
-	64281, 64291, 64301, 64310, 64320, 64330, 64339, 64349,
-	64358, 64368, 64377, 64387, 64396, 64405, 64414, 64424,
-	64433, 64442, 64451, 64460, 64469, 64478, 64487, 64496,
-	64505, 64514, 64523, 64532, 64540, 64549, 64558, 64566,
-	64575, 64584, 64592, 64600, 64609, 64617, 64626, 64634,
-	64642, 64651, 64659, 64667, 64675, 64683, 64691, 64699,
-	64707, 64715, 64723, 64731, 64739, 64747, 64754, 64762,
-	64770, 64777, 64785, 64793, 64800, 64808, 64815, 64822,
-	64830, 64837, 64844, 64852, 64859, 64866, 64873, 64880,
-	64887, 64895, 64902, 64908, 64915, 64922, 64929, 64936,
-	64943, 64949, 64956, 64963, 64969, 64976, 64982, 64989,
-	64995, 65002, 65008, 65015, 65021, 65027, 65033, 65040,
-	65046, 65052, 65058, 65064, 65070, 65076, 65082, 65088,
-	65094, 65099, 65105, 65111, 65117, 65122, 65128, 65133,
-	65139, 65144, 65150, 65155, 65161, 65166, 65171, 65177,
-	65182, 65187, 65192, 65197, 65202, 65207, 65212, 65217,
-	65222, 65227, 65232, 65237, 65242, 65246, 65251, 65256,
-	65260, 65265, 65270, 65274, 65279, 65283, 65287, 65292,
-	65296, 65300, 65305, 65309, 65313, 65317, 65321, 65325,
-	65329, 65333, 65337, 65341, 65345, 65349, 65352, 65356,
-	65360, 65363, 65367, 65371, 65374, 65378, 65381, 65385,
-	65388, 65391, 65395, 65398, 65401, 65404, 65408, 65411,
-	65414, 65417, 65420, 65423, 65426, 65429, 65431, 65434,
-	65437, 65440, 65442, 65445, 65448, 65450, 65453, 65455,
-	65458, 65460, 65463, 65465, 65467, 65470, 65472, 65474,
-	65476, 65478, 65480, 65482, 65484, 65486, 65488, 65490,
-	65492, 65494, 65496, 65497, 65499, 65501, 65502, 65504,
-	65505, 65507, 65508, 65510, 65511, 65513, 65514, 65515,
-	65516, 65518, 65519, 65520, 65521, 65522, 65523, 65524,
-	65525, 65526, 65527, 65527, 65528, 65529, 65530, 65530,
+	-65536, -65535, -65535, -65535, -65535, -65535, -65535, -65535,
+	-65534, -65534, -65534, -65533, -65533, -65532, -65532, -65531,
+	-65531, -65530, -65529, -65529, -65528, -65527, -65526, -65525,
+	-65524, -65523, -65522, -65521, -65520, -65519, -65518, -65517,
+	-65516, -65515, -65513, -65512, -65511, -65509, -65508, -65506,
+	-65505, -65503, -65501, -65500, -65498, -65496, -65495, -65493,
+	-65491, -65489, -65487, -65485, -65483, -65481, -65479, -65477,
+	-65475, -65473, -65471, -65468, -65466, -65464, -65461, -65459,
+	-65457, -65454, -65452, -65449, -65446, -65444, -65441, -65438,
+	-65436, -65433, -65430, -65427, -65424, -65421, -65418, -65415,
+	-65412, -65409, -65406, -65403, -65400, -65396, -65393, -65390,
+	-65386, -65383, -65379, -65376, -65372, -65369, -65365, -65362,
+	-65358, -65354, -65350, -65347, -65343, -65339, -65335, -65331,
+	-65327, -65323, -65319, -65315, -65311, -65307, -65302, -65298,
+	-65294, -65290, -65285, -65281, -65276, -65272, -65267, -65263,
+	-65258, -65253, -65249, -65244, -65239, -65235, -65230, -65225,
+	-65220, -65215, -65210, -65205, -65200, -65195, -65190, -65184,
+	-65179, -65174, -65169, -65163, -65158, -65153, -65147, -65142,
+	-65136, -65131, -65125, -65119, -65114, -65108, -65102, -65096,
+	-65091, -65085, -65079, -65073, -65067, -65061, -65055, -65049,
+	-65043, -65036, -65030, -65024, -65018, -65011, -65005, -64999,
+	-64992, -64986, -64979, -64973, -64966, -64959, -64953, -64946,
+	-64939, -64933, -64926, -64919, -64912, -64905, -64898, -64891,
+	-64884, -64877, -64870, -64863, -64855, -64848, -64841, -64834,
+	-64826, -64819, -64811, -64804, -64796, -64789, -64781, -64774,
+	-64766, -64758, -64751, -64743, -64735, -64727, -64719, -64711,
+	-64703, -64695, -64687, -64679, -64671, -64663, -64655, -64646,
+	-64638, -64630, -64622, -64613, -64605, -64596, -64588, -64579,
+	-64571, -64562, -64553, -64545, -64536, -64527, -64518, -64510,
+	-64501, -64492, -64483, -64474, -64465, -64456, -64447, -64437,
+	-64428, -64419, -64410, -64401, -64391, -64382, -64372, -64363,
+	-64353, -64344, -64334, -64325, -64315, -64305, -64296, -64286,
+	-64276, -64266, -64257, -64247, -64237, -64227, -64217, -64207,
+	-64197, -64186, -64176, -64166, -64156, -64146, -64135, -64125,
+	-64115, -64104, -64094, -64083, -64073, -64062, -64051, -64041,
+	-64030, -64019, -64009, -63998, -63987, -63976, -63965, -63954,
+	-63943, -63932, -63921, -63910, -63899, -63888, -63876, -63865,
+	-63854, -63842, -63831, -63820, -63808, -63797, -63785, -63774,
+	-63762, -63750, -63739, -63727, -63715, -63704, -63692, -63680,
+	-63668, -63656, -63644, -63632, -63620, -63608, -63596, -63584,
+	-63571, -63559, -63547, -63535, -63522, -63510, -63498, -63485,
+	-63473, -63460, -63447, -63435, -63422, -63410, -63397, -63384,
+	-63371, -63358, -63346, -63333, -63320, -63307, -63294, -63281,
+	-63268, -63254, -63241, -63228, -63215, -63202, -63188, -63175,
+	-63162, -63148, -63135, -63121, -63108, -63094, -63080, -63067,
+	-63053, -63039, -63026, -63012, -62998, -62984, -62970, -62956,
+	-62942, -62928, -62914, -62900, -62886, -62872, -62858, -62843,
+	-62829, -62815, -62800, -62786, -62772, -62757, -62743, -62728,
+	-62714, -62699, -62684, -62670, -62655, -62640, -62625, -62610,
+	-62596, -62581, -62566, -62551, -62536, -62521, -62506, -62491,
+	-62475, -62460, -62445, -62430, -62414, -62399, -62384, -62368,
+	-62353, -62337, -62322, -62306, -62291, -62275, -62259, -62244,
+	-62228, -62212, -62196, -62180, -62164, -62148, -62133, -62117,
+	-62100, -62084, -62068, -62052, -62036, -62020, -62003, -61987,
+	-61971, -61954, -61938, -61922, -61905, -61889, -61872, -61855,
+	-61839, -61822, -61805, -61789, -61772, -61755, -61738, -61721,
+	-61705, -61688, -61671, -61654, -61637, -61619, -61602, -61585,
+	-61568, -61551, -61533, -61516, -61499, -61481, -61464, -61446,
+	-61429, -61411, -61394, -61376, -61359, -61341, -61323, -61305,
+	-61288, -61270, -61252, -61234, -61216, -61198, -61180, -61162,
+	-61144, -61126, -61108, -61090, -61071, -61053, -61035, -61017,
+	-60998, -60980, -60961, -60943, -60924, -60906, -60887, -60869,
+	-60850, -60831, -60813, -60794, -60775, -60756, -60737, -60719,
+	-60700, -60681, -60662, -60643, -60624, -60604, -60585, -60566,
+	-60547, -60528, -60508, -60489, -60470, -60450, -60431, -60411,
+	-60392, -60372, -60353, -60333, -60313, -60294, -60274, -60254,
+	-60235, -60215, -60195, -60175, -60155, -60135, -60115, -60095,
+	-60075, -60055, -60035, -60015, -59994, -59974, -59954, -59934,
+	-59913, -59893, -59872, -59852, -59831, -59811, -59790, -59770,
+	-59749, -59728, -59708, -59687, -59666, -59645, -59625, -59604,
+	-59583, -59562, -59541, -59520, -59499, -59478, -59457, -59435,
+	-59414, -59393, -59372, -59350, -59329, -59308, -59286, -59265,
+	-59243, -59222, -59200, -59179, -59157, -59135, -59114, -59092,
+	-59070, -59049, -59027, -59005, -58983, -58961, -58939, -58917,
+	-58895, -58873, -58851, -58829, -58807, -58784, -58762, -58740,
+	-58718, -58695, -58673, -58650, -58628, -58605, -58583, -58560,
+	-58538, -58515, -58493, -58470, -58447, -58424, -58402, -58379,
+	-58356, -58333, -58310, -58287, -58264, -58241, -58218, -58195,
+	-58172, -58149, -58125, -58102, -58079, -58056, -58032, -58009,
+	-57986, -57962, -57939, -57915, -57892, -57868, -57844, -57821,
+	-57797, -57773, -57750, -57726, -57702, -57678, -57654, -57630,
+	-57606, -57582, -57558, -57534, -57510, -57486, -57462, -57438,
+	-57414, -57389, -57365, -57341, -57316, -57292, -57268, -57243,
+	-57219, -57194, -57170, -57145, -57120, -57096, -57071, -57046,
+	-57022, -56997, -56972, -56947, -56922, -56897, -56872, -56847,
+	-56822, -56797, -56772, -56747, -56722, -56697, -56671, -56646,
+	-56621, -56595, -56570, -56545, -56519, -56494, -56468, -56443,
+	-56417, -56392, -56366, -56340, -56315, -56289, -56263, -56237,
+	-56212, -56186, -56160, -56134, -56108, -56082, -56056, -56030,
+	-56004, -55978, -55952, -55925, -55899, -55873, -55847, -55820,
+	-55794, -55768, -55741, -55715, -55688, -55662, -55635, -55609,
+	-55582, -55555, -55529, -55502, -55475, -55448, -55422, -55395,
+	-55368, -55341, -55314, -55287, -55260, -55233, -55206, -55179,
+	-55152, -55124, -55097, -55070, -55043, -55015, -54988, -54961,
+	-54933, -54906, -54879, -54851, -54823, -54796, -54768, -54741,
+	-54713, -54685, -54658, -54630, -54602, -54574, -54546, -54519,
+	-54491, -54463, -54435, -54407, -54379, -54351, -54323, -54294,
+	-54266, -54238, -54210, -54182, -54153, -54125, -54097, -54068,
+	-54040, -54011, -53983, -53954, -53926, -53897, -53869, -53840,
+	-53811, -53783, -53754, -53725, -53696, -53667, -53639, -53610,
+	-53581, -53552, -53523, -53494, -53465, -53436, -53407, -53377,
+	-53348, -53319, -53290, -53260, -53231, -53202, -53172, -53143,
+	-53114, -53084, -53055, -53025, -52996, -52966, -52936, -52907,
+	-52877, -52847, -52818, -52788, -52758, -52728, -52698, -52668,
+	-52639, -52609, -52579, -52549, -52518, -52488, -52458, -52428,
+	-52398, -52368, -52338, -52307, -52277, -52247, -52216, -52186,
+	-52155, -52125, -52095, -52064, -52033, -52003, -51972, -51942,
+	-51911, -51880, -51850, -51819, -51788, -51757, -51726, -51695,
+	-51665, -51634, -51603, -51572, -51541, -51510, -51478, -51447,
+	-51416, -51385, -51354, -51323, -51291, -51260, -51229, -51197,
+	-51166, -51134, -51103, -51072, -51040, -51008, -50977, -50945,
+	-50914, -50882, -50850, -50819, -50787, -50755, -50723, -50691,
+	-50660, -50628, -50596, -50564, -50532, -50500, -50468, -50436,
+	-50403, -50371, -50339, -50307, -50275, -50242, -50210, -50178,
+	-50146, -50113, -50081, -50048, -50016, -49983, -49951, -49918,
+	-49886, -49853, -49820, -49788, -49755, -49722, -49690, -49657,
+	-49624, -49591, -49558, -49525, -49492, -49459, -49426, -49393,
+	-49360, -49327, -49294, -49261, -49228, -49195, -49161, -49128,
+	-49095, -49062, -49028, -48995, -48961, -48928, -48895, -48861,
+	-48828, -48794, -48760, -48727, -48693, -48660, -48626, -48592,
+	-48558, -48525, -48491, -48457, -48423, -48389, -48355, -48321,
+	-48288, -48254, -48219, -48185, -48151, -48117, -48083, -48049,
+	-48015, -47981, -47946, -47912, -47878, -47843, -47809, -47775,
+	-47740, -47706, -47671, -47637, -47602, -47568, -47533, -47498,
+	-47464, -47429, -47394, -47360, -47325, -47290, -47255, -47220,
+	-47186, -47151, -47116, -47081, -47046, -47011, -46976, -46941,
+	-46906, -46871, -46835, -46800, -46765, -46730, -46695, -46659,
+	-46624, -46589, -46553, -46518, -46482, -46447, -46411, -46376,
+	-46340, -46305, -46269, -46234, -46198, -46162, -46127, -46091,
+	-46055, -46019, -45984, -45948, -45912, -45876, -45840, -45804,
+	-45768, -45732, -45696, -45660, -45624, -45588, -45552, -45516,
+	-45480, -45443, -45407, -45371, -45335, -45298, -45262, -45226,
+	-45189, -45153, -45116, -45080, -45043, -45007, -44970, -44934,
+	-44897, -44861, -44824, -44787, -44750, -44714, -44677, -44640,
+	-44603, -44567, -44530, -44493, -44456, -44419, -44382, -44345,
+	-44308, -44271, -44234, -44197, -44160, -44122, -44085, -44048,
+	-44011, -43974, -43936, -43899, -43862, -43824, -43787, -43749,
+	-43712, -43675, -43637, -43600, -43562, -43524, -43487, -43449,
+	-43412, -43374, -43336, -43298, -43261, -43223, -43185, -43147,
+	-43110, -43072, -43034, -42996, -42958, -42920, -42882, -42844,
+	-42806, -42768, -42730, -42692, -42653, -42615, -42577, -42539,
+	-42501, -42462, -42424, -42386, -42347, -42309, -42271, -42232,
+	-42194, -42155, -42117, -42078, -42040, -42001, -41962, -41924,
+	-41885, -41846, -41808, -41769, -41730, -41692, -41653, -41614,
+	-41575, -41536, -41497, -41458, -41419, -41381, -41342, -41303,
+	-41263, -41224, -41185, -41146, -41107, -41068, -41029, -40990,
+	-40950, -40911, -40872, -40832, -40793, -40754, -40714, -40675,
+	-40636, -40596, -40557, -40517, -40478, -40438, -40399, -40359,
+	-40319, -40280, -40240, -40200, -40161, -40121, -40081, -40041,
+	-40002, -39962, -39922, -39882, -39842, -39802, -39762, -39722,
+	-39682, -39642, -39602, -39562, -39522, -39482, -39442, -39402,
+	-39362, -39321, -39281, -39241, -39201, -39160, -39120, -39080,
+	-39039, -38999, -38958, -38918, -38878, -38837, -38797, -38756,
+	-38716, -38675, -38634, -38594, -38553, -38512, -38472, -38431,
+	-38390, -38350, -38309, -38268, -38227, -38186, -38146, -38105,
+	-38064, -38023, -37982, -37941, -37900, -37859, -37818, -37777,
+	-37736, -37695, -37653, -37612, -37571, -37530, -37489, -37447,
+	-37406, -37365, -37324, -37282, -37241, -37200, -37158, -37117,
+	-37075, -37034, -36992, -36951, -36909, -36868, -36826, -36785,
+	-36743, -36701, -36660, -36618, -36576, -36535, -36493, -36451,
+	-36409, -36368, -36326, -36284, -36242, -36200, -36158, -36116,
+	-36074, -36032, -35990, -35948, -35906, -35864, -35822, -35780,
+	-35738, -35696, -35654, -35611, -35569, -35527, -35485, -35442,
+	-35400, -35358, -35316, -35273, -35231, -35188, -35146, -35104,
+	-35061, -35019, -34976, -34934, -34891, -34849, -34806, -34763,
+	-34721, -34678, -34635, -34593, -34550, -34507, -34465, -34422,
+	-34379, -34336, -34293, -34251, -34208, -34165, -34122, -34079,
+	-34036, -33993, -33950, -33907, -33864, -33821, -33778, -33735,
+	-33692, -33649, -33605, -33562, -33519, -33476, -33433, -33389,
+	-33346, -33303, -33260, -33216, -33173, -33130, -33086, -33043,
+	-32999, -32956, -32912, -32869, -32826, -32782, -32738, -32695,
+	-32651, -32608, -32564, -32521, -32477, -32433, -32390, -32346,
+	-32302, -32258, -32215, -32171, -32127, -32083, -32039, -31995,
+	-31952, -31908, -31864, -31820, -31776, -31732, -31688, -31644,
+	-31600, -31556, -31512, -31468, -31424, -31379, -31335, -31291,
+	-31247, -31203, -31159, -31114, -31070, -31026, -30982, -30937,
+	-30893, -30849, -30804, -30760, -30715, -30671, -30627, -30582,
+	-30538, -30493, -30449, -30404, -30360, -30315, -30271, -30226,
+	-30181, -30137, -30092, -30047, -30003, -29958, -29913, -29869,
+	-29824, -29779, -29734, -29690, -29645, -29600, -29555, -29510,
+	-29465, -29420, -29375, -29330, -29285, -29241, -29196, -29151,
+	-29105, -29060, -29015, -28970, -28925, -28880, -28835, -28790,
+	-28745, -28699, -28654, -28609, -28564, -28519, -28473, -28428,
+	-28383, -28337, -28292, -28247, -28201, -28156, -28111, -28065,
+	-28020, -27974, -27929, -27883, -27838, -27792, -27747, -27701,
+	-27656, -27610, -27565, -27519, -27473, -27428, -27382, -27336,
+	-27291, -27245, -27199, -27153, -27108, -27062, -27016, -26970,
+	-26925, -26879, -26833, -26787, -26741, -26695, -26649, -26603,
+	-26557, -26511, -26465, -26419, -26373, -26327, -26281, -26235,
+	-26189, -26143, -26097, -26051, -26005, -25959, -25913, -25866,
+	-25820, -25774, -25728, -25681, -25635, -25589, -25543, -25496,
+	-25450, -25404, -25357, -25311, -25265, -25218, -25172, -25125,
+	-25079, -25033, -24986, -24940, -24893, -24847, -24800, -24754,
+	-24707, -24660, -24614, -24567, -24521, -24474, -24427, -24381,
+	-24334, -24287, -24241, -24194, -24147, -24101, -24054, -24007,
+	-23960, -23914, -23867, -23820, -23773, -23726, -23679, -23632,
+	-23586, -23539, -23492, -23445, -23398, -23351, -23304, -23257,
+	-23210, -23163, -23116, -23069, -23022, -22975, -22928, -22881,
+	-22833, -22786, -22739, -22692, -22645, -22598, -22551, -22503,
+	-22456, -22409, -22362, -22314, -22267, -22220, -22173, -22125,
+	-22078, -22031, -21983, -21936, -21889, -21841, -21794, -21746,
+	-21699, -21651, -21604, -21557, -21509, -21462, -21414, -21367,
+	-21319, -21271, -21224, -21176, -21129, -21081, -21034, -20986,
+	-20938, -20891, -20843, -20795, -20748, -20700, -20652, -20605,
+	-20557, -20509, -20461, -20414, -20366, -20318, -20270, -20223,
+	-20175, -20127, -20079, -20031, -19983, -19935, -19888, -19840,
+	-19792, -19744, -19696, -19648, -19600, -19552, -19504, -19456,
+	-19408, -19360, -19312, -19264, -19216, -19168, -19120, -19072,
+	-19024, -18975, -18927, -18879, -18831, -18783, -18735, -18687,
+	-18638, -18590, -18542, -18494, -18446, -18397, -18349, -18301,
+	-18253, -18204, -18156, -18108, -18059, -18011, -17963, -17914,
+	-17866, -17818, -17769, -17721, -17672, -17624, -17576, -17527,
+	-17479, -17430, -17382, -17333, -17285, -17236, -17188, -17139,
+	-17091, -17042, -16994, -16945, -16897, -16848, -16800, -16751,
+	-16702, -16654, -16605, -16557, -16508, -16459, -16411, -16362,
+	-16313, -16265, -16216, -16167, -16118, -16070, -16021, -15972,
+	-15923, -15875, -15826, -15777, -15728, -15680, -15631, -15582,
+	-15533, -15484, -15435, -15387, -15338, -15289, -15240, -15191,
+	-15142, -15093, -15044, -14995, -14946, -14897, -14849, -14800,
+	-14751, -14702, -14653, -14604, -14555, -14506, -14457, -14408,
+	-14359, -14309, -14260, -14211, -14162, -14113, -14064, -14015,
+	-13966, -13917, -13868, -13819, -13769, -13720, -13671, -13622,
+	-13573, -13524, -13474, -13425, -13376, -13327, -13278, -13228,
+	-13179, -13130, -13081, -13031, -12982, -12933, -12884, -12834,
+	-12785, -12736, -12686, -12637, -12588, -12538, -12489, -12440,
+	-12390, -12341, -12292, -12242, -12193, -12143, -12094, -12045,
+	-11995, -11946, -11896, -11847, -11797, -11748, -11699, -11649,
+	-11600, -11550, -11501, -11451, -11402, -11352, -11303, -11253,
+	-11204, -11154, -11105, -11055, -11006, -10956, -10906, -10857,
+	-10807, -10758, -10708, -10658, -10609, -10559, -10510, -10460,
+	-10410, -10361, -10311, -10262, -10212, -10162, -10113, -10063,
+	-10013, -9964, -9914, -9864, -9814, -9765, -9715, -9665,
+	-9616, -9566, -9516, -9466, -9417, -9367, -9317, -9267,
+	-9218, -9168, -9118, -9068, -9019, -8969, -8919, -8869,
+	-8819, -8770, -8720, -8670, -8620, -8570, -8520, -8471,
+	-8421, -8371, -8321, -8271, -8221, -8171, -8122, -8072,
+	-8022, -7972, -7922, -7872, -7822, -7772, -7722, -7672,
+	-7623, -7573, -7523, -7473, -7423, -7373, -7323, -7273,
+	-7223, -7173, -7123, -7073, -7023, -6973, -6923, -6873,
+	-6823, -6773, -6723, -6673, -6623, -6573, -6523, -6473,
+	-6423, -6373, -6323, -6273, -6223, -6173, -6123, -6073,
+	-6023, -5973, -5923, -5873, -5823, -5773, -5722, -5672,
+	-5622, -5572, -5522, -5472, -5422, -5372, -5322, -5272,
+	-5222, -5171, -5121, -5071, -5021, -4971, -4921, -4871,
+	-4821, -4770, -4720, -4670, -4620, -4570, -4520, -4470,
+	-4420, -4369, -4319, -4269, -4219, -4169, -4119, -4068,
+	-4018, -3968, -3918, -3868, -3818, -3767, -3717, -3667,
+	-3617, -3567, -3516, -3466, -3416, -3366, -3316, -3265,
+	-3215, -3165, -3115, -3065, -3014, -2964, -2914, -2864,
+	-2814, -2763, -2713, -2663, -2613, -2562, -2512, -2462,
+	-2412, -2361, -2311, -2261, -2211, -2161, -2110, -2060,
+	-2010, -1960, -1909, -1859, -1809, -1759, -1708, -1658,
+	-1608, -1558, -1507, -1457, -1407, -1357, -1306, -1256,
+	-1206, -1156, -1105, -1055, -1005, -955, -904, -854,
+	-804, -753, -703, -653, -603, -552, -502, -452,
+	-402, -351, -301, -251, -201, -150, -100, -50,
+	0, 50, 100, 150, 201, 251, 301, 351,
+	402, 452, 502, 552, 603, 653, 703, 753,
+	804, 854, 904, 955, 1005, 1055, 1105, 1156,
+	1206, 1256, 1306, 1357, 1407, 1457, 1507, 1558,
+	1608, 1658, 1708, 1759, 1809, 1859, 1909, 1960,
+	2010, 2060, 2110, 2161, 2211, 2261, 2311, 2361,
+	2412, 2462, 2512, 2562, 2613, 2663, 2713, 2763,
+	2814, 2864, 2914, 2964, 3014, 3065, 3115, 3165,
+	3215, 3265, 3316, 3366, 3416, 3466, 3516, 3567,
+	3617, 3667, 3717, 3767, 3818, 3868, 3918, 3968,
+	4018, 4068, 4119, 4169, 4219, 4269, 4319, 4369,
+	4420, 4470, 4520, 4570, 4620, 4670, 4720, 4770,
+	4821, 4871, 4921, 4971, 5021, 5071, 5121, 5171,
+	5222, 5272, 5322, 5372, 5422, 5472, 5522, 5572,
+	5622, 5672, 5722, 5773, 5823, 5873, 5923, 5973,
+	6023, 6073, 6123, 6173, 6223, 6273, 6323, 6373,
+	6423, 6473, 6523, 6573, 6623, 6673, 6723, 6773,
+	6823, 6873, 6923, 6973, 7023, 7073, 7123, 7173,
+	7223, 7273, 7323, 7373, 7423, 7473, 7523, 7573,
+	7623, 7672, 7722, 7772, 7822, 7872, 7922, 7972,
+	8022, 8072, 8122, 8171, 8221, 8271, 8321, 8371,
+	8421, 8471, 8520, 8570, 8620, 8670, 8720, 8770,
+	8819, 8869, 8919, 8969, 9019, 9068, 9118, 9168,
+	9218, 9267, 9317, 9367, 9417, 9466, 9516, 9566,
+	9616, 9665, 9715, 9765, 9814, 9864, 9914, 9964,
+	10013, 10063, 10113, 10162, 10212, 10262, 10311, 10361,
+	10410, 10460, 10510, 10559, 10609, 10658, 10708, 10758,
+	10807, 10857, 10906, 10956, 11006, 11055, 11105, 11154,
+	11204, 11253, 11303, 11352, 11402, 11451, 11501, 11550,
+	11600, 11649, 11699, 11748, 11797, 11847, 11896, 11946,
+	11995, 12045, 12094, 12143, 12193, 12242, 12292, 12341,
+	12390, 12440, 12489, 12538, 12588, 12637, 12686, 12736,
+	12785, 12834, 12884, 12933, 12982, 13031, 13081, 13130,
+	13179, 13228, 13278, 13327, 13376, 13425, 13474, 13524,
+	13573, 13622, 13671, 13720, 13769, 13819, 13868, 13917,
+	13966, 14015, 14064, 14113, 14162, 14211, 14260, 14309,
+	14359, 14408, 14457, 14506, 14555, 14604, 14653, 14702,
+	14751, 14800, 14849, 14897, 14946, 14995, 15044, 15093,
+	15142, 15191, 15240, 15289, 15338, 15387, 15435, 15484,
+	15533, 15582, 15631, 15680, 15728, 15777, 15826, 15875,
+	15923, 15972, 16021, 16070, 16118, 16167, 16216, 16265,
+	16313, 16362, 16411, 16459, 16508, 16557, 16605, 16654,
+	16702, 16751, 16800, 16848, 16897, 16945, 16994, 17042,
+	17091, 17139, 17188, 17236, 17285, 17333, 17382, 17430,
+	17479, 17527, 17576, 17624, 17672, 17721, 17769, 17818,
+	17866, 17914, 17963, 18011, 18059, 18108, 18156, 18204,
+	18253, 18301, 18349, 18397, 18446, 18494, 18542, 18590,
+	18638, 18687, 18735, 18783, 18831, 18879, 18927, 18975,
+	19024, 19072, 19120, 19168, 19216, 19264, 19312, 19360,
+	19408, 19456, 19504, 19552, 19600, 19648, 19696, 19744,
+	19792, 19840, 19888, 19935, 19983, 20031, 20079, 20127,
+	20175, 20223, 20270, 20318, 20366, 20414, 20461, 20509,
+	20557, 20605, 20652, 20700, 20748, 20795, 20843, 20891,
+	20938, 20986, 21034, 21081, 21129, 21176, 21224, 21271,
+	21319, 21367, 21414, 21462, 21509, 21557, 21604, 21651,
+	21699, 21746, 21794, 21841, 21889, 21936, 21983, 22031,
+	22078, 22125, 22173, 22220, 22267, 22314, 22362, 22409,
+	22456, 22503, 22551, 22598, 22645, 22692, 22739, 22786,
+	22833, 22881, 22928, 22975, 23022, 23069, 23116, 23163,
+	23210, 23257, 23304, 23351, 23398, 23445, 23492, 23539,
+	23586, 23632, 23679, 23726, 23773, 23820, 23867, 23914,
+	23960, 24007, 24054, 24101, 24147, 24194, 24241, 24287,
+	24334, 24381, 24427, 24474, 24521, 24567, 24614, 24660,
+	24707, 24754, 24800, 24847, 24893, 24940, 24986, 25033,
+	25079, 25125, 25172, 25218, 25265, 25311, 25357, 25404,
+	25450, 25496, 25543, 25589, 25635, 25681, 25728, 25774,
+	25820, 25866, 25913, 25959, 26005, 26051, 26097, 26143,
+	26189, 26235, 26281, 26327, 26373, 26419, 26465, 26511,
+	26557, 26603, 26649, 26695, 26741, 26787, 26833, 26879,
+	26925, 26970, 27016, 27062, 27108, 27153, 27199, 27245,
+	27291, 27336, 27382, 27428, 27473, 27519, 27565, 27610,
+	27656, 27701, 27747, 27792, 27838, 27883, 27929, 27974,
+	28020, 28065, 28111, 28156, 28201, 28247, 28292, 28337,
+	28383, 28428, 28473, 28519, 28564, 28609, 28654, 28699,
+	28745, 28790, 28835, 28880, 28925, 28970, 29015, 29060,
+	29105, 29151, 29196, 29241, 29285, 29330, 29375, 29420,
+	29465, 29510, 29555, 29600, 29645, 29690, 29734, 29779,
+	29824, 29869, 29913, 29958, 30003, 30047, 30092, 30137,
+	30181, 30226, 30271, 30315, 30360, 30404, 30449, 30493,
+	30538, 30582, 30627, 30671, 30715, 30760, 30804, 30849,
+	30893, 30937, 30982, 31026, 31070, 31114, 31159, 31203,
+	31247, 31291, 31335, 31379, 31424, 31468, 31512, 31556,
+	31600, 31644, 31688, 31732, 31776, 31820, 31864, 31908,
+	31952, 31995, 32039, 32083, 32127, 32171, 32215, 32258,
+	32302, 32346, 32390, 32433, 32477, 32521, 32564, 32608,
+	32651, 32695, 32738, 32782, 32826, 32869, 32912, 32956,
+	32999, 33043, 33086, 33130, 33173, 33216, 33260, 33303,
+	33346, 33389, 33433, 33476, 33519, 33562, 33605, 33649,
+	33692, 33735, 33778, 33821, 33864, 33907, 33950, 33993,
+	34036, 34079, 34122, 34165, 34208, 34251, 34293, 34336,
+	34379, 34422, 34465, 34507, 34550, 34593, 34635, 34678,
+	34721, 34763, 34806, 34849, 34891, 34934, 34976, 35019,
+	35061, 35104, 35146, 35188, 35231, 35273, 35316, 35358,
+	35400, 35442, 35485, 35527, 35569, 35611, 35654, 35696,
+	35738, 35780, 35822, 35864, 35906, 35948, 35990, 36032,
+	36074, 36116, 36158, 36200, 36242, 36284, 36326, 36368,
+	36409, 36451, 36493, 36535, 36576, 36618, 36660, 36701,
+	36743, 36785, 36826, 36868, 36909, 36951, 36992, 37034,
+	37075, 37117, 37158, 37200, 37241, 37282, 37324, 37365,
+	37406, 37447, 37489, 37530, 37571, 37612, 37653, 37695,
+	37736, 37777, 37818, 37859, 37900, 37941, 37982, 38023,
+	38064, 38105, 38146, 38186, 38227, 38268, 38309, 38350,
+	38390, 38431, 38472, 38512, 38553, 38594, 38634, 38675,
+	38716, 38756, 38797, 38837, 38878, 38918, 38958, 38999,
+	39039, 39080, 39120, 39160, 39201, 39241, 39281, 39321,
+	39362, 39402, 39442, 39482, 39522, 39562, 39602, 39642,
+	39682, 39722, 39762, 39802, 39842, 39882, 39922, 39962,
+	40002, 40041, 40081, 40121, 40161, 40200, 40240, 40280,
+	40319, 40359, 40399, 40438, 40478, 40517, 40557, 40596,
+	40636, 40675, 40714, 40754, 40793, 40832, 40872, 40911,
+	40950, 40990, 41029, 41068, 41107, 41146, 41185, 41224,
+	41263, 41303, 41342, 41381, 41419, 41458, 41497, 41536,
+	41575, 41614, 41653, 41692, 41730, 41769, 41808, 41846,
+	41885, 41924, 41962, 42001, 42040, 42078, 42117, 42155,
+	42194, 42232, 42271, 42309, 42347, 42386, 42424, 42462,
+	42501, 42539, 42577, 42615, 42653, 42692, 42730, 42768,
+	42806, 42844, 42882, 42920, 42958, 42996, 43034, 43072,
+	43110, 43147, 43185, 43223, 43261, 43298, 43336, 43374,
+	43412, 43449, 43487, 43524, 43562, 43600, 43637, 43675,
+	43712, 43749, 43787, 43824, 43862, 43899, 43936, 43974,
+	44011, 44048, 44085, 44122, 44160, 44197, 44234, 44271,
+	44308, 44345, 44382, 44419, 44456, 44493, 44530, 44567,
+	44603, 44640, 44677, 44714, 44750, 44787, 44824, 44861,
+	44897, 44934, 44970, 45007, 45043, 45080, 45116, 45153,
+	45189, 45226, 45262, 45298, 45335, 45371, 45407, 45443,
+	45480, 45516, 45552, 45588, 45624, 45660, 45696, 45732,
+	45768, 45804, 45840, 45876, 45912, 45948, 45984, 46019,
+	46055, 46091, 46127, 46162, 46198, 46234, 46269, 46305,
+	46340, 46376, 46411, 46447, 46482, 46518, 46553, 46589,
+	46624, 46659, 46695, 46730, 46765, 46800, 46835, 46871,
+	46906, 46941, 46976, 47011, 47046, 47081, 47116, 47151,
+	47186, 47220, 47255, 47290, 47325, 47360, 47394, 47429,
+	47464, 47498, 47533, 47568, 47602, 47637, 47671, 47706,
+	47740, 47775, 47809, 47843, 47878, 47912, 47946, 47981,
+	48015, 48049, 48083, 48117, 48151, 48185, 48219, 48254,
+	48288, 48321, 48355, 48389, 48423, 48457, 48491, 48525,
+	48558, 48592, 48626, 48660, 48693, 48727, 48760, 48794,
+	48828, 48861, 48895, 48928, 48961, 48995, 49028, 49062,
+	49095, 49128, 49161, 49195, 49228, 49261, 49294, 49327,
+	49360, 49393, 49426, 49459, 49492, 49525, 49558, 49591,
+	49624, 49657, 49690, 49722, 49755, 49788, 49820, 49853,
+	49886, 49918, 49951, 49983, 50016, 50048, 50081, 50113,
+	50146, 50178, 50210, 50242, 50275, 50307, 50339, 50371,
+	50403, 50436, 50468, 50500, 50532, 50564, 50596, 50628,
+	50660, 50691, 50723, 50755, 50787, 50819, 50850, 50882,
+	50914, 50945, 50977, 51008, 51040, 51072, 51103, 51134,
+	51166, 51197, 51229, 51260, 51291, 51323, 51354, 51385,
+	51416, 51447, 51478, 51510, 51541, 51572, 51603, 51634,
+	51665, 51695, 51726, 51757, 51788, 51819, 51850, 51880,
+	51911, 51942, 51972, 52003, 52033, 52064, 52095, 52125,
+	52155, 52186, 52216, 52247, 52277, 52307, 52338, 52368,
+	52398, 52428, 52458, 52488, 52518, 52549, 52579, 52609,
+	52639, 52668, 52698, 52728, 52758, 52788, 52818, 52847,
+	52877, 52907, 52936, 52966, 52996, 53025, 53055, 53084,
+	53114, 53143, 53172, 53202, 53231, 53260, 53290, 53319,
+	53348, 53377, 53407, 53436, 53465, 53494, 53523, 53552,
+	53581, 53610, 53639, 53667, 53696, 53725, 53754, 53783,
+	53811, 53840, 53869, 53897, 53926, 53954, 53983, 54011,
+	54040, 54068, 54097, 54125, 54153, 54182, 54210, 54238,
+	54266, 54294, 54323, 54351, 54379, 54407, 54435, 54463,
+	54491, 54519, 54546, 54574, 54602, 54630, 54658, 54685,
+	54713, 54741, 54768, 54796, 54823, 54851, 54879, 54906,
+	54933, 54961, 54988, 55015, 55043, 55070, 55097, 55124,
+	55152, 55179, 55206, 55233, 55260, 55287, 55314, 55341,
+	55368, 55395, 55422, 55448, 55475, 55502, 55529, 55555,
+	55582, 55609, 55635, 55662, 55688, 55715, 55741, 55768,
+	55794, 55820, 55847, 55873, 55899, 55925, 55952, 55978,
+	56004, 56030, 56056, 56082, 56108, 56134, 56160, 56186,
+	56212, 56237, 56263, 56289, 56315, 56340, 56366, 56392,
+	56417, 56443, 56468, 56494, 56519, 56545, 56570, 56595,
+	56621, 56646, 56671, 56697, 56722, 56747, 56772, 56797,
+	56822, 56847, 56872, 56897, 56922, 56947, 56972, 56997,
+	57022, 57046, 57071, 57096, 57120, 57145, 57170, 57194,
+	57219, 57243, 57268, 57292, 57316, 57341, 57365, 57389,
+	57414, 57438, 57462, 57486, 57510, 57534, 57558, 57582,
+	57606, 57630, 57654, 57678, 57702, 57726, 57750, 57773,
+	57797, 57821, 57844, 57868, 57892, 57915, 57939, 57962,
+	57986, 58009, 58032, 58056, 58079, 58102, 58125, 58149,
+	58172, 58195, 58218, 58241, 58264, 58287, 58310, 58333,
+	58356, 58379, 58402, 58424, 58447, 58470, 58493, 58515,
+	58538, 58560, 58583, 58605, 58628, 58650, 58673, 58695,
+	58718, 58740, 58762, 58784, 58807, 58829, 58851, 58873,
+	58895, 58917, 58939, 58961, 58983, 59005, 59027, 59049,
+	59070, 59092, 59114, 59135, 59157, 59179, 59200, 59222,
+	59243, 59265, 59286, 59308, 59329, 59350, 59372, 59393,
+	59414, 59435, 59457, 59478, 59499, 59520, 59541, 59562,
+	59583, 59604, 59625, 59645, 59666, 59687, 59708, 59728,
+	59749, 59770, 59790, 59811, 59831, 59852, 59872, 59893,
+	59913, 59934, 59954, 59974, 59994, 60015, 60035, 60055,
+	60075, 60095, 60115, 60135, 60155, 60175, 60195, 60215,
+	60235, 60254, 60274, 60294, 60313, 60333, 60353, 60372,
+	60392, 60411, 60431, 60450, 60470, 60489, 60508, 60528,
+	60547, 60566, 60585, 60604, 60624, 60643, 60662, 60681,
+	60700, 60719, 60737, 60756, 60775, 60794, 60813, 60831,
+	60850, 60869, 60887, 60906, 60924, 60943, 60961, 60980,
+	60998, 61017, 61035, 61053, 61071, 61090, 61108, 61126,
+	61144, 61162, 61180, 61198, 61216, 61234, 61252, 61270,
+	61288, 61305, 61323, 61341, 61359, 61376, 61394, 61411,
+	61429, 61446, 61464, 61481, 61499, 61516, 61533, 61551,
+	61568, 61585, 61602, 61619, 61637, 61654, 61671, 61688,
+	61705, 61721, 61738, 61755, 61772, 61789, 61805, 61822,
+	61839, 61855, 61872, 61889, 61905, 61922, 61938, 61954,
+	61971, 61987, 62003, 62020, 62036, 62052, 62068, 62084,
+	62100, 62117, 62133, 62148, 62164, 62180, 62196, 62212,
+	62228, 62244, 62259, 62275, 62291, 62306, 62322, 62337,
+	62353, 62368, 62384, 62399, 62414, 62430, 62445, 62460,
+	62475, 62491, 62506, 62521, 62536, 62551, 62566, 62581,
+	62596, 62610, 62625, 62640, 62655, 62670, 62684, 62699,
+	62714, 62728, 62743, 62757, 62772, 62786, 62800, 62815,
+	62829, 62843, 62858, 62872, 62886, 62900, 62914, 62928,
+	62942, 62956, 62970, 62984, 62998, 63012, 63026, 63039,
+	63053, 63067, 63080, 63094, 63108, 63121, 63135, 63148,
+	63162, 63175, 63188, 63202, 63215, 63228, 63241, 63254,
+	63268, 63281, 63294, 63307, 63320, 63333, 63346, 63358,
+	63371, 63384, 63397, 63410, 63422, 63435, 63447, 63460,
+	63473, 63485, 63498, 63510, 63522, 63535, 63547, 63559,
+	63571, 63584, 63596, 63608, 63620, 63632, 63644, 63656,
+	63668, 63680, 63692, 63704, 63715, 63727, 63739, 63750,
+	63762, 63774, 63785, 63797, 63808, 63820, 63831, 63842,
+	63854, 63865, 63876, 63888, 63899, 63910, 63921, 63932,
+	63943, 63954, 63965, 63976, 63987, 63998, 64009, 64019,
+	64030, 64041, 64051, 64062, 64073, 64083, 64094, 64104,
+	64115, 64125, 64135, 64146, 64156, 64166, 64176, 64186,
+	64197, 64207, 64217, 64227, 64237, 64247, 64257, 64266,
+	64276, 64286, 64296, 64305, 64315, 64325, 64334, 64344,
+	64353, 64363, 64372, 64382, 64391, 64401, 64410, 64419,
+	64428, 64437, 64447, 64456, 64465, 64474, 64483, 64492,
+	64501, 64510, 64518, 64527, 64536, 64545, 64553, 64562,
+	64571, 64579, 64588, 64596, 64605, 64613, 64622, 64630,
+	64638, 64646, 64655, 64663, 64671, 64679, 64687, 64695,
+	64703, 64711, 64719, 64727, 64735, 64743, 64751, 64758,
+	64766, 64774, 64781, 64789, 64796, 64804, 64811, 64819,
+	64826, 64834, 64841, 64848, 64855, 64863, 64870, 64877,
+	64884, 64891, 64898, 64905, 64912, 64919, 64926, 64933,
+	64939, 64946, 64953, 64959, 64966, 64973, 64979, 64986,
+	64992, 64999, 65005, 65011, 65018, 65024, 65030, 65036,
+	65043, 65049, 65055, 65061, 65067, 65073, 65079, 65085,
+	65091, 65096, 65102, 65108, 65114, 65119, 65125, 65131,
+	65136, 65142, 65147, 65153, 65158, 65163, 65169, 65174,
+	65179, 65184, 65190, 65195, 65200, 65205, 65210, 65215,
+	65220, 65225, 65230, 65235, 65239, 65244, 65249, 65253,
+	65258, 65263, 65267, 65272, 65276, 65281, 65285, 65290,
+	65294, 65298, 65302, 65307, 65311, 65315, 65319, 65323,
+	65327, 65331, 65335, 65339, 65343, 65347, 65350, 65354,
+	65358, 65362, 65365, 65369, 65372, 65376, 65379, 65383,
+	65386, 65390, 65393, 65396, 65400, 65403, 65406, 65409,
+	65412, 65415, 65418, 65421, 65424, 65427, 65430, 65433,
+	65436, 65438, 65441, 65444, 65446, 65449, 65452, 65454,
+	65457, 65459, 65461, 65464, 65466, 65468, 65471, 65473,
+	65475, 65477, 65479, 65481, 65483, 65485, 65487, 65489,
+	65491, 65493, 65495, 65496, 65498, 65500, 65501, 65503,
+	65505, 65506, 65508, 65509, 65511, 65512, 65513, 65515,
+	65516, 65517, 65518, 65519, 65520, 65521, 65522, 65523,
+	65524, 65525, 65526, 65527, 65528, 65529, 65529, 65530,
 	65531, 65531, 65532, 65532, 65533, 65533, 65534, 65534,
 	65534, 65535, 65535, 65535, 65535, 65535, 65535, 65535
 };
-#endif
-
 
+fixed_t *finecosine = &finesine[FINEANGLES/4];
+#endif
 
 angle_t tantoangle[2049] =
 {
@@ -2225,9 +2225,6 @@ angle_t tantoangle[2049] =
 	536870912
 };
 
-
-#ifdef NEED_FIXED_VECTOR
-
 static angle_t fineacon[65536*2] = {
 	  ANGLE_MAX, 2143707442, 2142143280, 2140943052, 2139931208, 2139039753, 2138233813, 2137492672, 2136802831, 2136154917, 2135542102, 2134959233, 2134402306, 2133868139, 2133354148, 2132858208,
 	 2132378539, 2131913638, 2131462220, 2131023174, 2130595537, 2130178462, 2129771202, 2129373097, 2128983555, 2128602046, 2128228092, 2127861261, 2127501162, 2127147436, 2126799757, 2126457825,
@@ -10706,5 +10703,3 @@ void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z)
 	M(3, 3) = FRACUNIT;
 #undef M
 }
-
-#endif
diff --git a/src/tables.h b/src/tables.h
index 219d668b9dac5bb01af79de80adb7d5106de78bc..d7ec589dad20d4f5cd9fdbb781c3ee3e82de294c 100644
--- a/src/tables.h
+++ b/src/tables.h
@@ -96,9 +96,6 @@ FUNCMATH angle_t FixedAngle(fixed_t fa);
 // and with a factor, with +factor for (fa/factor) and -factor for (fa*factor)
 FUNCMATH angle_t FixedAngleC(fixed_t fa, fixed_t factor);
 
-
-#ifdef NEED_FIXED_VECTOR
-
 /// The FixedAcos function
 FUNCMATH angle_t FixedAcos(fixed_t x);
 
@@ -112,8 +109,6 @@ void FV3_Rotate(vector3_t *rotVec, const vector3_t *axisVec, const angle_t angle
 /// Fixed Point Matrix functions
 void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z);
 
-#endif // defined NEED_FIXED_VECTOR
-
 // The table values in tables.c are calculated with this many fractional bits.
 #define FINE_FRACBITS 16
 
diff --git a/src/tmap.nas b/src/tmap.nas
index 6d1629c20d0e9d428154a5117e47cb93bce13262..dbe64806dbede93a24b54b08c9dd3b346ab52dcf 100644
--- a/src/tmap.nas
+++ b/src/tmap.nas
@@ -17,7 +17,7 @@
 [BITS 32]
 
 %define FRACBITS 16
-%define TRANSPARENTPIXEL 247
+%define TRANSPARENTPIXEL 255
 
 %ifdef LINUX
 %macro cextern 1
diff --git a/src/tmap_mmx.nas b/src/tmap_mmx.nas
index 928916668e4b1af6dedfe401a52fe3107d79fa4f..758cd439530ddb65a03605dfb03cbe72561a6f2c 100644
--- a/src/tmap_mmx.nas
+++ b/src/tmap_mmx.nas
@@ -18,7 +18,7 @@
 [BITS 32]
 
 %define FRACBITS 16
-%define TRANSPARENTPIXEL 247
+%define TRANSPARENTPIXEL 255
 
 %ifdef LINUX
 %macro cextern 1
diff --git a/src/v_video.c b/src/v_video.c
index 524c15cc702311b2ca4f26ad417dd37fdee93aa0..c5afd783f0ccb4c4cd00f472c1fad118e34e6112 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -366,7 +366,7 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t
 	}
 	if (alphalevel)
 	{
-		v_translevel = ((alphalevel)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		v_translevel = transtables + ((alphalevel-1)<<FF_TRANSSHIFT);
 		patchdrawfunc = translucentpdraw;
 	}
 
@@ -1869,7 +1869,7 @@ void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param)
 		angle_t disStart = (leveltime * 128) & FINEMASK; // in 0 to FINEANGLE
 		INT32 newpix;
 		INT32 sine;
-		//UINT8 *transme = ((tr_trans50)<<FF_TRANSSHIFT) + transtables;
+		//UINT8 *transme = transtables + ((tr_trans50-1)<<FF_TRANSSHIFT);
 
 		for (y = yoffset; y < yoffset+height; y++)
 		{
@@ -1926,7 +1926,7 @@ Unoptimized version
 		INT32 x, y;
 
 		// TODO: Add a postimg_param so that we can pick the translucency level...
-		UINT8 *transme = ((param)<<FF_TRANSSHIFT) - 0x10000 + transtables;
+		UINT8 *transme = transtables + ((param-1)<<FF_TRANSSHIFT);
 
 		for (y = yoffset; y < yoffset+height; y++)
 		{
diff --git a/src/w_wad.h b/src/w_wad.h
index 614b7e4aec8c8b9bc4c16c9703c9735ed84006f8..d283c54a03b80af1f3fbe9a2b1c26250e63c52c6 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -16,8 +16,6 @@
 
 #ifdef HWRENDER
 #include "hardware/hw_data.h"
-#else
-typedef void GLPatch_t;
 #endif
 
 #ifdef __GNUG__
diff --git a/src/win32/CMakeLists.txt b/src/win32/CMakeLists.txt
index 94c198299add6162c63a69324207ba048d73cf01..39b01588b28c622a65f40ea63f9b2e541df220ec 100644
--- a/src/win32/CMakeLists.txt
+++ b/src/win32/CMakeLists.txt
@@ -1,11 +1,18 @@
-add_executable(${SRB2_WIN_EXE_NAME} EXCLUDE_FROM_ALL
-	${SRB2_CORE_SOURCES}
-	${SRB2_CORE_HEADERS}
-	${SRB2_LUA_SOURCES}
-	${SRB2_LUA_HEADERS}
-	${SRB2_BLUA_SOURCES}
-	${SRB2_BLUA_HEADERS})
-
-target_compile_definitions(${SRB2_WIN_EXE_NAME} PRIVATE
+file(GLOB SRB2_WIN_SOURCES *.c *.h *.rc)
+
+if(${SRB2_CONFIG_HWRENDER})
+	set(SRB2_WIN_SOURCES ${SRB2_WIN_SOURCES} ${SRB2_HWRENDER_SOURCES} ${SRB2_HWRENDER_HEADERS})
+	set(SRB2_WIN_SOURCES ${SRB2_WIN_SOURCES} ${SRB2_R_OPENGL_SOURCES} ${SRB2_R_OPENGL_HEADERS})
+endif()
+
+add_executable(SRB2DD EXCLUDE_FROM_ALL WIN32
+	${SRB2_WIN_SOURCES}
+)
+
+target_compile_definitions(SRB2DD PRIVATE
 	-D_WINDOWS
-)
\ No newline at end of file
+)
+
+set_target_properties(SRB2DD PROPERTIES OUTPUT_NAME ${SRB2_WIN_EXE_NAME})
+
+target_link_libraries(SRB2DD PRIVATE SRB2Core)
diff --git a/tools/anglechk.c b/tools/anglechk.c
index bb9c4d9ea5cba9636ee027fe0c2e573b1897d926..4a67069bf744772082afeac5d8875991f2075903 100644
--- a/tools/anglechk.c
+++ b/tools/anglechk.c
@@ -351,6 +351,13 @@ int main(int argc, char** argv)
 	return 0;
 }
 
+static void *cpu_cpy(void *dest, const void *src, size_t n)
+{
+	return memcpy(dest, src, n);
+}
+
+void *(*M_Memcpy)(void* dest, const void* src, size_t n) = cpu_cpy;
+
 void I_Error(const char *error, ...)
 {
 	(void)error;