diff --git a/.travis.yml b/.travis.yml
index 54c5901d07c591f1a3abf2872d18a8d448ab675a..9fd65786f78d723f506a1873ed53fab755893676 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -30,8 +30,8 @@ addons:
 
 before_script:
   - mkdir -p $HOME/srb2_cache
-  - wget --verbose --server-response -c http://rosenthalcastle.org/srb2/SRB2-v2114-assets.7z -O $HOME/srb2_cache/SRB2-v2114-assets.7z
-  - 7z x $HOME/srb2_cache/SRB2-v2114-assets.7z -oassets
+  - wget --verbose --server-response -c http://rosenthalcastle.org/srb2/SRB2-v2115-assets.7z -O $HOME/srb2_cache/SRB2-v2115-assets.7z
+  - 7z x $HOME/srb2_cache/SRB2-v2115-assets.7z -oassets
   - mkdir build
   - cd build
   - cmake ..
diff --git a/src/am_map.c b/src/am_map.c
index 97b7c51642bbea4d87d22d197cd46ed15d986f26..847e517fba5c99ef40ceb1a468517f3841a7e721 100644
--- a/src/am_map.c
+++ b/src/am_map.c
@@ -15,6 +15,7 @@
 #include "am_map.h"
 #include "g_input.h"
 #include "p_local.h"
+#include "p_slopes.h"
 #include "v_video.h"
 #include "i_video.h"
 #include "r_state.h"
@@ -996,6 +997,10 @@ static inline void AM_drawWalls(void)
 {
 	size_t i;
 	static mline_t l;
+#ifdef ESLOPE
+	fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
+	fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
+#endif
 
 	for (i = 0; i < numlines; i++)
 	{
@@ -1003,6 +1008,22 @@ static inline void AM_drawWalls(void)
 		l.a.y = lines[i].v1->y;
 		l.b.x = lines[i].v2->x;
 		l.b.y = lines[i].v2->y;
+#ifdef ESLOPE
+#define SLOPEPARAMS(slope, end1, end2, normalheight) \
+		if (slope) { \
+			end1 = P_GetZAt(slope, l.a.x, l.a.y); \
+			end2 = P_GetZAt(slope, l.b.x, l.b.y); \
+		} else \
+			end1 = end2 = normalheight;
+
+		SLOPEPARAMS(lines[i].frontsector->f_slope, frontf1, frontf2, lines[i].frontsector->floorheight)
+		SLOPEPARAMS(lines[i].frontsector->c_slope, frontc1, frontc2, lines[i].frontsector->ceilingheight)
+		if (lines[i].backsector) {
+			SLOPEPARAMS(lines[i].backsector->f_slope, backf1,  backf2,  lines[i].backsector->floorheight)
+			SLOPEPARAMS(lines[i].backsector->c_slope, backc1,  backc2,  lines[i].backsector->ceilingheight)
+		}
+#undef SLOPEPARAMS
+#endif
 
 //		AM_drawMline(&l, GRAYS + 3); // Old, everything-is-gray automap
 		if (!lines[i].backsector) // 1-sided
@@ -1016,11 +1037,19 @@ static inline void AM_drawWalls(void)
 				AM_drawMline(&l, WALLCOLORS+lightlev);
 			}
 		}
+#ifdef ESLOPE
+		else if ((backf1 == backc1 && backf2 == backc2) // Back is thok barrier
+				 || (frontf1 == frontc1 && frontf2 == frontc2)) // Front is thok barrier
+		{
+			if (backf1 == backc1 && backf2 == backc2
+				&& frontf1 == frontc1 && frontf2 == frontc2) // BOTH are thok barriers
+#else
 		else if (lines[i].backsector->floorheight == lines[i].backsector->ceilingheight // Back is thok barrier
 				 || lines[i].frontsector->floorheight == lines[i].frontsector->ceilingheight) // Front is thok barrier
 		{
 			if (lines[i].backsector->floorheight == lines[i].backsector->ceilingheight
 				&& lines[i].frontsector->floorheight == lines[i].frontsector->ceilingheight) // BOTH are thok barriers
+#endif
 			{
 				if (lines[i].flags & ML_NOCLIMB)
 				{
@@ -1046,12 +1075,20 @@ static inline void AM_drawWalls(void)
 		else
 		{
 			if (lines[i].flags & ML_NOCLIMB) {
+#ifdef ESLOPE
+				if (backf1 != frontf1 || backf2 != frontf2) {
+#else
 				if (lines[i].backsector->floorheight
 						!= lines[i].frontsector->floorheight) {
+#endif
 					AM_drawMline(&l, NOCLIMBFDWALLCOLORS + lightlev); // floor level change
 				}
+#ifdef ESLOPE
+				else if (backc1 != frontc1 || backc2 != frontc2) {
+#else
 				else if (lines[i].backsector->ceilingheight
 						!= lines[i].frontsector->ceilingheight) {
+#endif
 					AM_drawMline(&l, NOCLIMBCDWALLCOLORS+lightlev); // ceiling level change
 				}
 				else {
@@ -1060,12 +1097,20 @@ static inline void AM_drawWalls(void)
 			}
 			else
 			{
+#ifdef ESLOPE
+				if (backf1 != frontf1 || backf2 != frontf2) {
+#else
 				if (lines[i].backsector->floorheight
 						!= lines[i].frontsector->floorheight) {
+#endif
 					AM_drawMline(&l, FDWALLCOLORS + lightlev); // floor level change
 				}
+#ifdef ESLOPE
+				else if (backc1 != frontc1 || backc2 != frontc2) {
+#else
 				else if (lines[i].backsector->ceilingheight
 						!= lines[i].frontsector->ceilingheight) {
+#endif
 					AM_drawMline(&l, CDWALLCOLORS+lightlev); // ceiling level change
 				}
 				else {
diff --git a/src/config.h.in b/src/config.h.in
index eef4fec1314a44baa2ddaf1f59cb8f460dda9c9f..f95a0e975b0fc185de6ab8f54636f0eaff73236d 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -29,14 +29,14 @@
 #else
 
 /* Manually defined asset hashes for non-CMake builds
- * Last updated 2000 / 00 / 00
+ * Last updated 2015 / 05 / 03
  */
 #define ASSET_HASH_SRB2_SRB   "c1b9577687f8a795104aef4600720ea7"
 #define ASSET_HASH_ZONES_DTA  "303838c6c534d9540288360fa49cca60"
 #define ASSET_HASH_PLAYER_DTA "cfca0f1c73023cbbd8f844f45480f799"
 #define ASSET_HASH_RINGS_DTA  "85901ad4bf94637e5753d2ac2c03ea26"
 #ifdef USE_PATCH_DTA
-#define ASSET_HASH_PATCH_DTA  "0c66790502e648bfce90fdc5bb15722e"
+#define ASSET_HASH_PATCH_DTA  "6db9bd55c2f9b04123740ad71ea6b841"
 #endif
 
 #endif
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 5eb35283414b7f807249df101c14d4048bb1251e..b4ba92182aa549375a4487491cb9326e5175102b 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -597,7 +597,9 @@ void D_RegisterClientCommands(void)
 	CV_RegisterVar(&cv_gif_optimize);
 	CV_RegisterVar(&cv_gif_downscale);
 
+#ifdef WALLSPLATS
 	CV_RegisterVar(&cv_splats);
+#endif
 
 	// register these so it is saved to config
 	if ((username = I_GetUserName()))
@@ -808,7 +810,7 @@ static boolean IsNameGood(char *name, INT32 playernum)
 			else if (len == 1) // Agh!
 			{
 				// Last ditch effort...
-				sprintf(name, "%d", M_Random() & 7);
+				sprintf(name, "%d", M_RandomKey(10));
 				if (!IsNameGood (name, playernum))
 					return false;
 			}
@@ -3583,7 +3585,7 @@ retryscramble:
 		for (i = 0; i < playercount; i++)
 		{
 			if (repick)
-				newteam = (INT16)((M_Random() % 2) + 1);
+				newteam = (INT16)((M_RandomByte() % 2) + 1);
 
 			// One team has the most players they can get, assign the rest to the other team.
 			if (red == maxcomposition || blue == maxcomposition)
@@ -3628,7 +3630,7 @@ retryscramble:
 		{
 			if (repick)
 			{
-				newteam = (INT16)((M_Random() % 2) + 1);
+				newteam = (INT16)((M_RandomByte() % 2) + 1);
 				repick = false;
 			}
 			else
diff --git a/src/d_netcmd.h b/src/d_netcmd.h
index 31a7cf81864bd7872e2752ea6c264cbba6c43303..42ac4c054b65e636e4462aaccfde1243436e3008 100644
--- a/src/d_netcmd.h
+++ b/src/d_netcmd.h
@@ -81,7 +81,9 @@ extern consvar_t cv_useranalog, cv_useranalog2;
 extern consvar_t cv_analog, cv_analog2;
 
 extern consvar_t cv_netstat;
+#ifdef WALLSPLATS
 extern consvar_t cv_splats;
+#endif
 
 extern consvar_t cv_countdowntime;
 extern consvar_t cv_runscripts;
diff --git a/src/g_game.c b/src/g_game.c
index 6012f4fcd472b4c61c04236a813a7929873818c8..da1eab2ea6f900a1454daf757694d788ebe3eeeb 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -2350,7 +2350,7 @@ mapthing_t *G_FindCTFStart(INT32 playernum)
 		return NULL;
 	}
 
-	if ((!players[playernum].ctfteam && numredctfstarts && (!numbluectfstarts || P_Random() & 1)) || players[playernum].ctfteam == 1) //red
+	if ((!players[playernum].ctfteam && numredctfstarts && (!numbluectfstarts || P_RandomChance(FRACUNIT/2))) || players[playernum].ctfteam == 1) //red
 	{
 		if (!numredctfstarts)
 		{
@@ -5488,7 +5488,7 @@ ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void)
 		UINT8 i;
 		WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
 		for (i = 0; i < 16; i++, p++)
-			*p = P_Random(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
+			*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
 #else
 		WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
 		md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file.
@@ -5570,7 +5570,7 @@ boolean G_CheckDemoStatus(void)
 		UINT8 i;
 		WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
 		for (i = 0; i < 16; i++, p++)
-			*p = P_Random(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
+			*p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct.
 #else
 		WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker
 		md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file.
diff --git a/src/hardware/hw3sound.c b/src/hardware/hw3sound.c
index efc1d247b5191737e005d0a61c7b76d27cf6c438..c68430921fa4053b5e3fc96fe23f94804291a0ea 100644
--- a/src/hardware/hw3sound.c
+++ b/src/hardware/hw3sound.c
@@ -384,12 +384,12 @@ INT32 HW3S_I_StartSound(const void *origin_p, source3D_data_t *source_parm, chan
 		/*if (gamemode != heretic)
 		{
 			if (sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit)
-				pitch += 8 - (M_Random()&15);
+				pitch += 8 - (M_RandomByte()&15);
 			else if (sfx_id != sfx_itemup && sfx_id != sfx_tink)
-				pitch += 16 - (M_Random()&31);
+				pitch += 16 - (M_RandomByte()&31);
 		}
 		else*/
-			pitch = 128 + (M_Random() & 7) - (M_Random() & 7);
+			pitch = 128 + (M_RandomByte() & 7) - (M_RandomByte() & 7);
 	}
 #endif
 
diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c
index fb369387f424764d88a76ffefa3e9c92506f06e6..a93e96dc3d3e27ea2497b0230c90812ad363744f 100644
--- a/src/hardware/hw_light.c
+++ b/src/hardware/hw_light.c
@@ -871,7 +871,7 @@ void HWR_DoCoronasLighting(FOutVector *outVerts, gr_vissprite_t *spr)
 				size  = p_lspr->corona_radius  * ((outVerts[0].z+120.0f)/950.0f); // d'ou vienne ces constante ?
 				break;
 			case ROCKET_SPR:
-				p_lspr->corona_color = (((M_Random()>>1)&0xff)<<24)|0x0040ff;
+				p_lspr->corona_color = (((M_RandomByte()>>1)&0xff)<<24)|0x0040ff;
 				// don't need a break
 			case CORONA_SPR:
 				size  = p_lspr->corona_radius  * ((outVerts[0].z+60.0f)/100.0f); // d'ou vienne ces constante ?
@@ -974,7 +974,7 @@ void HWR_DrawCoronas(void)
 				size  = p_lspr->corona_radius  * ((cz+120.0f)/950.0f); // d'ou vienne ces constante ?
 				break;
 			case ROCKET_SPR:
-				Surf.FlatColor.s.alpha = (UINT8)((M_Random()>>1)&0xff);
+				Surf.FlatColor.s.alpha = (UINT8)((M_RandomByte()>>1)&0xff);
 				// don't need a break
 			case CORONA_SPR:
 				size  = p_lspr->corona_radius  * ((cz+60.0f)/100.0f); // d'ou vienne ces constante ?
diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h
index af7d821b1ac437632a062db460e09edffc2038bb..b0a14d3b58640b3d43ec10e91cb5de75b1f70a93 100644
--- a/src/hardware/hw_main.h
+++ b/src/hardware/hw_main.h
@@ -74,10 +74,12 @@ FUNCMATH UINT8 LightLevelToLum(INT32 l);
 
 extern CV_PossibleValue_t granisotropicmode_cons_t[];
 
+#ifdef ALAM_LIGHTING
 extern consvar_t cv_grdynamiclighting;
 extern consvar_t cv_grstaticlighting;
 extern consvar_t cv_grcoronas;
 extern consvar_t cv_grcoronasize;
+#endif
 extern consvar_t cv_grfov;
 extern consvar_t cv_grmd2;
 extern consvar_t cv_grfog;
diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c
index e23b3eebf2fd2d74e69240e782e4b99a659a9ec4..1a81fe796251a5a40ef213e30bb4b01a8f3a205f 100644
--- a/src/hardware/r_opengl/r_opengl.c
+++ b/src/hardware/r_opengl/r_opengl.c
@@ -1470,6 +1470,26 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo)
 			else
 				pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
 		}
+		else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8)
+		{
+			//pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
+			if (MipMap)
+			{
+				pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
+#ifdef GL_TEXTURE_MIN_LOD
+				pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
+#endif
+#ifdef GL_TEXTURE_MAX_LOD
+				if (pTexInfo->flags & TF_TRANSPARENT)
+					pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff
+				else
+					pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4);
+#endif
+				//pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR);
+			}
+			else
+				pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex);
+		}
 		else
 		{
 			if (MipMap)
@@ -2150,7 +2170,7 @@ EXPORT void HWRAPI(StartScreenWipe) (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
@@ -2179,7 +2199,7 @@ EXPORT void HWRAPI(EndScreenWipe)(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
@@ -2294,22 +2314,22 @@ EXPORT void HWRAPI(DoScreenWipe)(float alpha)
 
 			// Bottom left
 			pglMultiTexCoord2f(GL_TEXTURE0, 0.0f, 0.0f);
-			pglMultiTexCoord2f(GL_TEXTURE1, 0.0f, 0.0f);
+			pglMultiTexCoord2f(GL_TEXTURE1, 0.0f, 1.0f);
 			pglVertex3f(-1.0f, -1.0f, 1.0f);
 
 			// Top left
 			pglMultiTexCoord2f(GL_TEXTURE0, 0.0f, yfix);
-			pglMultiTexCoord2f(GL_TEXTURE1, 0.0f, 1.0f);
+			pglMultiTexCoord2f(GL_TEXTURE1, 0.0f, 0.0f);
 			pglVertex3f(-1.0f, 1.0f, 1.0f);
 
 			// Top right
 			pglMultiTexCoord2f(GL_TEXTURE0, xfix, yfix);
-			pglMultiTexCoord2f(GL_TEXTURE1, 1.0f, 1.0f);
+			pglMultiTexCoord2f(GL_TEXTURE1, 1.0f, 0.0f);
 			pglVertex3f(1.0f, 1.0f, 1.0f);
 
 			// Bottom right
 			pglMultiTexCoord2f(GL_TEXTURE0, xfix, 0.0f);
-			pglMultiTexCoord2f(GL_TEXTURE1, 1.0f, 0.0f);
+			pglMultiTexCoord2f(GL_TEXTURE1, 1.0f, 1.0f);
 			pglVertex3f(1.0f, -1.0f, 1.0f);
 		pglEnd();
 
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index a7f2eb39fc4887e33a2c19108a52d2da9c322c85..525f2fe68481271d2573eee8e6039c7f37c0cabc 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -96,17 +96,17 @@ static int lib_evalMath(lua_State *L)
 // M_RANDOM
 //////////////
 
-static int lib_pRandom(lua_State *L)
+static int lib_pRandomFixed(lua_State *L)
 {
 	NOHUD
-	lua_pushinteger(L, P_Random());
+	lua_pushfixed(L, P_RandomFixed());
 	return 1;
 }
 
-static int lib_pSignedRandom(lua_State *L)
+static int lib_pRandomByte(lua_State *L)
 {
 	NOHUD
-	lua_pushinteger(L, P_SignedRandom());
+	lua_pushinteger(L, P_RandomByte());
 	return 1;
 }
 
@@ -134,6 +134,30 @@ static int lib_pRandomRange(lua_State *L)
 	return 1;
 }
 
+// Deprecated, macros, etc.
+static int lib_pRandom(lua_State *L)
+{
+	NOHUD
+	LUA_Deprecated(L, "P_Random", "P_RandomByte");
+	lua_pushinteger(L, P_RandomByte());
+	return 1;
+}
+
+static int lib_pSignedRandom(lua_State *L)
+{
+	NOHUD
+	lua_pushinteger(L, P_SignedRandom());
+	return 1;
+}
+
+static int lib_pRandomChance(lua_State *L)
+{
+	fixed_t p = luaL_checkfixed(L, 1);
+	NOHUD
+	lua_pushboolean(L, P_RandomChance(p));
+	return 1;
+}
+
 // P_MAPUTIL
 ///////////////
 
@@ -271,8 +295,8 @@ static int lib_pSpawnMobj(lua_State *L)
 	fixed_t z = luaL_checkfixed(L, 3);
 	mobjtype_t type = luaL_checkinteger(L, 4);
 	NOHUD
-	if (type > MT_LASTFREESLOT)
-		return luaL_error(L, "mobjtype_t out of bounds error!");
+	if (type >= NUMMOBJTYPES)
+		return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
 	LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ);
 	return 1;
 }
@@ -297,8 +321,8 @@ static int lib_pSpawnMissile(lua_State *L)
 	NOHUD
 	if (!source || !dest)
 		return LUA_ErrInvalid(L, "mobj_t");
-	if (type > MT_LASTFREESLOT)
-		return luaL_error(L, "mobjtype_t out of bounds error!");
+	if (type >= NUMMOBJTYPES)
+		return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
 	LUA_PushUserdata(L, P_SpawnMissile(source, dest, type), META_MOBJ);
 	return 1;
 }
@@ -314,8 +338,8 @@ static int lib_pSpawnXYZMissile(lua_State *L)
 	NOHUD
 	if (!source || !dest)
 		return LUA_ErrInvalid(L, "mobj_t");
-	if (type > MT_LASTFREESLOT)
-		return luaL_error(L, "mobjtype_t out of bounds error!");
+	if (type >= NUMMOBJTYPES)
+		return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
 	LUA_PushUserdata(L, P_SpawnXYZMissile(source, dest, type, x, y, z), META_MOBJ);
 	return 1;
 }
@@ -333,8 +357,8 @@ static int lib_pSpawnPointMissile(lua_State *L)
 	NOHUD
 	if (!source)
 		return LUA_ErrInvalid(L, "mobj_t");
-	if (type > MT_LASTFREESLOT)
-		return luaL_error(L, "mobjtype_t out of bounds error!");
+	if (type >= NUMMOBJTYPES)
+		return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
 	LUA_PushUserdata(L, P_SpawnPointMissile(source, xa, ya, za, type, x, y, z), META_MOBJ);
 	return 1;
 }
@@ -350,8 +374,8 @@ static int lib_pSpawnAlteredDirectionMissile(lua_State *L)
 	NOHUD
 	if (!source)
 		return LUA_ErrInvalid(L, "mobj_t");
-	if (type > MT_LASTFREESLOT)
-		return luaL_error(L, "mobjtype_t out of bounds error!");
+	if (type >= NUMMOBJTYPES)
+		return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
 	LUA_PushUserdata(L, P_SpawnAlteredDirectionMissile(source, type, x, y, z, shiftingAngle), META_MOBJ);
 	return 1;
 }
@@ -379,8 +403,8 @@ static int lib_pSPMAngle(lua_State *L)
 	NOHUD
 	if (!source)
 		return LUA_ErrInvalid(L, "mobj_t");
-	if (type > MT_LASTFREESLOT)
-		return luaL_error(L, "mobjtype_t out of bounds error!");
+	if (type >= NUMMOBJTYPES)
+		return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
 	LUA_PushUserdata(L, P_SPMAngle(source, type, angle, allowaim, flags2), META_MOBJ);
 	return 1;
 }
@@ -393,8 +417,8 @@ static int lib_pSpawnPlayerMissile(lua_State *L)
 	NOHUD
 	if (!source)
 		return LUA_ErrInvalid(L, "mobj_t");
-	if (type > MT_LASTFREESLOT)
-		return luaL_error(L, "mobjtype_t out of bounds error!");
+	if (type >= NUMMOBJTYPES)
+		return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
 	LUA_PushUserdata(L, P_SpawnPlayerMissile(source, type, flags2), META_MOBJ);
 	return 1;
 }
@@ -413,8 +437,8 @@ static int lib_pWeaponOrPanel(lua_State *L)
 {
 	mobjtype_t type = luaL_checkinteger(L, 1);
 	//HUDSAFE
-	if (type > MT_LASTFREESLOT)
-		return luaL_error(L, "mobjtype_t out of bounds error!");
+	if (type >= NUMMOBJTYPES)
+		return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
 	lua_pushboolean(L, P_WeaponOrPanel(type));
 	return 1;
 }
@@ -453,8 +477,10 @@ static int lib_pSpawnParaloop(lua_State *L)
 	statenum_t nstate = luaL_optinteger(L, 8, S_NULL);
 	boolean spawncenter = lua_optboolean(L, 9);
 	NOHUD
-	if (type > MT_LASTFREESLOT)
-		return luaL_error(L, "mobjtype_t out of bounds error!");
+	if (type >= NUMMOBJTYPES)
+		return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
+	if (nstate >= NUMSTATES)
+		return luaL_error(L, "state %d out of range (0 - %d)", nstate, NUMSTATES-1);
 	P_SpawnParaloop(x, y, z, radius, number, type, nstate, rotangle, spawncenter);
 	return 0;
 }
@@ -884,8 +910,8 @@ static int lib_pSpawnSpinMobj(lua_State *L)
 	NOHUD
 	if (!player)
 		return LUA_ErrInvalid(L, "player_t");
-	if (type > MT_LASTFREESLOT)
-		return luaL_error(L, "mobjtype_t out of bounds error!");
+	if (type >= NUMMOBJTYPES)
+		return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
 	P_SpawnSpinMobj(player, type);
 	return 0;
 }
@@ -1250,6 +1276,8 @@ static int lib_pSetMobjStateNF(lua_State *L)
 	NOHUD
 	if (!mobj)
 		return LUA_ErrInvalid(L, "mobj_t");
+	if (state >= NUMSTATES)
+		return luaL_error(L, "state %d out of range (0 - %d)", state, NUMSTATES-1);
 	if (mobj->player && state == S_NULL)
 		return luaL_error(L, "Attempt to remove player mobj with S_NULL.");
 	lua_pushboolean(L, P_SetMobjStateNF(mobj, state));
@@ -1361,8 +1389,8 @@ static int lib_pIsFlagAtBase(lua_State *L)
 {
 	mobjtype_t flag = luaL_checkinteger(L, 1);
 	NOHUD
-	if (flag > MT_LASTFREESLOT)
-		return luaL_error(L, "mobjtype_t out of bounds error!");
+	if (flag >= NUMMOBJTYPES)
+		return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1);
 	lua_pushboolean(L, P_IsFlagAtBase(flag));
 	return 1;
 }
@@ -1595,7 +1623,7 @@ static int lib_rSetPlayerSkin(lua_State *L)
 	{
 		INT32 i = luaL_checkinteger(L, 2);
 		if (i < 0 || i >= MAXSKINS)
-			return luaL_error(L, "argument #2 cannot exceed MAXSKINS");
+			return luaL_error(L, "skin number (argument #2) %d out of range (0 - %d)", i, MAXSKINS-1);
 		SetPlayerSkinByNum(player-players, i);
 	}
 	else // skin name
@@ -1615,6 +1643,8 @@ static int lib_sStartSound(lua_State *L)
 	sfxenum_t sound_id = luaL_checkinteger(L, 2);
 	player_t *player = NULL;
 	NOHUD
+	if (sound_id >= NUMSFX)
+		return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
 	if (!lua_isnil(L, 1))
 	{
 		origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@@ -1639,12 +1669,15 @@ static int lib_sStartSoundAtVolume(lua_State *L)
 	INT32 volume = (INT32)luaL_checkinteger(L, 3);
 	player_t *player = NULL;
 	NOHUD
+
 	if (!lua_isnil(L, 1))
 	{
 		origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
 		if (!origin)
 			return LUA_ErrInvalid(L, "mobj_t");
 	}
+	if (sound_id >= NUMSFX)
+		return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1);
 	if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
 	{
 		player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER));
@@ -1776,6 +1809,8 @@ static int lib_sIdPlaying(lua_State *L)
 {
 	sfxenum_t id = luaL_checkinteger(L, 1);
 	NOHUD
+	if (id >= NUMSFX)
+		return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1);
 	lua_pushboolean(L, S_IdPlaying(id));
 	return 1;
 }
@@ -1787,6 +1822,8 @@ static int lib_sSoundPlaying(lua_State *L)
 	NOHUD
 	if (!origin)
 		return LUA_ErrInvalid(L, "mobj_t");
+	if (id >= NUMSFX)
+		return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1);
 	lua_pushboolean(L, S_SoundPlaying(origin, id));
 	return 1;
 }
@@ -1807,7 +1844,7 @@ static int lib_gDoReborn(lua_State *L)
 	INT32 playernum = luaL_checkinteger(L, 1);
 	NOHUD
 	if (playernum >= MAXPLAYERS)
-		return luaL_error(L, "playernum out of bounds error!");
+		return luaL_error(L, "playernum %d out of range (0 - %d)", playernum, MAXPLAYERS-1);
 	G_DoReborn(playernum);
 	return 0;
 }
@@ -1934,10 +1971,13 @@ static luaL_Reg lib[] = {
 	{"EvalMath", lib_evalMath},
 
 	// m_random
-	{"P_Random",lib_pRandom},
-	{"P_SignedRandom",lib_pSignedRandom},
+	{"P_RandomFixed",lib_pRandomFixed},
+	{"P_RandomByte",lib_pRandomByte},
 	{"P_RandomKey",lib_pRandomKey},
 	{"P_RandomRange",lib_pRandomRange},
+	{"P_Random",lib_pRandom}, // DEPRECATED
+	{"P_SignedRandom",lib_pSignedRandom}, // MACRO
+	{"P_RandomChance",lib_pRandomChance}, // MACRO
 
 	// p_maputil
 	{"P_AproxDistance",lib_pAproxDistance},
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 52770a88a500d72cddbc7484e88a1126102807c3..33cc1b36729cb16bb0189133b8d1e3cdcf227827 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -166,6 +166,8 @@ static int lib_getHudInfo(lua_State *L)
 	lua_remove(L, 1);
 
 	i = luaL_checkinteger(L, 1);
+	if (i >= NUMHUDITEMS)
+		return luaL_error(L, "hudinfo[] index %d out of range (0 - %d)", i, NUMHUDITEMS-1);
 	LUA_PushUserdata(L, &hudinfo[i], META_HUDINFO);
 	return 1;
 }
@@ -526,6 +528,22 @@ static int libd_height(lua_State *L)
 	return 1;
 }
 
+static int libd_dupx(lua_State *L)
+{
+	HUDONLY
+	lua_pushinteger(L, vid.dupx); // push integral scale (patch scale)
+	lua_pushfixed(L, vid.fdupx); // push fixed point scale (position scale)
+	return 2;
+}
+
+static int libd_dupy(lua_State *L)
+{
+	HUDONLY
+	lua_pushinteger(L, vid.dupy); // push integral scale (patch scale)
+	lua_pushfixed(L, vid.fdupy); // push fixed point scale (position scale)
+	return 2;
+}
+
 static int libd_renderer(lua_State *L)
 {
 	HUDONLY
@@ -550,6 +568,8 @@ static luaL_Reg lib_draw[] = {
 	{"getColormap", libd_getColormap},
 	{"width", libd_width},
 	{"height", libd_height},
+	{"dupx", libd_dupx},
+	{"dupy", libd_dupy},
 	{"renderer", libd_renderer},
 	{NULL, NULL}
 };
diff --git a/src/lua_infolib.c b/src/lua_infolib.c
index 0fddebabae628703c87f4efec7330489bfffc7cf..6c99e4f6ef3ad4d138fe5a7ea1632357719cd114 100644
--- a/src/lua_infolib.c
+++ b/src/lua_infolib.c
@@ -146,6 +146,8 @@ static int lib_getState(lua_State *L)
 	lua_remove(L, 1);
 
 	i = luaL_checkinteger(L, 1);
+	if (i >= NUMSTATES)
+		return luaL_error(L, "states[] index %d out of range (0 - %d)", i, NUMSTATES-1);
 	LUA_PushUserdata(L, &states[i], META_STATE);
 	return 1;
 }
@@ -155,7 +157,12 @@ static int lib_setState(lua_State *L)
 {
 	state_t *state;
 	lua_remove(L, 1); // don't care about states[] userdata.
-	state = &states[luaL_checkinteger(L, 1)]; // get the state to assign to.
+	{
+		UINT32 i = luaL_checkinteger(L, 1);
+		if (i >= NUMSTATES)
+			return luaL_error(L, "states[] index %d out of range (0 - %d)", i, NUMSTATES-1);
+		state = &states[i]; // get the state to assign to.
+	}
 	luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
 	lua_remove(L, 1); // pop state num, don't need it any more.
 	lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the state.
@@ -436,6 +443,8 @@ static int lib_getMobjInfo(lua_State *L)
 	lua_remove(L, 1);
 
 	i = luaL_checkinteger(L, 1);
+	if (i >= NUMMOBJTYPES)
+		return luaL_error(L, "mobjinfo[] index %d out of range (0 - %d)", i, NUMMOBJTYPES-1);
 	LUA_PushUserdata(L, &mobjinfo[i], META_MOBJINFO);
 	return 1;
 }
@@ -445,7 +454,12 @@ static int lib_setMobjInfo(lua_State *L)
 {
 	mobjinfo_t *info;
 	lua_remove(L, 1); // don't care about mobjinfo[] userdata.
-	info = &mobjinfo[luaL_checkinteger(L, 1)]; // get the mobjinfo to assign to.
+	{
+		UINT32 i = luaL_checkinteger(L, 1);
+		if (i >= NUMMOBJTYPES)
+			return luaL_error(L, "mobjinfo[] index %d out of range (0 - %d)", i, NUMMOBJTYPES-1);
+		info = &mobjinfo[i]; // get the mobjinfo to assign to.
+	}
 	luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
 	lua_remove(L, 1); // pop mobjtype num, don't need it any more.
 	lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the mobjinfo.
@@ -717,6 +731,8 @@ static int lib_getSfxInfo(lua_State *L)
 	lua_remove(L, 1);
 
 	i = luaL_checkinteger(L, 1);
+	if (i >= NUMSFX)
+		return luaL_error(L, "sfxinfo[] index %d out of range (0 - %d)", i, NUMSFX-1);
 	LUA_PushUserdata(L, &S_sfx[i], META_SFXINFO);
 	return 1;
 }
@@ -727,7 +743,12 @@ static int lib_setSfxInfo(lua_State *L)
 	sfxinfo_t *info;
 
 	lua_remove(L, 1);
-	info = &S_sfx[luaL_checkinteger(L, 1)]; // get the mobjinfo to assign to.
+	{
+		UINT32 i = luaL_checkinteger(L, 1);
+		if (i >= NUMSFX)
+			return luaL_error(L, "sfxinfo[] index %d out of range (0 - %d)", i, NUMSFX-1);
+		info = &S_sfx[i]; // get the mobjinfo to assign to.
+	}
 	luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
 	lua_remove(L, 1); // pop mobjtype num, don't need it any more.
 	lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the mobjinfo.
diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index 64513ab9728e6a2e4c7723e3a80ef36ceb9bee59..388fe3175f52ce09e5effddf7eb81b6fbdfc84e9 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -55,7 +55,7 @@ static int lib_getPlayer(lua_State *L)
 	{
 		lua_Integer i = luaL_checkinteger(L, 2);
 		if (i < 0 || i >= MAXPLAYERS)
-			return luaL_error(L, "players[] index cannot exceed MAXPLAYERS");
+			return luaL_error(L, "players[] index %d out of range (0 - %d)", i, MAXPLAYERS-1);
 		if (!playeringame[i])
 			return 0;
 		if (!players[i].mo)
@@ -298,6 +298,8 @@ static int player_get(lua_State *L)
 		lua_pushinteger(L, plr->lastlinehit);
 	else if (fastcmp(field,"losstime"))
 		lua_pushinteger(L, plr->losstime);
+	else if (fastcmp(field,"timeshit"))
+		lua_pushinteger(L, plr->timeshit);
 	else if (fastcmp(field,"onconveyor"))
 		lua_pushinteger(L, plr->onconveyor);
 	else if (fastcmp(field,"awayviewmobj"))
@@ -553,6 +555,8 @@ static int player_set(lua_State *L)
 		plr->lastlinehit = (INT16)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"losstime"))
 		plr->losstime = (tic_t)luaL_checkinteger(L, 3);
+	else if (fastcmp(field,"timeshit"))
+		plr->timeshit = (UINT8)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"onconveyor"))
 		plr->onconveyor = (INT32)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"awayviewmobj"))
diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c
index f07b4564c15d553c9b5640d03d6151fd0e69d87b..545cf55b061b4604b0c18851b3bb1293e8d97cea 100644
--- a/src/lua_skinlib.c
+++ b/src/lua_skinlib.c
@@ -244,7 +244,7 @@ static int lib_getSkin(lua_State *L)
 	{
 		i = luaL_checkinteger(L, 2);
 		if (i < 0 || i >= MAXSKINS)
-			return luaL_error(L, "skins[] index cannot exceed MAXSKINS");
+			return luaL_error(L, "skins[] index %d out of range (0 - %d)", i, MAXSKINS-1);
 		if (i >= numskins)
 			return 0;
 		LUA_PushUserdata(L, &skins[i], META_SKIN);
diff --git a/src/m_cheat.c b/src/m_cheat.c
index 3ccb2e10f6eb2e4e7027a71eb75d21912a3cc9ff..06a374634135218f0e83c9f23759af080b17a0f0 100644
--- a/src/m_cheat.c
+++ b/src/m_cheat.c
@@ -31,6 +31,7 @@
 
 #include "v_video.h"
 #include "z_zone.h"
+#include "p_slopes.h"
 
 #include "lua_script.h"
 #include "lua_hook.h"
@@ -598,9 +599,9 @@ void Command_CauseCfail_f(void)
 	}
 
 	P_UnsetThingPosition(players[consoleplayer].mo);
-	P_Random();
-	P_Random();
-	P_Random();
+	P_RandomFixed();
+	P_RandomByte();
+	P_RandomFixed();
 	players[consoleplayer].mo->x = 0;
 	players[consoleplayer].mo->y = 123311; //cfail cansuled kthxbye
 	players[consoleplayer].mo->z = 123311;
@@ -837,9 +838,19 @@ static void OP_CycleThings(INT32 amt)
 
 static boolean OP_HeightOkay(player_t *player, UINT8 ceiling)
 {
+	sector_t *sec = player->mo->subsector->sector;
+
 	if (ceiling)
 	{
-		if (((player->mo->subsector->sector->ceilingheight - player->mo->z - player->mo->height)>>FRACBITS) >= (1 << (16-ZSHIFT)))
+#ifdef ESLOPE
+		// Truncate position to match where mapthing would be when spawned
+		// (this applies to every further P_GetZAt call as well)
+		fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->ceilingheight;
+#else
+		fixed_t cheight = sec->ceilingheight;
+#endif
+
+		if (((cheight - player->mo->z - player->mo->height)>>FRACBITS) >= (1 << (16-ZSHIFT)))
 		{
 			CONS_Printf(M_GetText("Sorry, you're too %s to place this object (max: %d %s).\n"), M_GetText("low"),
 				(1 << (16-ZSHIFT)), M_GetText("below top ceiling"));
@@ -848,7 +859,12 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling)
 	}
 	else
 	{
-		if (((player->mo->z - player->mo->subsector->sector->floorheight)>>FRACBITS) >= (1 << (16-ZSHIFT)))
+#ifdef ESLOPE
+		fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight;
+#else
+		fixed_t fheight = sec->floorheight;
+#endif
+		if (((player->mo->z - fheight)>>FRACBITS) >= (1 << (16-ZSHIFT)))
 		{
 			CONS_Printf(M_GetText("Sorry, you're too %s to place this object (max: %d %s).\n"), M_GetText("high"),
 				(1 << (16-ZSHIFT)), M_GetText("above bottom floor"));
@@ -861,6 +877,7 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling)
 static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean ceiling)
 {
 	mapthing_t *mt = mapthings;
+	sector_t *sec = player->mo->subsector->sector;
 
 #ifdef HAVE_BLUA
 	LUA_InvalidateMapthings();
@@ -893,9 +910,23 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
 	mt->x = (INT16)(player->mo->x>>FRACBITS);
 	mt->y = (INT16)(player->mo->y>>FRACBITS);
 	if (ceiling)
-		mt->options = (UINT16)((player->mo->subsector->sector->ceilingheight - player->mo->z - player->mo->height)>>FRACBITS);
+	{
+#ifdef ESLOPE
+		fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, mt->x << FRACBITS, mt->y << FRACBITS) : sec->ceilingheight;
+#else
+		fixed_t cheight = sec->ceilingheight;
+#endif
+		mt->options = (UINT16)((cheight - player->mo->z - player->mo->height)>>FRACBITS);
+	}
 	else
-		mt->options = (UINT16)((player->mo->z - player->mo->subsector->sector->floorheight)>>FRACBITS);
+	{
+#ifdef ESLOPE
+		fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : sec->floorheight;
+#else
+		fixed_t fheight = sec->floorheight;
+#endif
+		mt->options = (UINT16)((player->mo->z - fheight)>>FRACBITS);
+	}
 	mt->options <<= ZSHIFT;
 	mt->angle = (INT16)(FixedInt(AngleFixed(player->mo->angle)));
 
@@ -949,6 +980,13 @@ void OP_NightsObjectplace(player_t *player)
 	{
 		UINT16 angle = (UINT16)(player->anotherflyangle % 360);
 		INT16 temp = (INT16)FixedInt(AngleFixed(player->mo->angle)); // Traditional 2D Angle
+		sector_t *sec = player->mo->subsector->sector;
+#ifdef ESLOPE
+		fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight;
+#else
+		fixed_t fheight = sec->floorheight;
+#endif
+
 
 		player->pflags |= PF_ATTACKDOWN;
 
@@ -963,7 +1001,7 @@ void OP_NightsObjectplace(player_t *player)
 			temp += 90;
 		temp %= 360;
 
-		mt->options = (UINT16)((player->mo->z - player->mo->subsector->sector->floorheight)>>FRACBITS);
+		mt->options = (UINT16)((player->mo->z - fheight)>>FRACBITS);
 		mt->angle = (INT16)(mt->angle+(INT16)((FixedInt(FixedDiv(temp*FRACUNIT, 360*(FRACUNIT/256))))<<8));
 
 		P_SpawnHoopsAndRings(mt);
@@ -1097,6 +1135,33 @@ void OP_ObjectplaceMovement(player_t *player)
 	else
 		player->viewz = player->mo->z + player->viewheight;
 
+	// Display flag information
+	// Moved up so it always updates.
+	{
+		sector_t *sec = player->mo->subsector->sector;
+
+		if (!!(mobjinfo[op_currentthing].flags & MF_SPAWNCEILING) ^ !!(cv_opflags.value & MTF_OBJECTFLIP))
+		{
+#ifdef ESLOPE
+			fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->ceilingheight;
+#else
+			fixed_t cheight = sec->ceilingheight;
+#endif
+			op_displayflags = (UINT16)((cheight - player->mo->z - mobjinfo[op_currentthing].height)>>FRACBITS);
+		}
+		else
+		{
+#ifdef ESLOPE
+			fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight;
+#else
+			fixed_t fheight = sec->floorheight;
+#endif
+			op_displayflags = (UINT16)((player->mo->z - fheight)>>FRACBITS);
+		}
+		op_displayflags <<= ZSHIFT;
+		op_displayflags |= (UINT16)cv_opflags.value;
+	}
+
 	if (player->pflags & PF_ATTACKDOWN)
 	{
 		// Are ANY objectplace buttons pressed?  If no, remove flag.
@@ -1162,16 +1227,6 @@ void OP_ObjectplaceMovement(player_t *player)
 
 		CONS_Printf(M_GetText("Placed object type %d at %d, %d, %d, %d\n"), mt->type, mt->x, mt->y, mt->options>>ZSHIFT, mt->angle);
 	}
-
-	// Display flag information
-	{
-		if (!!(mobjinfo[op_currentthing].flags & MF_SPAWNCEILING) ^ !!(cv_opflags.value & MTF_OBJECTFLIP))
-			op_displayflags = (UINT16)((player->mo->subsector->sector->ceilingheight - player->mo->z - mobjinfo[op_currentthing].height)>>FRACBITS);
-		else
-			op_displayflags = (UINT16)((player->mo->z - player->mo->subsector->sector->floorheight)>>FRACBITS);
-		op_displayflags <<= ZSHIFT;
-		op_displayflags |= (UINT16)cv_opflags.value;
-	}
 }
 
 //
diff --git a/src/m_misc.c b/src/m_misc.c
index 22effdddfef3c65a5d4edb056e19b59d0434fa72..6899059b6e563316484c26bee218b0cfb335fb79 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -1787,17 +1787,6 @@ UINT8 M_CountBits(UINT32 num, UINT8 size)
 	return sum;
 }
 
-
-/** Get the most significant bit in a number.
-  * (integer log2)
-  */
-UINT8 M_HighestBit(UINT32 num)
-{
-	UINT8 i = 0;
-	while (num >>= 1) ++i;
-	return i;
-}
-
 const char *GetRevisionString(void)
 {
 	static char rev[9] = {0};
diff --git a/src/m_misc.h b/src/m_misc.h
index f681bfcb3ce7ec43581725876c1029b81f489d67..5fc4fa63bf79a4ee255f829021ff426356826726 100644
--- a/src/m_misc.h
+++ b/src/m_misc.h
@@ -95,7 +95,6 @@ void M_SetupMemcpy(void);
 
 // counting bits, for weapon ammo code, usually
 FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);
-FUNCMATH UINT8 M_HighestBit(UINT32 num);
 
 // Flags for AA trees.
 #define AATREE_ZUSER	1		// Treat values as z_zone-allocated blocks and set their user fields
diff --git a/src/m_random.c b/src/m_random.c
index fce65b88a468a2d429a2a9a1d62e8197fc3def43..5fde12535232330c9973920f2e14c0015833b7b5 100644
--- a/src/m_random.c
+++ b/src/m_random.c
@@ -10,7 +10,7 @@
 // See the 'LICENSE' file for more details.
 //-----------------------------------------------------------------------------
 /// \file  m_random.c
-/// \brief LCG PRNG originally created for XMOD
+/// \brief RNG for client effects and PRNG for game actions
 
 #include "doomdef.h"
 #include "doomtype.h"
@@ -19,48 +19,57 @@
 #include "m_random.h"
 #include "m_fixed.h"
 
+
+
 // ---------------------------
 // RNG functions (not synched)
 // ---------------------------
 
-/** Provides a random byte.
-  * Used outside the p_xxx game code and not synchronized in netgames. This is
-  * for anything that doesn't need to be synced, e.g. precipitation.
+/** Provides a random fixed point number. Distribution is uniform.
+  * As with all M_Random functions, not synched in netgames.
   *
-  * \return A random byte, 0 to 255.
+  * \return A random fixed point number from [0,1).
   */
-UINT8 M_Random(void)
+fixed_t M_RandomFixed(void)
 {
-	return (rand() & 255);
+#if RAND_MAX < 65535
+	// Compensate for insufficient randomness.
+	fixed_t rndv = (rand()&1)<<15;
+	return rand()^rndv;
+#else
+	return (rand() & 0xFFFF);
+#endif
 }
 
-/** Provides a random signed byte.  Distribution is uniform.
-  * As with all M_*Random functions, not synched in netgames.
+/** Provides a random byte. Distribution is uniform.
+  * As with all M_Random functions, not synched in netgames.
   *
-  * \return A random byte, -128 to 127.
-  * \sa M_Random
+  * \return A random integer from [0, 255].
   */
-INT32 M_SignedRandom(void)
+UINT8 M_RandomByte(void)
 {
-	return M_Random() - 128;
+	return (rand() & 0xFF);
 }
 
-/** Provides a random number in between 0 and the given number - 1.
-  * Distribution is uniform.  Use for picking random elements from an array.
-  * As with all M_*Random functions, not synched in netgames.
+/** Provides a random integer for picking random elements from an array.
+  * Distribution is uniform.
+  * As with all M_Random functions, not synched in netgames.
   *
-  * \return A random number, 0 to arg1-1.
+  * \param a Number of items in array.
+  * \return A random integer from [0,a).
   */
 INT32 M_RandomKey(INT32 a)
 {
 	return (INT32)((rand()/((unsigned)RAND_MAX+1.0f))*a);
 }
 
-/** Provides a random number in between a specific range.
+/** Provides a random integer in a given range.
   * Distribution is uniform.
-  * As with all M_*Random functions, not synched in netgames.
+  * As with all M_Random functions, not synched in netgames.
   *
-  * \return A random number, arg1 to arg2.
+  * \param a Lower bound.
+  * \param b Upper bound.
+  * \return A random integer from [a,b].
   */
 INT32 M_RandomRange(INT32 a, INT32 b)
 {
@@ -74,54 +83,65 @@ INT32 M_RandomRange(INT32 a, INT32 b)
 // ------------------------
 
 // Holds the current seed.
-static UINT32 randomseed = 0;
+static UINT32 randomseed = 0xBADE4404;
 
 // Holds the INITIAL seed value.  Used for demos, possibly other debugging.
-static UINT32 initialseed = 0;
+static UINT32 initialseed = 0xBADE4404;
+
+/** Provides a random fixed point number.
+  * This is a variant of an xorshift PRNG; state fits in a 32 bit integer structure.
+  *
+  * \return A random fixed point number from [0,1).
+  */
+ATTRINLINE static fixed_t FUNCINLINE __internal_prng__(void)
+{
+	randomseed ^= randomseed >> 13;
+	randomseed ^= randomseed >> 11;
+	randomseed ^= randomseed << 21;
+	return ( (randomseed*36548569) >> 4) & (FRACUNIT-1);
+}
 
-/**
-  * Provides a random byte and sets the seed appropriately.
-  * The nature of this PRNG allows it to cycle through about two million numbers
-  * before it finally starts repeating numeric sequences.
-  * That's more than good enough for our purposes.
+/** Provides a random fixed point number. Distribution is uniform.
+  * Literally a wrapper for the internal PRNG function.
   *
-  * \return A random byte, 0 to 255.
+  * \return A random fixed point number from [0,1).
   */
 #ifndef DEBUGRANDOM
-UINT8 P_Random(void)
+fixed_t P_RandomFixed(void)
 {
 #else
-UINT8 P_RandomD(const char *rfile, INT32 rline)
+fixed_t P_RandomFixedD(const char *rfile, INT32 rline)
 {
-	CONS_Printf("P_Random() at: %sp %d\n", rfile, rline);
+	CONS_Printf("P_RandomFixed() at: %sp %d\n", rfile, rline);
 #endif
-	randomseed = (randomseed*746151647)+48205429;
-	return (UINT8)((randomseed >> 17)&255);
+	return __internal_prng__();
 }
 
-/** Provides a random number from -128 to 127.
-  * Distribution is uniform.
+/** Provides a random byte. Distribution is uniform.
+  * If you're curious, (&0xFF00) >> 8 gives the same result
+  * as a fixed point multiplication by 256.
   *
-  * \return Random number from -128 to 127.
-  * \sa P_Random
+  * \return Random integer from [0, 255].
+  * \sa __internal_prng__
   */
 #ifndef DEBUGRANDOM
-INT32 P_SignedRandom(void)
+UINT8 P_RandomByte(void)
 {
 #else
-INT32 P_SignedRandomD(const char *rfile, INT32 rline)
+UINT8 P_RandomByteD(const char *rfile, INT32 rline)
 {
-	CONS_Printf("P_SignedRandom() at: %sp %d\n", rfile, rline);
+	CONS_Printf("P_RandomByte() at: %sp %d\n", rfile, rline);
 #endif
-	return P_Random() - 128;
+	return (UINT8)((__internal_prng__()&0xFF00)>>8);
 }
 
-/** Provides a random number in between 0 and the given number - 1.
-  * Distribution is uniform, also calls for two numbers for bigger output range.
-  * Use for picking random elements from an array.
+/** Provides a random integer for picking random elements from an array.
+  * Distribution is uniform.
+  * NOTE: Maximum range is 65536.
   *
-  * \return A random number, 0 to arg1-1.
-  * \sa P_Random
+  * \param a Number of items in array.
+  * \return A random integer from [0,a).
+  * \sa __internal_prng__
   */
 #ifndef DEBUGRANDOM
 INT32 P_RandomKey(INT32 a)
@@ -131,16 +151,17 @@ INT32 P_RandomKeyD(const char *rfile, INT32 rline, INT32 a)
 {
 	CONS_Printf("P_RandomKey() at: %sp %d\n", rfile, rline);
 #endif
-	INT32 prandom = P_Random(); // note: forcing explicit function call order
-	prandom |= P_Random() << 8; // (function call order is not strictly defined)
-	return (INT32)((prandom/65536.0f)*a);
+	return (INT32)((__internal_prng__() * a) >> FRACBITS);
 }
 
-/** Provides a random number in between a specific range.
-  * Distribution is uniform, also calls for two numbers for bigger output range.
+/** Provides a random integer in a given range.
+  * Distribution is uniform.
+  * NOTE: Maximum range is 65536.
   *
-  * \return A random number, arg1 to arg2.
-  * \sa P_Random
+  * \param a Lower bound.
+  * \param b Upper bound.
+  * \return A random integer from [a,b].
+  * \sa __internal_prng__
   */
 #ifndef DEBUGRANDOM
 INT32 P_RandomRange(INT32 a, INT32 b)
@@ -150,21 +171,27 @@ INT32 P_RandomRangeD(const char *rfile, INT32 rline, INT32 a, INT32 b)
 {
 	CONS_Printf("P_RandomRange() at: %sp %d\n", rfile, rline);
 #endif
-	INT32 prandom = P_Random(); // note: forcing explicit function call order
-	prandom |= P_Random() << 8; // (function call order is not strictly defined)
-	return (INT32)((prandom/65536.0f)*(b-a+1))+a;
+	return (INT32)((__internal_prng__() * (b-a+1)) >> FRACBITS) + a;
 }
 
-/** Provides a random byte without saving what the seed would be.
-  * Used just to debug the PRNG.
+
+
+// ----------------------
+// PRNG seeds & debugging
+// ----------------------
+
+/** Peeks to see what the next result from the PRNG will be.
+  * Used for debugging.
   *
-  * \return A 'random' byte, 0 to 255.
-  * \sa P_Random
+  * \return A 'random' fixed point number from [0,1).
+  * \sa __internal_prng__
   */
-UINT8 P_RandomPeek(void)
+fixed_t P_RandomPeek(void)
 {
-	UINT32 r = (randomseed*746151647)+48205429;
-	return (UINT8)((r >> 17)&255);
+	UINT32 r = randomseed;
+	fixed_t ret = __internal_prng__();
+	randomseed = r;
+	return ret;
 }
 
 /** Gets the current random seed.  Used by netgame savegames.
@@ -213,6 +240,9 @@ void P_SetRandSeedD(const char *rfile, INT32 rline, UINT32 seed)
 {
 	CONS_Printf("P_SetRandSeed() at: %sp %d\n", rfile, rline);
 #endif
+	// xorshift requires a nonzero seed
+	// this should never happen, but just in case it DOES, we check
+	if (!seed) seed = 0xBADE4404;
 	randomseed = initialseed = seed;
 }
 
@@ -222,5 +252,5 @@ void P_SetRandSeedD(const char *rfile, INT32 rline, UINT32 seed)
   */
 UINT32 M_RandomizedSeed(void)
 {
-	return ((totalplaytime & 0xFFFF) << 16)|(rand() & 0xFFFF);
+	return ((totalplaytime & 0xFFFF) << 16)|M_RandomFixed();
 }
diff --git a/src/m_random.h b/src/m_random.h
index 42c8716086acddfa8ed7035b20433e60eb6332c7..90784a5d0d0decbd9d24923d63b19d0537f9d154 100644
--- a/src/m_random.h
+++ b/src/m_random.h
@@ -20,32 +20,42 @@
 
 //#define DEBUGRANDOM
 
+
 // M_Random functions pull random numbers of various types that aren't network synced.
-// P_Random functions pulls random bytes from a LCG PRNG that is network synced.
+// P_Random functions pulls random bytes from a PRNG that is network synced.
 
 // RNG functions
-UINT8 M_Random(void);
-INT32 M_SignedRandom(void);
-INT32 M_RandomKey(INT32 a);
-INT32 M_RandomRange(INT32 a, INT32 b);
+fixed_t M_RandomFixed(void);
+UINT8   M_RandomByte(void);
+INT32   M_RandomKey(INT32 a);
+INT32   M_RandomRange(INT32 a, INT32 b);
 
 // PRNG functions
 #ifdef DEBUGRANDOM
-#define P_Random() P_RandomD(__FILE__, __LINE__)
-#define P_SignedRandom() P_SignedRandomD(__FILE__, __LINE__)
-#define P_RandomKey(c) P_RandomKeyD(__FILE__, __LINE__, c)
+#define P_RandomFixed()     P_RandomFixedD(__FILE__, __LINE__)
+#define P_RandomByte()      P_RandomByteD(__FILE__, __LINE__)
+#define P_RandomKey(c)      P_RandomKeyD(__FILE__, __LINE__, c)
 #define P_RandomRange(c, d) P_RandomRangeD(__FILE__, __LINE__, c, d)
-UINT8 P_RandomD(const char *rfile, INT32 rline);
-INT32 P_SignedRandomD(const char *rfile, INT32 rline);
-INT32 P_RandomKeyD(const char *rfile, INT32 rline, INT32 a);
-INT32 P_RandomRangeD(const char *rfile, INT32 rline, INT32 a, INT32 b);
+fixed_t P_RandomFixedD(const char *rfile, INT32 rline);
+UINT8   P_RandomByteD(const char *rfile, INT32 rline);
+INT32   P_RandomKeyD(const char *rfile, INT32 rline, INT32 a);
+INT32   P_RandomRangeD(const char *rfile, INT32 rline, INT32 a, INT32 b);
 #else
-UINT8 P_Random(void);
-INT32 P_SignedRandom(void);
-INT32 P_RandomKey(INT32 a);
-INT32 P_RandomRange(INT32 a, INT32 b);
+fixed_t P_RandomFixed(void);
+UINT8   P_RandomByte(void);
+INT32   P_RandomKey(INT32 a);
+INT32   P_RandomRange(INT32 a, INT32 b);
 #endif
-UINT8 P_RandomPeek(void);
+
+// Macros for other functions
+#define M_SignedRandom()  ((INT32)M_RandomByte() - 128) // [-128, 127] signed byte, originally a
+#define P_SignedRandom()  ((INT32)P_RandomByte() - 128) // function of its own, moved to a macro
+
+#define M_RandomChance(p) (M_RandomFixed() < p) // given fixed point probability, p, between 0 (0%)
+#define P_RandomChance(p) (P_RandomFixed() < p) // and FRACUNIT (100%), returns true p% of the time
+
+// Debugging
+fixed_t P_RandomPeek(void);
 
 // Working with the seed for PRNG
 #ifdef DEBUGRANDOM
diff --git a/src/p_enemy.c b/src/p_enemy.c
index ffb69082213b86374f923ab2875452407ea0ac3f..82391a748dc61366c94403c5896e391f96ad18b4 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -386,7 +386,7 @@ boolean P_CheckMissileRange(mobj_t *actor)
 	if (actor->type == MT_EGGMOBILE && dist > 160)
 		dist = 160;
 
-	if (P_Random() < dist)
+	if (P_RandomByte() < dist)
 		return false;
 
 	return true;
@@ -486,7 +486,7 @@ static boolean P_TryWalk(mobj_t *actor)
 {
 	if (!P_Move(actor, actor->info->speed))
 		return false;
-	actor->movecount = P_Random() & 15;
+	actor->movecount = P_RandomByte() & 15;
 	return true;
 }
 
@@ -539,7 +539,7 @@ void P_NewChaseDir(mobj_t *actor)
 	}
 
 	// try other directions
-	if (P_Random() > 200 || abs(deltay) > abs(deltax))
+	if (P_RandomChance(25*FRACUNIT/32) || abs(deltay) > abs(deltax))
 	{
 		tdir = d[1];
 		d[1] = d[2];
@@ -577,7 +577,7 @@ void P_NewChaseDir(mobj_t *actor)
 	}
 
 	// randomly determine direction of search
-	if (P_Random() & 1)
+	if (P_RandomChance(FRACUNIT/2))
 	{
 		for (tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++)
 		{
@@ -632,7 +632,7 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
 
 	// BP: first time init, this allow minimum lastlook changes
 	if (actor->lastlook < 0)
-		actor->lastlook = P_Random();
+		actor->lastlook = P_RandomByte();
 
 	actor->lastlook %= MAXPLAYERS;
 
@@ -707,7 +707,7 @@ static boolean P_LookForShield(mobj_t *actor)
 
 	// BP: first time init, this allow minimum lastlook changes
 	if (actor->lastlook < 0)
-		actor->lastlook = P_Random();
+		actor->lastlook = P_RandomByte();
 
 	actor->lastlook %= MAXPLAYERS;
 
@@ -2293,12 +2293,7 @@ void A_SkullAttack(mobj_t *actor)
 	if (locvar1 == 1)
 		actor->angle += ANGLE_180;
 	else if (locvar1 == 2)
-	{
-		if (P_Random() & 1)
-			actor->angle += ANGLE_90;
-		else
-			actor->angle -= ANGLE_90;
-	}
+		actor->angle += (P_RandomChance(FRACUNIT/2)) ? ANGLE_90 : -ANGLE_90;
 
 	an = actor->angle >> ANGLETOFINESHIFT;
 
@@ -2398,9 +2393,9 @@ void A_BossScream(mobj_t *actor)
 		explodetype = (mobjtype_t)locvar2;
 
 	if (actor->eflags & MFE_VERTICALFLIP)
-		z = actor->z + actor->height - mobjinfo[explodetype].height - FixedMul((P_Random()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale);
+		z = actor->z + actor->height - mobjinfo[explodetype].height - FixedMul((P_RandomByte()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale);
 	else
-		z = actor->z + FixedMul((P_Random()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale);
+		z = actor->z + FixedMul((P_RandomByte()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale);
 
 	mo = P_SpawnMobj(x, y, z, explodetype);
 	if (actor->eflags & MFE_VERTICALFLIP)
@@ -3461,7 +3456,7 @@ void A_BubbleSpawn(mobj_t *actor)
 			return; // don't make bubble!
 	}
 
-	prandom = P_Random();
+	prandom = P_RandomByte();
 
 	if (leveltime % (3*TICRATE) < 8)
 		bubble = P_SpawnMobj(actor->x, actor->y, actor->z + (actor->height / 2), MT_EXTRALARGEBUBBLE);
@@ -3509,7 +3504,7 @@ void A_FanBubbleSpawn(mobj_t *actor)
 			return; // don't make bubble!
 	}
 
-	prandom = P_Random();
+	prandom = P_RandomByte();
 
 	if ((prandom & 0x7) == 0x7)
 		bubble = P_SpawnMobj(actor->x, actor->y, hz, MT_SMALLBUBBLE);
@@ -3550,7 +3545,7 @@ void A_BubbleRise(mobj_t *actor)
 		// Move around slightly to make it look like it's bending around the water
 		if (!locvar1)
 		{
-			UINT8 prandom = P_Random();
+			UINT8 prandom = P_RandomByte();
 			if (!(prandom & 0x7)) // *****000
 			{
 				P_InstaThrust(actor, prandom & 0x70 ? actor->angle + ANGLE_90 : actor->angle,
@@ -3833,7 +3828,7 @@ void A_ThrownRing(mobj_t *actor)
 
 	// first time init, this allow minimum lastlook changes
 	if (actor->lastlook < 0)
-		actor->lastlook = P_Random();
+		actor->lastlook = P_RandomByte();
 
 	actor->lastlook %= MAXPLAYERS;
 
@@ -3913,7 +3908,7 @@ void A_SetSolidSteam(mobj_t *actor)
 #endif
 	actor->flags &= ~MF_NOCLIP;
 	actor->flags |= MF_SOLID;
-	if (!(P_Random() & 7))
+	if (P_RandomChance(FRACUNIT/8))
 	{
 		if (actor->info->deathsound)
 			S_StartSound(actor, actor->info->deathsound); // Hiss!
@@ -4055,7 +4050,7 @@ void A_JetChase(mobj_t *actor)
 	if (actor->reactiontime)
 		actor->reactiontime--;
 
-	if (P_Random() % 32 == 1)
+	if (P_RandomChance(FRACUNIT/32))
 	{
 		actor->momx = actor->momx / 2;
 		actor->momy = actor->momy / 2;
@@ -4416,7 +4411,7 @@ void A_JetgThink(mobj_t *actor)
 
 	if (actor->target)
 	{
-		if (P_Random() <= 32 && !actor->reactiontime)
+		if (P_RandomChance(FRACUNIT/8) && !actor->reactiontime)
 			P_SetMobjState(actor, actor->info->missilestate);
 		else
 			A_JetChase (actor);
@@ -4469,10 +4464,10 @@ void A_MouseThink(mobj_t *actor)
 	{
 		if (twodlevel || actor->flags2 & MF2_TWOD)
 		{
-			if (P_Random() & 1)
+			if (P_RandomChance(FRACUNIT/2))
 				actor->angle += ANGLE_180;
 		}
-		else if (P_Random() & 1)
+		else if (P_RandomChance(FRACUNIT/2))
 			actor->angle += ANGLE_90;
 		else
 			actor->angle -= ANGLE_90;
@@ -4878,7 +4873,7 @@ void A_RockSpawn(mobj_t *actor)
 	type = MT_ROCKCRUMBLE1 + (sides[line->sidenum[0]].rowoffset >> FRACBITS);
 
 	if (line->flags & ML_NOCLIMB)
-		randomoomph = P_Random() * (FRACUNIT/32);
+		randomoomph = P_RandomByte() * (FRACUNIT/32);
 	else
 		randomoomph = 0;
 
@@ -5172,7 +5167,7 @@ void A_CrawlaCommanderThink(mobj_t *actor)
 
 	if (locvar1)
 	{
-		if (actor->health < 2 && P_Random() < 2)
+		if (actor->health < 2 && P_RandomChance(FRACUNIT/128))
 			P_SpawnMissile(actor, actor->target, locvar1);
 	}
 
@@ -5187,8 +5182,8 @@ void A_CrawlaCommanderThink(mobj_t *actor)
 		actor->threshold = 0;
 
 		// Roam around, somewhat in the player's direction.
-		actor->angle += (P_Random()<<10);
-		actor->angle -= (P_Random()<<10);
+		actor->angle += (P_RandomByte()<<10);
+		actor->angle -= (P_RandomByte()<<10);
 
 		if (actor->health > 1)
 			P_InstaThrust(actor, actor->angle, FixedMul(10*FRACUNIT, actor->scale));
@@ -5204,7 +5199,7 @@ void A_CrawlaCommanderThink(mobj_t *actor)
 				actor->threshold = 1;
 			}
 		}
-		actor->reactiontime = 2*TICRATE + P_Random()/2;
+		actor->reactiontime = 2*TICRATE + P_RandomByte()/2;
 	}
 
 	if (actor->health == 1)
@@ -5222,8 +5217,8 @@ void A_CrawlaCommanderThink(mobj_t *actor)
 		}
 		else
 		{
-			UINT8 prandom = P_Random();
-			actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_Random() & 1 ? -prandom : +prandom);
+			UINT8 prandom = P_RandomByte();
+			actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom);
 			P_InstaThrust(actor, actor->angle, FixedDiv(FixedMul(locvar2, actor->scale), 3*FRACUNIT/2));
 			actor->momz = FixedMul(locvar2, actor->scale); // Bounce up in air
 		}
@@ -5552,7 +5547,7 @@ void A_MixUp(mobj_t *actor)
 		{
 			if (counter > 255) // fail-safe to avoid endless loop
 				break;
-			prandom = P_Random();
+			prandom = P_RandomByte();
 			prandom %= numplayers; // I love modular arithmetic, don't you?
 			if (prandom) // Make sure it's not a useless mix
 				break;
@@ -5701,7 +5696,7 @@ void A_RecyclePowers(mobj_t *actor)
 	{
 		UINT8 tempint;
 
-		i = j + ((P_Random() + leveltime) % (numplayers - j));
+		i = j + ((P_RandomByte() + leveltime) % (numplayers - j));
 		tempint = postscramble[j];
 		postscramble[j] = postscramble[i];
 		postscramble[i] = tempint;
@@ -5814,7 +5809,7 @@ void A_Boss1Chase(mobj_t *actor)
 	{
 		if (actor->health > actor->info->damage)
 		{
-			if (P_Random() & 1)
+			if (P_RandomChance(FRACUNIT/2))
 				P_SetMobjState(actor, actor->info->missilestate);
 			else
 				P_SetMobjState(actor, actor->info->meleestate);
@@ -5833,7 +5828,7 @@ void A_Boss1Chase(mobj_t *actor)
 	// ?
 nomissile:
 	// possibly choose another target
-	if (multiplayer && P_Random() < 2)
+	if (multiplayer && P_RandomChance(FRACUNIT/128))
 	{
 		if (P_LookForPlayers(actor, true, false, 0))
 			return; // got a new target
@@ -5871,7 +5866,7 @@ nomissile:
 		deltay = actor->target->y - actor->y;
 
 		actor->movedir = diags[((deltay < 0)<<1) + (deltax > 0)];
-		actor->movecount = P_Random() & 15;
+		actor->movecount = P_RandomByte() & 15;
 	}
 }
 
@@ -5897,13 +5892,13 @@ void A_Boss2Chase(mobj_t *actor)
 
 	// Startup randomness
 	if (actor->reactiontime <= -666)
-		actor->reactiontime = 2*TICRATE + P_Random();
+		actor->reactiontime = 2*TICRATE + P_RandomByte();
 
 	// When reactiontime hits zero, he will go the other way
 	if (--actor->reactiontime <= 0)
 	{
 		reverse = true;
-		actor->reactiontime = 2*TICRATE + P_Random();
+		actor->reactiontime = 2*TICRATE + P_RandomByte();
 	}
 
 	P_SetTarget(&actor->target, P_GetClosestAxis(actor));
@@ -5990,12 +5985,12 @@ void A_Boss2Chase(mobj_t *actor)
 			if (actor->info->attacksound)
 				S_StartAttackSound(actor, actor->info->attacksound);
 
-			if (P_Random() & 1)
+			if (P_RandomChance(FRACUNIT/2))
 			{
 				goop->momx *= 2;
 				goop->momy *= 2;
 			}
-			else if (P_Random() > 128)
+			else if (P_RandomChance(129*FRACUNIT/256))
 			{
 				goop->momx *= 3;
 				goop->momy *= 3;
@@ -6153,7 +6148,7 @@ void A_Boss7Chase(mobj_t *actor)
 	{
 		A_FaceTarget(actor);
 		P_SetMobjState(actor, S_BLACKEGG_SHOOT1);
-		actor->movecount = TICRATE + P_Random()/2;
+		actor->movecount = TICRATE + P_RandomByte()/2;
 		return;
 	}
 
@@ -6162,7 +6157,7 @@ void A_Boss7Chase(mobj_t *actor)
 
 	if (actor->reactiontime <= 0 && actor->z == actor->floorz)
 	{
-		// Here, we'll call P_Random() and decide what kind of attack to do
+		// Here, we'll call P_RandomByte() and decide what kind of attack to do
 		switch(actor->threshold)
 		{
 			case 0: // Lob cannon balls
@@ -6170,7 +6165,7 @@ void A_Boss7Chase(mobj_t *actor)
 				{
 					A_FaceTarget(actor);
 					P_SetMobjState(actor, actor->info->xdeathstate);
-					actor->movecount = 7*TICRATE + P_Random();
+					actor->movecount = 7*TICRATE + P_RandomByte();
 					break;
 				}
 				actor->threshold++;
@@ -6180,9 +6175,9 @@ void A_Boss7Chase(mobj_t *actor)
 				P_SetMobjState(actor, S_BLACKEGG_SHOOT1);
 
 				if (actor->health > actor->info->damage)
-					actor->movecount = TICRATE + P_Random()/3;
+					actor->movecount = TICRATE + P_RandomByte()/3;
 				else
-					actor->movecount = TICRATE + P_Random()/2;
+					actor->movecount = TICRATE + P_RandomByte()/2;
 				break;
 			case 2: // Homing Missile
 				A_FaceTarget(actor);
@@ -6266,8 +6261,8 @@ void A_Boss2PogoSFX(mobj_t *actor)
 	}
 	else
 	{
-		UINT8 prandom = P_Random();
-		actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_Random() & 1 ? -prandom : +prandom);
+		UINT8 prandom = P_RandomByte();
+		actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom);
 		P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale));
 	}
 	if (actor->info->activesound) S_StartSound(actor, actor->info->activesound);
@@ -6307,10 +6302,10 @@ void A_Boss2PogoTarget(mobj_t *actor)
 	// Target hit, retreat!
 	if (actor->target->player->powers[pw_flashing] > TICRATE || actor->flags2 & MF2_FRET)
 	{
-		UINT8 prandom = P_Random();
+		UINT8 prandom = P_RandomByte();
 		actor->z++; // unstick from the floor
 		actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air
-		actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_Random() & 1 ? -prandom : +prandom); // Pick a direction, and randomize it.
+		actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); // Pick a direction, and randomize it.
 		P_InstaThrust(actor, actor->angle+ANGLE_180, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed
 	}
 	// Try to land on top of the player.
@@ -6347,10 +6342,10 @@ void A_Boss2PogoTarget(mobj_t *actor)
 	// Wander semi-randomly towards the player to get closer.
 	else
 	{
-		UINT8 prandom = P_Random();
+		UINT8 prandom = P_RandomByte();
 		actor->z++; // unstick from the floor
 		actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air
-		actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_Random() & 1 ? -prandom : +prandom); // Pick a direction, and randomize it.
+		actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); // Pick a direction, and randomize it.
 		P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed
 	}
 	// Boing!
@@ -7084,7 +7079,7 @@ void A_SmokeTrailer(mobj_t *actor)
 	P_SetObjectMomZ(th, FRACUNIT, false);
 	th->destscale = actor->scale;
 	P_SetScale(th, actor->scale);
-	th->tics -= P_Random() & 3;
+	th->tics -= P_RandomByte() & 3;
 	if (th->tics < 1)
 		th->tics = 1;
 }
@@ -7183,7 +7178,7 @@ void A_ChangeAngleRelative(mobj_t *actor)
 	//  rather than the ranges, so <0 and >360 work as possible values. -Red
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-	//angle_t angle = (P_Random()+1)<<24;
+	//angle_t angle = (P_RandomByte()+1)<<24;
 	const fixed_t amin = locvar1*FRACUNIT;
 	const fixed_t amax = locvar2*FRACUNIT;
 	//const angle_t amin = FixedAngle(locvar1*FRACUNIT);
@@ -7217,7 +7212,7 @@ void A_ChangeAngleAbsolute(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-	//angle_t angle = (P_Random()+1)<<24;
+	//angle_t angle = (P_RandomByte()+1)<<24;
 	const fixed_t amin = locvar1*FRACUNIT;
 	const fixed_t amax = locvar2*FRACUNIT;
 	//const angle_t amin = FixedAngle(locvar1*FRACUNIT);
@@ -7825,7 +7820,7 @@ void A_RandomState(mobj_t *actor)
 		return;
 #endif
 
-	P_SetMobjState(actor, P_Random()&1 ? locvar1 : locvar2);
+	P_SetMobjState(actor, P_RandomChance(FRACUNIT/2) ? locvar1 : locvar2);
 }
 
 // Function: A_RandomStateRange
@@ -8516,34 +8511,32 @@ void A_SearchForPlayers(mobj_t *actor)
 
 // Function: A_CheckRandom
 //
-// Description: Calls a state by chance (around 1/var1).
+// Description: Calls a state by chance.
 //
-// var1 = denominator (can't exceed 100)
+// var1:
+//		lower 16 bits = denominator
+//		upper 16 bits = numerator (defaults to 1 if zero)
 // var2 = state number
 //
 void A_CheckRandom(mobj_t *actor)
 {
 	INT32 locvar1 = var1;
 	INT32 locvar2 = var2;
-	INT32 i, chance;
-	INT32 rndadd = 0;
+	fixed_t chance = FRACUNIT;
+
 #ifdef HAVE_BLUA
 	if (LUA_CallAction("A_CheckRandom", actor))
 		return;
 #endif
+	if ((locvar1 & 0xFFFF) == 0)
+		return;
 
-	if(locvar1 > 100)
-		locvar1 = 100;
-
-	for (i = 0; i < MAXPLAYERS; i++)
-		if (playeringame[i])
-			rndadd += abs((int)players[i].mo->x) + abs((int)players[i].mo->y) + abs((int)players[i].mo->z);
-
-	rndadd = rndadd % 10000; //additional component to enlarge random number
-
-	chance = (P_Random() + rndadd) % locvar1;
+	// The PRNG doesn't suck anymore, OK?
+	if (locvar1 >> 16)
+		chance *= (locvar1 >> 16);
+	chance /= (locvar1 & 0xFFFF);
 
-	if (chance == 0)
+	if (P_RandomChance(chance))
 		P_SetMobjState(actor, locvar2);
 }
 
@@ -9890,7 +9883,7 @@ void A_BrakChase(mobj_t *actor)
 		S_StartSound(actor, (sfxenum_t)locvar2);
 
 	// make active sound
-	if (actor->type != MT_CYBRAKDEMON && actor->info->activesound && P_Random() < 3)
+	if (actor->type != MT_CYBRAKDEMON && actor->info->activesound && P_RandomChance(3*FRACUNIT/256))
 	{
 		S_StartSound(actor, actor->info->activesound);
 	}
diff --git a/src/p_inter.c b/src/p_inter.c
index c08f1f267a7c188681626d18ec4b66692bacb563..7809d6c59b519c947e05d9ca6ef9f3f0b36213e7 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -1253,7 +1253,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 
 				if (special->target && special->target->state == &states[S_BLACKEGG_SHOOT1])
 				{
-					if (special->target->health <= 2 && (P_Random() & 1))
+					if (special->target->health <= 2 && P_RandomChance(FRACUNIT/2))
 						P_SetMobjState(special->target, special->target->info->missilestate);
 					else
 						P_SetMobjState(special->target, special->target->info->raisestate);
@@ -2203,29 +2203,17 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
 
 				default:
 					if (target->info->doomednum)
+						prandom = target->info->doomednum%5; // "Random" animal for new enemies.
+					else
+						prandom = P_RandomKey(5); // No placable object, just use a random number.
+
+					switch(prandom)
 					{
-						switch(target->info->doomednum%5)
-						{
 						default: item = MT_BUNNY; break;
 						case 1: item = MT_BIRD; break;
 						case 2: item = MT_MOUSE; break;
 						case 3: item = MT_COW; break;
 						case 4: item = MT_CHICKEN; break;
-						}
-					}
-					else
-					{
-						prandom = P_Random();
-						if (prandom < 51)
-							item = MT_BUNNY;
-						else if (prandom < 102)
-							item = MT_BIRD;
-						else if (prandom < 153)
-							item = MT_MOUSE;
-						else if (prandom < 204)
-							item = MT_COW;
-						else
-							item = MT_CHICKEN;
 					}
 					break;
 			}
@@ -3103,7 +3091,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 
 	// Killing dead. Just for kicks.
 	// Require source and inflictor be player.  Don't hurt for firing rings.
-	if (cv_killingdead.value && (source && source->player) && (inflictor && inflictor->player) && P_Random() < 80)
+	if (cv_killingdead.value && (source && source->player) && (inflictor && inflictor->player) && P_RandomChance(5*FRACUNIT/16))
 		P_DamageMobj(source, target, target, 1);
 
 	// do the damage
@@ -3617,7 +3605,7 @@ void P_PlayerFlagBurst(player_t *player, boolean toss)
 		P_InstaThrust(flag, player->mo->angle, FixedMul(6*FRACUNIT, player->mo->scale));
 	else
 	{
-		angle_t fa = P_Random()*FINEANGLES/256;
+		angle_t fa = P_RandomByte()*FINEANGLES/256;
 		flag->momx = FixedMul(FINECOSINE(fa), FixedMul(6*FRACUNIT, player->mo->scale));
 		if (!(twodlevel || (player->mo->flags2 & MF2_TWOD)))
 			flag->momy = FixedMul(FINESINE(fa), FixedMul(6*FRACUNIT, player->mo->scale));
diff --git a/src/p_lights.c b/src/p_lights.c
index 2dfe006dc1f1d2b4884d884b9c3701d645f76a1a..a9758c723307cd92edc82bfcd73e17ab76396915 100644
--- a/src/p_lights.c
+++ b/src/p_lights.c
@@ -51,7 +51,7 @@ void T_FireFlicker(fireflicker_t *flick)
 	if (--flick->count)
 		return;
 
-	amount = (INT16)((UINT8)(P_Random() & 3) * 16);
+	amount = (INT16)((UINT8)(P_RandomByte() & 3) * 16);
 
 	if (flick->sector->lightlevel - amount < flick->minlight)
 		flick->sector->lightlevel = (INT16)flick->minlight;
@@ -235,7 +235,7 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector,
 		flash->minlight = 0;
 
 	if (!inSync)
-		flash->count = (P_Random() & 7) + 1;
+		flash->count = (P_RandomByte() & 7) + 1;
 	else
 		flash->count = 1;
 
diff --git a/src/p_map.c b/src/p_map.c
index 304f286f2f7737417d5650a5667f6827c4933611..c980b41a643d35355eda8d71780fd00f6c4553f3 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -1152,13 +1152,17 @@ static boolean PIT_CheckLine(line_t *ld)
 	{
 		tmceilingz = opentop;
 		ceilingline = ld;
+#ifdef ESLOPE
 		tmceilingslope = opentopslope;
+#endif
 	}
 
 	if (openbottom > tmfloorz)
 	{
 		tmfloorz = openbottom;
+#ifdef ESLOPE
 		tmfloorslope = openbottomslope;
+#endif
 	}
 
 	if (highceiling > tmdrpoffceilz)
@@ -1971,22 +1975,28 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 						thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
 						thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 					}
-					else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
+#ifdef ESLOPE
+					// HACK TO FIX DSZ2: apply only if slopes are involved
+					else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
 					{
 						thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
 						thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 					}
+#endif
 				}
 				else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep)
 				{
 					thing->z = thing->floorz = tmfloorz;
 					thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 				}
-				else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
+#ifdef ESLOPE
+				// HACK TO FIX DSZ2: apply only if slopes are involved
+				else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
 				{
 					thing->z = thing->floorz = tmfloorz;
 					thing->eflags |= MFE_JUSTSTEPPEDDOWN;
 				}
+#endif
 			}
 
 			if (thing->eflags & MFE_VERTICALFLIP)
@@ -2057,21 +2067,26 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 	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->flags & MF_NOCLIPHEIGHT))
+	{
+		// 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 = 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;
+			if (thing->momz >= 0)
+				thing->standingslope = tmceilingslope;
+		}
 	}
+	else // don't set standingslope if you're not going to clip against it
+		thing->standingslope = NULL;
 #endif
 
 	thing->x = x;
diff --git a/src/p_maputl.c b/src/p_maputl.c
index 82d9bbfe4001d129b62bd0c126a50840d0afda77..6bd94362ffd23312cfcaddd48b418fe2fa37967a 100644
--- a/src/p_maputl.c
+++ b/src/p_maputl.c
@@ -527,13 +527,17 @@ void P_LineOpening(line_t *linedef)
 		{
 			opentop = frontheight;
 			highceiling = backheight;
+#ifdef ESLOPE
 			opentopslope = front->c_slope;
+#endif
 		}
 		else
 		{
 			opentop = backheight;
 			highceiling = frontheight;
+#ifdef ESLOPE
 			opentopslope = back->c_slope;
+#endif
 		}
 
 		frontheight = P_GetFloorZ(tmthing, front, tmx, tmy, linedef);
@@ -543,13 +547,17 @@ void P_LineOpening(line_t *linedef)
 		{
 			openbottom = frontheight;
 			lowfloor = backheight;
+#ifdef ESLOPE
 			openbottomslope = front->f_slope;
+#endif
 		}
 		else
 		{
 			openbottom = backheight;
 			lowfloor = frontheight;
+#ifdef ESLOPE
 			openbottomslope = back->f_slope;
+#endif
 		}
 	}
 
diff --git a/src/p_mobj.c b/src/p_mobj.c
index ce67f1a5a15d6c72a8e9e492cf079c063f8d43d9..bcbb72c42b7c9b635d2a412582fed13dcedb4199 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -38,7 +38,9 @@
 // protos.
 static CV_PossibleValue_t viewheight_cons_t[] = {{16, "MIN"}, {56, "MAX"}, {0, NULL}};
 consvar_t cv_viewheight = {"viewheight", VIEWHEIGHTS, 0, viewheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
+#ifdef WALLSPLATS
 consvar_t cv_splats = {"splats", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
+#endif
 
 actioncache_t actioncachehead;
 
@@ -652,9 +654,9 @@ void P_EmeraldManager(void)
 				break;
 
 			if (leveltime < TICRATE) // Start of map
-				spawnpoints[j]->threshold = 60*TICRATE + P_Random() * (TICRATE/5);
+				spawnpoints[j]->threshold = 60*TICRATE + P_RandomByte() * (TICRATE/5);
 			else
-				spawnpoints[j]->threshold = P_Random() * (TICRATE/5);
+				spawnpoints[j]->threshold = P_RandomByte() * (TICRATE/5);
 
 			break;
 		}
@@ -683,26 +685,26 @@ void P_ExplodeMissile(mobj_t *mo)
 		explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
 		P_SetScale(explodemo, mo->scale);
 		explodemo->destscale = mo->destscale;
-		explodemo->momx += (P_Random() % 32) * FixedMul(FRACUNIT/8, explodemo->scale);
-		explodemo->momy += (P_Random() % 32) * FixedMul(FRACUNIT/8, explodemo->scale);
+		explodemo->momx += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale);
+		explodemo->momy += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale);
 		S_StartSound(explodemo, sfx_pop);
 		explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
 		P_SetScale(explodemo, mo->scale);
 		explodemo->destscale = mo->destscale;
-		explodemo->momx += (P_Random() % 64) * FixedMul(FRACUNIT/8, explodemo->scale);
-		explodemo->momy -= (P_Random() % 64) * FixedMul(FRACUNIT/8, explodemo->scale);
+		explodemo->momx += (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale);
+		explodemo->momy -= (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale);
 		S_StartSound(explodemo, sfx_dmpain);
 		explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
 		P_SetScale(explodemo, mo->scale);
 		explodemo->destscale = mo->destscale;
-		explodemo->momx -= (P_Random() % 128) * FixedMul(FRACUNIT/8, explodemo->scale);
-		explodemo->momy += (P_Random() % 128) * FixedMul(FRACUNIT/8, explodemo->scale);
+		explodemo->momx -= (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale);
+		explodemo->momy += (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale);
 		S_StartSound(explodemo, sfx_pop);
 		explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
 		P_SetScale(explodemo, mo->scale);
 		explodemo->destscale = mo->destscale;
-		explodemo->momx -= (P_Random() % 96) * FixedMul(FRACUNIT/8, explodemo->scale);
-		explodemo->momy -= (P_Random() % 96) * FixedMul(FRACUNIT/8, explodemo->scale);
+		explodemo->momx -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale);
+		explodemo->momy -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale);
 		S_StartSound(explodemo, sfx_cybdth);
 
 		// Hack: Release an animal.
@@ -752,6 +754,7 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover)
 	return true;
 }
 
+#ifdef ESLOPE
 // 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
@@ -855,10 +858,13 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line,
 			P_GetZAt(slope, v2.x, v2.y)
 		);
 }
+#endif
 
 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)
 {
+#ifdef ESLOPE
 	I_Assert(mobj != NULL);
+#endif
 	I_Assert(sector != NULL);
 #ifdef ESLOPE
 	if (sector->f_slope) {
@@ -930,13 +936,23 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
 
 		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
 	} else // Well, that makes it easy. Just get the floor height
+#else
+	(void)mobj;
+	(void)boundsec;
+	(void)x;
+	(void)y;
+	(void)line;
+	(void)lowest;
+	(void)perfect;
 #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)
 {
+#ifdef ESLOPE
 	I_Assert(mobj != NULL);
+#endif
 	I_Assert(sector != NULL);
 #ifdef ESLOPE
 	if (sector->c_slope) {
@@ -1008,6 +1024,14 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
 
 		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
 	} else // Well, that makes it easy. Just get the ceiling height
+#else
+	(void)mobj;
+	(void)boundsec;
+	(void)x;
+	(void)y;
+	(void)line;
+	(void)lowest;
+	(void)perfect;
 #endif
 		return sector->ceilingheight;
 }
@@ -1015,7 +1039,9 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
 // 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)
 {
+#ifdef ESLOPE
 	I_Assert(mobj != NULL);
+#endif
 	I_Assert(sector != NULL);
 #ifdef ESLOPE
 	if (sector->f_slope) {
@@ -1087,13 +1113,23 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix
 
 		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
 	} else // Well, that makes it easy. Just get the floor height
+#else
+	(void)mobj;
+	(void)boundsec;
+	(void)x;
+	(void)y;
+	(void)line;
+	(void)lowest;
+	(void)perfect;
 #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)
 {
+#ifdef ESLOPE
 	I_Assert(mobj != NULL);
+#endif
 	I_Assert(sector != NULL);
 #ifdef ESLOPE
 	if (sector->c_slope) {
@@ -1165,6 +1201,14 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
 
 		return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
 	} else // Well, that makes it easy. Just get the ceiling height
+#else
+	(void)mobj;
+	(void)boundsec;
+	(void)x;
+	(void)y;
+	(void)line;
+	(void)lowest;
+	(void)perfect;
 #endif
 		return sector->ceilingheight;
 }
@@ -2106,8 +2150,13 @@ static boolean P_ZMovement(mobj_t *mo)
 	I_Assert(!P_MobjWasRemoved(mo));
 
 #ifdef ESLOPE
-	if (mo->standingslope && !P_IsObjectOnGround(mo))
+	if (mo->standingslope)
+	{
+		if (mo->flags & MF_NOCLIPHEIGHT)
+			mo->standingslope = NULL;
+		else if (!P_IsObjectOnGround(mo))
 			P_SlopeLaunch(mo);
+	}
 #endif
 
 	// Intercept the stupid 'fall through 3dfloors' bug
@@ -2405,12 +2454,12 @@ static boolean P_ZMovement(mobj_t *mo)
 							// If deafed, give the tumbleweed another random kick if it runs out of steam.
 							mom.z += P_MobjFlip(mo)*FixedMul(6*FRACUNIT, mo->scale);
 
-							if (P_Random() & 1)
+							if (P_RandomChance(FRACUNIT/2))
 								mom.x += FixedMul(6*FRACUNIT, mo->scale);
 							else
 								mom.x -= FixedMul(6*FRACUNIT, mo->scale);
 
-							if (P_Random() & 1)
+							if (P_RandomChance(FRACUNIT/2))
 								mom.y += FixedMul(6*FRACUNIT, mo->scale);
 							else
 								mom.y -= FixedMul(6*FRACUNIT, mo->scale);
@@ -2588,8 +2637,13 @@ static void P_PlayerZMovement(mobj_t *mo)
 		return;
 
 #ifdef ESLOPE
-	if (mo->standingslope && !P_IsObjectOnGround(mo))
+	if (mo->standingslope)
+	{
+		if (mo->flags & MF_NOCLIPHEIGHT)
+			mo->standingslope = NULL;
+		else if (!P_IsObjectOnGround(mo))
 			P_SlopeLaunch(mo);
+	}
 #endif
 
 	// clip movement
@@ -2886,7 +2940,7 @@ static boolean P_SceneryZMovement(mobj_t *mo)
 
 				for (i = 0; i < 4; ++i) // split into four
 				{
-					prandom = P_Random();
+					prandom = P_RandomByte();
 					explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_SMALLBUBBLE);
 					explodemo->momx += ((prandom & 0x0F) << (FRACBITS-2)) * (i & 2 ? -1 : 1);
 					explodemo->momy += ((prandom & 0xF0) << (FRACBITS-6)) * (i & 1 ? -1 : 1);
@@ -3218,13 +3272,13 @@ void P_MobjCheckWater(mobj_t *mobj)
 			// Create tons of bubbles
 			for (i = 0; i < bubblecount; i++)
 			{
-				// P_Random()s are called individually to allow consistency
+				// P_RandomByte()s are called individually to allow consistency
 				// across various compilers, since the order of function calls
 				// in C is not part of the ANSI specification.
-				prandom[0] = P_Random();
-				prandom[1] = P_Random();
-				prandom[2] = P_Random();
-				prandom[3] = P_Random();
+				prandom[0] = P_RandomByte();
+				prandom[1] = P_RandomByte();
+				prandom[2] = P_RandomByte();
+				prandom[3] = P_RandomByte();
 
 				bubbletype = MT_SMALLBUBBLE;
 				if (!(prandom[0] & 0x3)) // medium bubble chance up to 64 from 32
@@ -3698,10 +3752,15 @@ static void CalculatePrecipFloor(precipmobj_t *mobj)
 		mobjsecsubsec = mobj->subsector->sector;
 	else
 		return;
-	mobj->floorz = mobjsecsubsec->floorheight;
+	mobj->floorz =
+#ifdef ESLOPE
+				mobjsecsubsec->f_slope ? P_GetZAt(mobjsecsubsec->f_slope, mobj->x, mobj->y) :
+#endif
+				mobjsecsubsec->floorheight;
 	if (mobjsecsubsec->ffloors)
 	{
 		ffloor_t *rover;
+		fixed_t topheight;
 
 		for (rover = mobjsecsubsec->ffloors; rover; rover = rover->next)
 		{
@@ -3712,8 +3771,15 @@ static void CalculatePrecipFloor(precipmobj_t *mobj)
 			if (!(rover->flags & FF_BLOCKOTHERS) && !(rover->flags & FF_SWIMMABLE))
 				continue;
 
-			if (*rover->topheight > mobj->floorz)
-				mobj->floorz = *rover->topheight;
+#ifdef ESLOPE
+			if (*rover->t_slope)
+				topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y);
+			else
+#endif
+			topheight = *rover->topheight;
+
+			if (topheight > mobj->floorz)
+				mobj->floorz = topheight;
 		}
 	}
 }
@@ -3826,7 +3892,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest)
 
 	// first time init, this allow minimum lastlook changes
 	if (actor->lastlook < 0)
-		actor->lastlook = P_Random();
+		actor->lastlook = P_RandomByte();
 	actor->lastlook &= PLAYERSMASK;
 
 	for( ; ; actor->lastlook = (actor->lastlook+1) & PLAYERSMASK)
@@ -4707,7 +4773,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
 
 	if (mobj->state == &states[S_BLACKEGG_STND] && mobj->tics == mobj->state->tics)
 	{
-		mobj->reactiontime += P_Random();
+		mobj->reactiontime += P_RandomByte();
 
 		if (mobj->health <= mobj->info->damage)
 			mobj->reactiontime /= 4;
@@ -4901,7 +4967,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
 		if (mobj->tracer && mobj->tracer->type == MT_BOSS3WAYPOINT
 			&& mobj->tracer->spawnpoint && (mobj->tracer->spawnpoint->options & 7) == waypointNum)
 		{
-			if (P_Random() & 1)
+			if (P_RandomChance(FRACUNIT/2))
 				waypointNum++;
 			else
 				waypointNum--;
@@ -4913,7 +4979,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
 		}
 
 		if (waypointNum == 0 && mobj->health <= mobj->info->damage)
-			waypointNum = 1 + (P_Random() & 1);
+			waypointNum = 1 + (P_RandomFixed() & 1);
 
 		// scan the thinkers to find
 		// the waypoint to use
@@ -5013,7 +5079,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
 		P_SetMobjState(mobj, mobj->info->spawnstate);
 	}
 	else if (mobj->state == &states[mobj->info->deathstate] && mobj->tics == mobj->state->tics)
-		S_StartSound(0, sfx_bedie1 + (P_Random() & 1));
+		S_StartSound(0, sfx_bedie1 + (P_RandomFixed() & 1));
 
 }
 
@@ -5440,7 +5506,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
 				// An incoming attack is detected! What should we do?!
 				// Go into vector form!
 				mobj->movedir = ANGLE_11hh - FixedAngle(FixedMul(AngleFixed(ANGLE_11hh), FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS)));
-				if (P_Random()&1)
+				if (P_RandomChance(FRACUNIT/2))
 					mobj->movedir = InvAngle(mobj->movedir);
 				mobj->threshold = 6 + (FixedMul(24<<FRACBITS, FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS))>>FRACBITS);
 				if (mobj->info->activesound)
@@ -6042,20 +6108,20 @@ static void P_KoopaThinker(mobj_t *koopa)
 
 	P_XYMovement(koopa);
 
-	if (P_Random() < 8 && koopa->z <= koopa->floorz)
+	if (P_RandomChance(FRACUNIT/32) && koopa->z <= koopa->floorz)
 		koopa->momz = FixedMul(5*FRACUNIT, koopa->scale);
 
 	if (koopa->z > koopa->floorz)
 		koopa->momz += FixedMul(FRACUNIT/4, koopa->scale);
 
-	if (P_Random() < 4)
+	if (P_RandomChance(FRACUNIT/64))
 	{
 		mobj_t *flame;
-		flame = P_SpawnMobj(koopa->x - koopa->radius + FixedMul(5*FRACUNIT, koopa->scale), koopa->y, koopa->z + (P_Random()<<(FRACBITS-2)), MT_KOOPAFLAME);
+		flame = P_SpawnMobj(koopa->x - koopa->radius + FixedMul(5*FRACUNIT, koopa->scale), koopa->y, koopa->z + (P_RandomByte()<<(FRACBITS-2)), MT_KOOPAFLAME);
 		flame->momx = -FixedMul(flame->info->speed, flame->scale);
 		S_StartSound(flame, sfx_koopfr);
 	}
-	else if (P_Random() > 250)
+	else if (P_RandomChance(5*FRACUNIT/256))
 	{
 		mobj_t *hammer;
 		hammer = P_SpawnMobj(koopa->x - koopa->radius, koopa->y, koopa->z + koopa->height, MT_HAMMER);
@@ -6499,11 +6565,11 @@ void P_MobjThinker(mobj_t *mobj)
 				fixed_t ns;
 				mobj_t *mo2;
 
-				i = P_Random();
-				z = mobj->subsector->sector->floorheight + ((P_Random()&63)*FRACUNIT);
+				i = P_RandomByte();
+				z = mobj->subsector->sector->floorheight + ((P_RandomByte()&63)*FRACUNIT);
 				for (j = 0; j < 2; j++)
 				{
-					const angle_t fa = (P_Random()*FINEANGLES/16) & FINEMASK;
+					const angle_t fa = (P_RandomByte()*FINEANGLES/16) & FINEMASK;
 					ns = 64 * FRACUNIT;
 					x = mobj->x + FixedMul(FINESINE(fa),ns);
 					y = mobj->y + FixedMul(FINECOSINE(fa),ns);
@@ -6513,7 +6579,7 @@ void P_MobjThinker(mobj_t *mobj)
 					mo2->momx = FixedMul(FINESINE(fa),ns);
 					mo2->momy = FixedMul(FINECOSINE(fa),ns);
 
-					i = P_Random();
+					i = P_RandomByte();
 
 					if (i % 5 == 0)
 						P_SpawnMobj(x, y, z, MT_CHICKEN);
@@ -7753,6 +7819,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
 {
 	state_t *st;
 	precipmobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
+	fixed_t starting_floorz;
 
 	mobj->x = x;
 	mobj->y = y;
@@ -7771,8 +7838,16 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
 	// set subsector and/or block links
 	P_SetPrecipitationThingPosition(mobj);
 
-	mobj->floorz = mobj->subsector->sector->floorheight;
-	mobj->ceilingz = mobj->subsector->sector->ceilingheight;
+	mobj->floorz = starting_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;
 
 	mobj->z = z;
 	mobj->momz = mobjinfo[type].speed;
@@ -7782,7 +7857,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
 
 	CalculatePrecipFloor(mobj);
 
-	if (mobj->floorz != mobj->subsector->sector->floorheight)
+	if (mobj->floorz != starting_floorz)
 		mobj->precipflags |= PCF_FOF;
 	else if (GETSECSPECIAL(mobj->subsector->sector->special, 1) == 7
 	 || GETSECSPECIAL(mobj->subsector->sector->special, 1) == 6
@@ -7999,7 +8074,7 @@ void P_SpawnPrecipitation(void)
 					continue;
 
 				rainmo = P_SpawnSnowMobj(x, y, height, MT_SNOWFLAKE);
-				mrand = M_Random();
+				mrand = M_RandomByte();
 				if (mrand < 64)
 					P_SetPrecipMobjState(rainmo, S_SNOW3);
 				else if (mrand < 144)
@@ -8209,7 +8284,11 @@ void P_RespawnSpecials(void)
 
 		if (mthing->options & MTF_OBJECTFLIP)
 		{
-			z = ss->sector->ceilingheight - (mthing->options >> ZSHIFT) * FRACUNIT;
+			z = (
+#ifdef ESLOPE
+			ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) :
+#endif
+			ss->sector->ceilingheight) - (mthing->options >> ZSHIFT) * FRACUNIT;
 			if (mthing->options & MTF_AMBUSH
 			&& (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING || i == MT_COIN || P_WeaponOrPanel(i)))
 				z -= 24*FRACUNIT;
@@ -8217,7 +8296,11 @@ void P_RespawnSpecials(void)
 		}
 		else
 		{
-			z = ss->sector->floorheight + (mthing->options >> ZSHIFT) * FRACUNIT;
+			z = (
+#ifdef ESLOPE
+			ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) :
+#endif
+			ss->sector->floorheight) + (mthing->options >> ZSHIFT) * FRACUNIT;
 			if (mthing->options & MTF_AMBUSH
 			&& (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING || i == MT_COIN || P_WeaponOrPanel(i)))
 				z += 24*FRACUNIT;
@@ -8387,7 +8470,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
 
 	fixed_t z;
 	sector_t *sector;
-
+	fixed_t floor, ceiling;
 
 	player_t *p = &players[playernum];
 	mobj_t *mobj = p->mo;
@@ -8403,19 +8486,31 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
 
 	// set Z height
 	sector = R_PointInSubsector(x, y)->sector;
+
+	floor =
+#ifdef ESLOPE
+	sector->f_slope ? P_GetZAt(sector->f_slope, x, y) :
+#endif
+	sector->floorheight;
+	ceiling =
+#ifdef ESLOPE
+	sector->c_slope ? P_GetZAt(sector->c_slope, x, y) :
+#endif
+	sector->ceilingheight;
+
 	if (mthing)
 	{
 		// Flagging a player's ambush will make them start on the ceiling
 		// Objectflip inverts
 		if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP))
 		{
-			z = sector->ceilingheight - mobjinfo[MT_PLAYER].height;
+			z = ceiling - mobjinfo[MT_PLAYER].height;
 			if (mthing->options >> ZSHIFT)
 				z -= ((mthing->options >> ZSHIFT) << FRACBITS);
 		}
 		else
 		{
-			z = sector->floorheight;
+			z = floor;
 			if (mthing->options >> ZSHIFT)
 				z += ((mthing->options >> ZSHIFT) << FRACBITS);
 		}
@@ -8427,15 +8522,15 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
 		}
 	}
 	else
-		z = sector->floorheight;
+		z = floor;
 
-	if (z < sector->floorheight)
-		z = sector->floorheight;
-	else if (z > sector->ceilingheight - mobjinfo[MT_PLAYER].height)
-		z = sector->ceilingheight - mobjinfo[MT_PLAYER].height;
+	if (z < floor)
+		z = floor;
+	else if (z > ceiling - mobjinfo[MT_PLAYER].height)
+		z = ceiling - mobjinfo[MT_PLAYER].height;
 
-	mobj->floorz = sector->floorheight;
-	mobj->ceilingz = sector->ceilingheight;
+	mobj->floorz = floor;
+	mobj->ceilingz = ceiling;
 
 	P_UnsetThingPosition(mobj);
 	mobj->x = x;
@@ -8443,7 +8538,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
 	P_SetThingPosition(mobj);
 
 	mobj->z = z;
-	if (mobj->z == sector->floorheight)
+	if (mobj->z == mobj->floorz)
 		mobj->eflags |= MFE_ONGROUND;
 
 	mobj->angle = angle;
@@ -8455,6 +8550,7 @@ void P_MovePlayerToStarpost(INT32 playernum)
 {
 	fixed_t z;
 	sector_t *sector;
+	fixed_t floor, ceiling;
 
 	player_t *p = &players[playernum];
 	mobj_t *mobj = p->mo;
@@ -8466,14 +8562,25 @@ void P_MovePlayerToStarpost(INT32 playernum)
 	P_SetThingPosition(mobj);
 	sector = R_PointInSubsector(mobj->x, mobj->y)->sector;
 
+	floor =
+#ifdef ESLOPE
+	sector->f_slope ? P_GetZAt(sector->f_slope, mobj->x, mobj->y) :
+#endif
+	sector->floorheight;
+	ceiling =
+#ifdef ESLOPE
+	sector->c_slope ? P_GetZAt(sector->c_slope, mobj->x, mobj->y) :
+#endif
+	sector->ceilingheight;
+
 	z = p->starpostz << FRACBITS;
-	if (z < sector->floorheight)
-		z = sector->floorheight;
-	else if (z > sector->ceilingheight - mobjinfo[MT_PLAYER].height)
-		z = sector->ceilingheight - mobjinfo[MT_PLAYER].height;
+	if (z < floor)
+		z = floor;
+	else if (z > ceiling - mobjinfo[MT_PLAYER].height)
+		z = ceiling - mobjinfo[MT_PLAYER].height;
 
-	mobj->floorz = sector->floorheight;
-	mobj->ceilingz = sector->ceilingheight;
+	mobj->floorz = floor;
+	mobj->ceilingz = ceiling;
 
 	mobj->z = z;
 	if (mobj->z == mobj->floorz)
@@ -9167,12 +9274,12 @@ ML_NOCLIMB : Direction not controllable
 		{
 			mobj->momz += FixedMul(16*FRACUNIT, mobj->scale);
 
-			if (P_Random() & 1)
+			if (P_RandomChance(FRACUNIT/2))
 				mobj->momx += FixedMul(16*FRACUNIT, mobj->scale);
 			else
 				mobj->momx -= FixedMul(16*FRACUNIT, mobj->scale);
 
-			if (P_Random() & 1)
+			if (P_RandomChance(FRACUNIT/2))
 				mobj->momy += FixedMul(16*FRACUNIT, mobj->scale);
 			else
 				mobj->momy -= FixedMul(16*FRACUNIT,mobj->scale);
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 952e567d7d410ede4c6aa4f57e3e8772c2e52c48..31607cdc3c077b54b35a61af5d8a5f3587a33c20 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -924,8 +924,12 @@ typedef enum
 	MD2_EXTVAL1     = 1<<5,
 	MD2_EXTVAL2     = 1<<6,
 	MD2_HNEXT       = 1<<7,
+#ifdef ESLOPE
 	MD2_HPREV       = 1<<8,
 	MD2_SLOPE       = 1<<9
+#else
+	MD2_HPREV       = 1<<8
+#endif
 } mobj_diff2_t;
 
 typedef enum
@@ -1115,8 +1119,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 		diff2 |= MD2_HNEXT;
 	if (mobj->hprev)
 		diff2 |= MD2_HPREV;
+#ifdef ESLOPE
 	if (mobj->standingslope)
 		diff2 |= MD2_SLOPE;
+#endif
 	if (diff2 != 0)
 		diff |= MD_MORE;
 
@@ -1232,8 +1238,10 @@ 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);
+#ifdef ESLOPE
 	if (diff2 & MD2_SLOPE)
 		WRITEUINT16(save_p, mobj->standingslope->id);
+#endif
 
 	WRITEUINT32(save_p, mobj->mobjnum);
 }
@@ -2087,8 +2095,10 @@ 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);
+#ifdef ESLOPE
 	if (diff2 & MD2_SLOPE)
 		mobj->standingslope = P_SlopeById(READUINT16(save_p));
+#endif
 
 
 	if (diff & MD_REDFLAG)
diff --git a/src/p_slopes.c b/src/p_slopes.c
index 2d55cf19451f25458f61fa5c01c9608e7f13e3b0..797fe46b4b282f20e1208512f65c50d0479dff44 100644
--- a/src/p_slopes.c
+++ b/src/p_slopes.c
@@ -1099,6 +1099,9 @@ void P_ButteredSlope(mobj_t *mo)
 	if (!mo->standingslope)
 		return;
 
+	if (mo->flags & (MF_NOCLIPHEIGHT|MF_NOGRAVITY))
+		return; // don't slide down slopes if you can't touch them or you're not affected by gravity
+
 	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
diff --git a/src/p_spec.c b/src/p_spec.c
index 7f911a3379b49817e70fb3906c8b009e65a33d9b..576deaef013289d4f046c03b15fe229b7244190d 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -2059,7 +2059,7 @@ void P_SwitchWeather(INT32 weathernum)
 				precipmobj = (precipmobj_t *)think;
 
 				precipmobj->flags = mobjinfo[MT_SNOWFLAKE].flags;
-				z = M_Random();
+				z = M_RandomByte();
 
 				if (z < 64)
 					z = 2;
@@ -4675,8 +4675,10 @@ void P_UpdateSpecials(void)
 	// POINT LIMIT
 	P_CheckPointLimit();
 
+#ifdef ESLOPE
 	// Dynamic slopeness
 	P_RunDynamicSlopes();
+#endif
 
 	// ANIMATE TEXTURES
 	for (anim = anims; anim < lastanim; anim++)
diff --git a/src/p_tick.c b/src/p_tick.c
index c72ab5b6730053222bbd796462546241c5288826..d45f5882115e3e04308deee7b13aa44726673d54 100644
--- a/src/p_tick.c
+++ b/src/p_tick.c
@@ -363,7 +363,7 @@ static void P_DoAutobalanceTeams(void)
 	{
 		if (totalred > totalblue)
 		{
-			i = M_Random() % red;
+			i = M_RandomKey(red);
 			NetPacket.packet.newteam = 2;
 			NetPacket.packet.playernum = redarray[i];
 			NetPacket.packet.verification = true;
@@ -375,7 +375,7 @@ static void P_DoAutobalanceTeams(void)
 
 		if (totalblue > totalred)
 		{
-			i = M_Random() % blue;
+			i = M_RandomKey(blue);
 			NetPacket.packet.newteam = 1;
 			NetPacket.packet.playernum = bluearray[i];
 			NetPacket.packet.verification = true;
diff --git a/src/p_user.c b/src/p_user.c
index da02c74fef607e2a451caee25ee1bba29fac4266..26e30dfb2957997c15efc0a8d19c0b5bd01fb199 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -2172,9 +2172,9 @@ static void P_DoBubbleBreath(player_t *player)
 	if (!(player->mo->eflags & MFE_UNDERWATER) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && !(player->pflags & PF_NIGHTSMODE)) || player->spectator)
 		return;
 
-	if (!(P_Random() % 16))
+	if (P_RandomChance(FRACUNIT/16))
 		bubble = P_SpawnMobj(player->mo->x, player->mo->y, zh, MT_SMALLBUBBLE);
-	else if (!(P_Random() % 96))
+	else if (P_RandomChance(3*FRACUNIT/256))
 		bubble = P_SpawnMobj(player->mo->x, player->mo->y, zh, MT_MEDIUMBUBBLE);
 	if (bubble)
 	{
@@ -6186,6 +6186,14 @@ void P_ElementalFireTrail(player_t *player)
 	{
 		newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(24*FRACUNIT, player->mo->scale));
 		newy = player->mo->y + P_ReturnThrustY(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(24*FRACUNIT, player->mo->scale));
+#ifdef ESLOPE
+		if (player->mo->standingslope)
+		{
+			ground = P_GetZAt(player->mo->standingslope, newx, newy);
+			if (player->mo->eflags & MFE_VERTICALFLIP)
+				ground -= FixedMul(mobjinfo[MT_SPINFIRE].height, player->mo->scale);
+		}
+#endif
 		flame = P_SpawnMobj(newx, newy, ground, MT_SPINFIRE);
 		P_SetTarget(&flame->target, player->mo);
 		flame->angle = travelangle;
@@ -6626,7 +6634,7 @@ static void P_MovePlayer(player_t *player)
 	// Little water sound while touching water - just a nicety.
 	if ((player->mo->eflags & MFE_TOUCHWATER) && !(player->mo->eflags & MFE_UNDERWATER) && !player->spectator)
 	{
-		if (P_Random() & 1 && leveltime % TICRATE == 0)
+		if (P_RandomChance(FRACUNIT/2) && leveltime % TICRATE == 0)
 			S_StartSound(player->mo, sfx_floush);
 	}
 
@@ -6840,7 +6848,7 @@ static void P_MovePlayer(player_t *player)
 				}
 			}
 			// Super Sonic move
-			if (player->charflags & SF_SUPER && player->powers[pw_super] && player->speed > FixedMul(5<<FRACBITS, player->mo->scale)
+			if (player->skin == 0 && 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])
@@ -7518,8 +7526,6 @@ boolean P_LookForEnemies(player_t *player)
 		if (an > ANGLE_90 && an < ANGLE_270)
 			continue; // behind back
 
-		player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, mo->x, mo->y);
-
 		if (!P_CheckSight(player->mo, mo))
 			continue; // out of sight
 
@@ -7530,6 +7536,7 @@ boolean P_LookForEnemies(player_t *player)
 	{
 		// Found a target monster
 		P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, closestmo));
+		player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, closestmo->x, closestmo->y);
 		return true;
 	}
 
@@ -8446,7 +8453,7 @@ static boolean P_SpectatorJoinGame(player_t *player)
 		else if (redscore > bluescore)
 			changeto = 2;
 		else
-			changeto = (P_Random() & 1) + 1;
+			changeto = (P_RandomFixed() & 1) + 1;
 
 		if (player->mo)
 		{
@@ -8697,7 +8704,7 @@ void P_PlayerThink(player_t *player)
 
 	// Add some extra randomization.
 	if (cmd->forwardmove)
-		P_Random();
+		P_RandomFixed();
 
 #ifdef PARANOIA
 	if (player->playerstate == PST_REBORN)
diff --git a/src/r_bsp.c b/src/r_bsp.c
index 52be9a0e340a334d89ffb27bcc0c36ed2e5d9083..b4e726892d3d651664e7d168f97c6e8455151559 100644
--- a/src/r_bsp.c
+++ b/src/r_bsp.c
@@ -462,26 +462,64 @@ static void R_AddLine(seg_t *line)
 
 	// 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)
+	if (frontsector->f_slope || frontsector->c_slope || backsector->f_slope || backsector->c_slope)
 	{
-		goto clipsolid;
-	}
+		fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends
+		fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends
+#define SLOPEPARAMS(slope, end1, end2, normalheight) \
+		if (slope) { \
+			end1 = P_GetZAt(slope, line->v1->x, line->v1->y); \
+			end2 = P_GetZAt(slope, line->v2->x, line->v2->y); \
+		} else \
+			end1 = end2 = normalheight;
+
+		SLOPEPARAMS(frontsector->f_slope, frontf1, frontf2, frontsector->floorheight)
+		SLOPEPARAMS(frontsector->c_slope, frontc1, frontc2, frontsector->ceilingheight)
+		SLOPEPARAMS( backsector->f_slope, backf1,  backf2,  backsector->floorheight)
+		SLOPEPARAMS( backsector->c_slope, backc1,  backc2,  backsector->ceilingheight)
+#undef SLOPEPARAMS
+		if ((backc1 <= frontf1 && backc2 <= frontf2)
+			|| (backf1 >= frontc1 && backf2 >= frontc2))
+		{
+			goto clipsolid;
+		}
 
-	// Check for automap fix. Store in doorclosed for r_segs.c
-	doorclosed = R_DoorClosed();
-	if (doorclosed)
-		goto clipsolid;
+		// Check for automap fix. Store in doorclosed for r_segs.c
+		doorclosed = (backc1 <= backf1 && backc2 <= backf2
+		&& ((backc1 >= frontc1 && backc2 >= frontc2) || curline->sidedef->toptexture)
+		&& ((backf1 <= frontf1 && backf2 >= frontf2) || curline->sidedef->bottomtexture)
+		&& (backsector->ceilingpic != skyflatnum || frontsector->ceilingpic != skyflatnum));
+
+		if (doorclosed)
+			goto clipsolid;
 
-	// Window.
-	if (backsector->ceilingheight != frontsector->ceilingheight
-		|| backsector->floorheight != frontsector->floorheight)
+		// Window.
+		if (backc1 != frontc1 || backc2 != frontc2
+			|| backf1 != frontf1 || backf2 != frontf2)
+		{
+			goto clippass;
+		}
+	}
+	else
+#endif
 	{
-		goto clippass;
+		if (backsector->ceilingheight <= frontsector->floorheight
+			|| backsector->floorheight >= frontsector->ceilingheight)
+		{
+			goto clipsolid;
+		}
+
+		// Check for automap fix. Store in doorclosed for r_segs.c
+		doorclosed = R_DoorClosed();
+		if (doorclosed)
+			goto clipsolid;
+
+		// Window.
+		if (backsector->ceilingheight != frontsector->ceilingheight
+			|| backsector->floorheight != frontsector->floorheight)
+		{
+			goto clippass;
+		}
 	}
 
 	// Reject empty lines used for triggers and special events.
@@ -966,7 +1004,7 @@ static void R_Subsector(size_t num)
 				|| (viewz > heightcheck && (rover->flags & FF_BOTHPLANES))))
 			{
 				light = R_GetPlaneLight(frontsector, planecenterz,
-					viewz < *rover->bottomheight);
+					viewz < heightcheck);
 
 				ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic,
 					*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs,
@@ -984,12 +1022,7 @@ static void R_Subsector(size_t num)
 					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 = heightcheck;
 				ffloor[numffloors].ffloor = rover;
 				numffloors++;
 			}
@@ -1014,7 +1047,7 @@ static void R_Subsector(size_t num)
 				&& ((viewz > heightcheck && !(rover->flags & FF_INVERTPLANES))
 				|| (viewz < heightcheck && (rover->flags & FF_BOTHPLANES))))
 			{
-				light = R_GetPlaneLight(frontsector, planecenterz, viewz < *rover->topheight);
+				light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck);
 
 				ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic,
 					*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle,
@@ -1032,12 +1065,7 @@ static void R_Subsector(size_t num)
 					frontsector->hasslope = true;
 #endif
 
-				ffloor[numffloors].height =
-#ifdef ESLOPE
-				*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) :
-#endif
-				*rover->topheight;
-
+				ffloor[numffloors].height = heightcheck;
 				ffloor[numffloors].ffloor = rover;
 				numffloors++;
 			}
diff --git a/src/r_draw.c b/src/r_draw.c
index 766e0428e09844b2f32d96ca00d257c3a4bc8f23..f7896b0228d73d30b405780e4b1c6d9b3a77ba7d 100644
--- a/src/r_draw.c
+++ b/src/r_draw.c
@@ -801,4 +801,6 @@ void R_DrawViewBorder(void)
 //                   INCLUDE 16bpp DRAWING CODE HERE
 // ==========================================================================
 
+#ifdef HIGHCOLOR
 #include "r_draw16.c"
+#endif
diff --git a/src/r_draw.h b/src/r_draw.h
index 0ece26487cde450c0fea2029d773d021a0e3408b..97b2b29532837a6b25b74df38f5a2d8ff2e3e93e 100644
--- a/src/r_draw.h
+++ b/src/r_draw.h
@@ -169,11 +169,13 @@ void R_DrawColumnShadowed_8(void);
 // 16bpp DRAWING CODE
 // ------------------
 
+#ifdef HIGHCOLOR
 void R_DrawColumn_16(void);
 void R_DrawWallColumn_16(void);
 void R_DrawTranslucentColumn_16(void);
 void R_DrawTranslatedColumn_16(void);
 void R_DrawSpan_16(void);
+#endif
 
 // =========================================================================
 #endif  // __R_DRAW__
diff --git a/src/r_main.c b/src/r_main.c
index 3b71b7f92b4834325d5de2ba40c8dbf52b16097d..304021f4d5dcd0da5f2e92cd79f27a2f081fd388 100644
--- a/src/r_main.c
+++ b/src/r_main.c
@@ -517,7 +517,9 @@ static void R_InitTextureMapping(void)
 	focallength = FixedDiv(centerxfrac,
 		FINETANGENT(FINEANGLES/4+/*cv_fov.value*/ FIELDOFVIEW/2));
 
+#ifdef ESLOPE
 	focallengthf = FIXED_TO_FLOAT(focallength);
+#endif
 
 	for (i = 0; i < FINEANGLES/2; i++)
 	{
@@ -971,14 +973,42 @@ void R_SkyboxFrame(player_t *player)
 		{
 			if (skyboxmo[1])
 			{
+				fixed_t x = 0, y = 0;
 				if (mh->skybox_scalex > 0)
-					viewx += (player->mo->x - skyboxmo[1]->x) / mh->skybox_scalex;
+					x = (player->mo->x - skyboxmo[1]->x) / mh->skybox_scalex;
 				else if (mh->skybox_scalex < 0)
-					viewx += (player->mo->x - skyboxmo[1]->x) * -mh->skybox_scalex;
+					x = (player->mo->x - skyboxmo[1]->x) * -mh->skybox_scalex;
 				if (mh->skybox_scaley > 0)
-					viewy += (player->mo->y - skyboxmo[1]->y) / mh->skybox_scaley;
+					y = (player->mo->y - skyboxmo[1]->y) / mh->skybox_scaley;
 				else if (mh->skybox_scaley < 0)
-					viewy += (player->mo->y - skyboxmo[1]->y) * -mh->skybox_scaley;
+					y = (player->mo->y - skyboxmo[1]->y) * -mh->skybox_scaley;
+
+				if (viewmobj->angle == 0)
+				{
+					viewx += x;
+					viewy += y;
+				}
+				else if (viewmobj->angle == ANGLE_90)
+				{
+					viewx -= y;
+					viewy += x;
+				}
+				else if (viewmobj->angle == ANGLE_180)
+				{
+					viewx -= x;
+					viewy -= y;
+				}
+				else if (viewmobj->angle == ANGLE_270)
+				{
+					viewx += y;
+					viewy -= x;
+				}
+				else
+				{
+					angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT;
+					viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y,  FINESINE(ang));
+					viewy += FixedMul(x,  FINESINE(ang)) + FixedMul(y,FINECOSINE(ang));
+				}
 			}
 			if (mh->skybox_scalez > 0)
 				viewz += player->viewz / mh->skybox_scalez;
@@ -1433,10 +1463,12 @@ void R_RegisterEngineStuff(void)
 	CV_RegisterVar(&cv_voodoocompatibility);
 	CV_RegisterVar(&cv_grfogcolor);
 	CV_RegisterVar(&cv_grsoftwarefog);
+#ifdef ALAM_LIGHTING
 	CV_RegisterVar(&cv_grstaticlighting);
 	CV_RegisterVar(&cv_grdynamiclighting);
 	CV_RegisterVar(&cv_grcoronas);
 	CV_RegisterVar(&cv_grcoronasize);
+#endif
 	CV_RegisterVar(&cv_grmd2);
 #endif
 
diff --git a/src/r_plane.c b/src/r_plane.c
index 417f0360a8856f3e3ed1381b29384c5983905f79..ac7dcb90e69efaae99682eed38a13e3448a02ba2 100644
--- a/src/r_plane.c
+++ b/src/r_plane.c
@@ -299,7 +299,7 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2)
 	}
 
 	length = FixedMul (distance,distscale[x1]);
-	angle = (currentplane->viewangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
+	angle = (currentplane->viewangle + currentplane->plangle + xtoviewangle[x1])>>ANGLETOFINESHIFT;
 	/// \note Wouldn't it be faster just to add viewx and viewy
 	// to the plane's x/yoffs anyway??
 
@@ -475,7 +475,8 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 			&& lightlevel == check->lightlevel
 			&& xoff == check->xoffs && yoff == check->yoffs
 			&& planecolormap == check->extra_colormap
-			&& !pfloor && !check->ffloor && check->viewz == viewz
+			&& !pfloor && !check->ffloor
+			&& check->viewx == viewx && check->viewy == viewy && check->viewz == viewz
 			&& check->viewangle == viewangle
 #ifdef ESLOPE
 			&& check->slope == slope
@@ -497,8 +498,10 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
 	check->yoffs = yoff;
 	check->extra_colormap = planecolormap;
 	check->ffloor = pfloor;
+	check->viewx = viewx;
+	check->viewy = viewy;
 	check->viewz = viewz;
-	check->viewangle = viewangle + plangle;
+	check->viewangle = viewangle;
 	check->plangle = plangle;
 #ifdef POLYOBJECTS_PLANES
 	check->polyobj = NULL;
@@ -567,6 +570,8 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop)
 		new_pl->yoffs = pl->yoffs;
 		new_pl->extra_colormap = pl->extra_colormap;
 		new_pl->ffloor = pl->ffloor;
+		new_pl->viewx = pl->viewx;
+		new_pl->viewy = pl->viewy;
 		new_pl->viewz = pl->viewz;
 		new_pl->viewangle = pl->viewangle;
 		new_pl->plangle = pl->plangle;
@@ -665,7 +670,6 @@ void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2)
 void R_DrawPlanes(void)
 {
 	visplane_t *pl;
-	angle_t skyviewangle = viewangle; // the flat angle itself can mess with viewangle, so do your own angle instead!
 	INT32 x;
 	INT32 angle;
 	INT32 i;
@@ -704,7 +708,7 @@ void R_DrawPlanes(void)
 
 					if (dc_yl <= dc_yh)
 					{
-						angle = (skyviewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
+						angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT;
 						dc_x = x;
 						dc_source =
 							R_GetColumn(skytexture,
@@ -857,13 +861,13 @@ void R_DrawSinglePlane(visplane_t *pl)
 #ifdef ESLOPE
 	if (!pl->slope) // Don't mess with angle on slopes! We'll handle this ourselves later
 #endif
-	if (viewangle != pl->viewangle)
+	if (viewangle != pl->viewangle+pl->plangle)
 	{
 		memset(cachedheight, 0, sizeof (cachedheight));
-		angle = (pl->viewangle-ANGLE_90)>>ANGLETOFINESHIFT;
+		angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT;
 		basexscale = FixedDiv(FINECOSINE(angle),centerxfrac);
 		baseyscale = -FixedDiv(FINESINE(angle),centerxfrac);
-		viewangle = pl->viewangle;
+		viewangle = pl->viewangle+pl->plangle;
 	}
 
 	currentplane = pl;
@@ -954,11 +958,11 @@ void R_DrawSinglePlane(visplane_t *pl)
 		xoffs *= fudge;
 		yoffs /= fudge;
 
-		vx = FIXED_TO_FLOAT(viewx+xoffs);
-		vy = FIXED_TO_FLOAT(viewy-yoffs);
-		vz = FIXED_TO_FLOAT(viewz);
+		vx = FIXED_TO_FLOAT(pl->viewx+xoffs);
+		vy = FIXED_TO_FLOAT(pl->viewy-yoffs);
+		vz = FIXED_TO_FLOAT(pl->viewz);
 
-		temp = P_GetZAt(pl->slope, viewx, viewy);
+		temp = P_GetZAt(pl->slope, pl->viewx, pl->viewy);
 		zeroheight = FIXED_TO_FLOAT(temp);
 
 #define ANG2RAD(angle) ((float)((angle)*M_PI)/ANGLE_180)
@@ -966,14 +970,14 @@ void R_DrawSinglePlane(visplane_t *pl)
 		// 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);
+		ang = ANG2RAD(ANGLE_270 - pl->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);
+		ang = ANG2RAD(ANGLE_180 - (pl->viewangle + pl->plangle));
 		m.x = cos(ang);
 		m.z = sin(ang);
 
@@ -982,9 +986,9 @@ void R_DrawSinglePlane(visplane_t *pl)
 		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)));
+		temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(sin(ang)), pl->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)));
+		temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang)));
 		n.y = FIXED_TO_FLOAT(temp) - zeroheight;
 
 		m.x /= fudge;
@@ -1040,6 +1044,14 @@ void R_DrawSinglePlane(visplane_t *pl)
 
 	stop = pl->maxx + 1;
 
+	if (viewx != pl->viewx || viewy != pl->viewy)
+	{
+		viewx = pl->viewx;
+		viewy = pl->viewy;
+	}
+	if (viewz != pl->viewz)
+		viewz = pl->viewz;
+
 	for (x = pl->minx; x <= stop; x++)
 	{
 		R_MakeSpans(x, pl->top[x-1], pl->bottom[x-1],
diff --git a/src/r_plane.h b/src/r_plane.h
index 239723ed1d6316c33efa6a44ab97c719df330ea8..562c6a9ae6064b3de53aca147ab36f18a859f2c1 100644
--- a/src/r_plane.h
+++ b/src/r_plane.h
@@ -27,7 +27,8 @@ typedef struct visplane_s
 {
 	struct visplane_s *next;
 
-	fixed_t height, viewz;
+	fixed_t height;
+	fixed_t viewx, viewy, viewz;
 	angle_t viewangle;
 	angle_t plangle;
 	INT32 picnum;
diff --git a/src/r_segs.c b/src/r_segs.c
index 95227ba6a28f72d30a4863c0122d114a5be5641c..9b1533daac612a19078fff4d149465b2be6d5d43 100644
--- a/src/r_segs.c
+++ b/src/r_segs.c
@@ -288,6 +288,10 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 	line_t *ldef;
 	sector_t *front, *back;
 	INT32 times, repeats;
+	INT64 overflow_test;
+#ifdef ESLOPE
+	INT32 range;
+#endif
 
 	// Calculate light table.
 	// Use different light tables
@@ -334,6 +338,9 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 		colfunc = fuzzcolfunc;
 	}
 
+#ifdef ESLOPE
+	range = max(ds->x2-ds->x1, 1);
+#endif
 	rw_scalestep = ds->scalestep;
 	spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
 
@@ -360,10 +367,30 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 
 		for (i = 0; i < dc_numlights; i++)
 		{
+#ifdef ESLOPE
+			fixed_t leftheight, rightheight;
+#endif
 			light = &frontsector->lightlist[i];
 			rlight = &dc_lightlist[i];
+#ifdef ESLOPE
+			if (light->slope) {
+				leftheight = P_GetZAt(light->slope, ds->leftpos.x, ds->leftpos.y);
+				rightheight = P_GetZAt(light->slope, ds->rightpos.x, ds->rightpos.y);
+			} else
+				leftheight = rightheight = light->height;
+
+			leftheight -= viewz;
+			rightheight -= viewz;
+
+			rlight->height = (centeryfrac) - FixedMul(leftheight, ds->scale1);
+			rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2);
+			rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
+			//if (x1 > ds->x1)
+				//rlight->height -= (x1 - ds->x1)*rlight->heightstep;
+#else
 			rlight->height = (centeryfrac) - FixedMul((light->height - viewz), spryscale);
 			rlight->heightstep = -FixedMul(rw_scalestep, (light->height - viewz));
+#endif
 			rlight->lightlevel = *light->lightlevel;
 			rlight->extra_colormap = light->extra_colormap;
 			rlight->flags = light->flags;
@@ -459,7 +486,6 @@ 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)
 		{
@@ -497,6 +523,16 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
 			// calculate lighting
 			if (maskedtexturecol[dc_x] != INT16_MAX)
 			{
+				// Check for overflows first
+				overflow_test = (INT64)centeryfrac - (((INT64)dc_texturemid*spryscale)>>FRACBITS);
+				if (overflow_test < 0) overflow_test = -overflow_test;
+				if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL)
+				{
+					// Eh, no, go away, don't waste our time
+					spryscale += rw_scalestep;
+					continue;
+				}
+
 				if (dc_numlights)
 				{
 					lighttable_t **xwalllights;
@@ -673,7 +709,12 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	fixed_t         offsetvalue = 0;
 	lightlist_t     *light;
 	r_lightlist_t   *rlight;
+#ifdef ESLOPE
+	INT32           range;
+#endif
+#ifndef ESLOPE
 	fixed_t         lheight;
+#endif
 	line_t          *newline = NULL;
 #ifdef ESLOPE
 	// Render FOF sides kinda like normal sides, with the frac and step and everything
@@ -735,6 +776,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	else if (pfloor->flags & FF_FOG)
 		colfunc = R_DrawFogColumn_8;
 
+#ifdef ESLOPE
+	range = max(ds->x2-ds->x1, 1);
+#endif
 	//SoM: Moved these up here so they are available for my lightlist calculations
 	rw_scalestep = ds->scalestep;
 	spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep;
@@ -751,9 +795,49 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 
 		for (i = p = 0; i < dc_numlights; i++)
 		{
+#ifdef ESLOPE
+			fixed_t leftheight, rightheight;
+			fixed_t pfloorleft, pfloorright;
+#endif
 			light = &frontsector->lightlist[i];
 			rlight = &dc_lightlist[p];
+#ifdef ESLOPE
+			if (light->slope) {
+				leftheight = P_GetZAt(light->slope, ds->leftpos.x, ds->leftpos.y);
+				rightheight = P_GetZAt(light->slope, ds->rightpos.x, ds->rightpos.y);
+			} else
+				leftheight = rightheight = light->height;
+
+			if (*pfloor->b_slope) {
+				pfloorleft = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y);
+				pfloorright = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y);
+			} else
+				pfloorleft = pfloorright = *pfloor->bottomheight;
+
+			if (leftheight < pfloorleft && rightheight < pfloorright)
+				continue;
+
+			if (*pfloor->t_slope) {
+				pfloorleft = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y);
+				pfloorright = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y);
+			} else
+				pfloorleft = pfloorright = *pfloor->topheight;
 
+			if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights)
+			{
+				lightlist_t *nextlight = &frontsector->lightlist[i+1];
+				if (nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height > pfloorleft
+				 && nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height > pfloorright)
+					continue;
+			}
+
+			leftheight -= viewz;
+			rightheight -= viewz;
+			rlight->height = (centeryfrac) - FixedMul(leftheight, ds->scale1);
+			rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2);
+			rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
+			rlight->height -= rlight->heightstep;
+#else
 			if (light->height < *pfloor->bottomheight)
 				continue;
 
@@ -763,13 +847,29 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 			lheight = light->height;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : light->height;
 			rlight->heightstep = -FixedMul (rw_scalestep, (lheight - viewz));
 			rlight->height = (centeryfrac) - FixedMul((lheight - viewz), spryscale) - rlight->heightstep;
+#endif
 			rlight->flags = light->flags;
-
 			if (light->flags & FF_CUTLEVEL)
 			{
+#ifdef ESLOPE
+				if (*light->caster->b_slope) {
+					leftheight = P_GetZAt(*light->caster->b_slope, ds->leftpos.x, ds->leftpos.y);
+					rightheight = P_GetZAt(*light->caster->b_slope, ds->rightpos.x, ds->rightpos.y);
+				} else
+					leftheight = rightheight = *light->caster->bottomheight;
+
+				leftheight -= viewz;
+				rightheight -= viewz;
+
+				rlight->botheight = (centeryfrac) - FixedMul(leftheight, ds->scale1);
+				rlight->botheightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2);
+				rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range);
+				rlight->botheight -= rlight->botheightstep;
+#else
 				lheight = *light->caster->bottomheight;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : *light->caster->bottomheight;
 				rlight->botheightstep = -FixedMul (rw_scalestep, (lheight - viewz));
 				rlight->botheight = (centeryfrac) - FixedMul((lheight - viewz), spryscale) - rlight->botheightstep;
+#endif
 			}
 
 			rlight->lightlevel = *light->lightlevel;
@@ -857,24 +957,46 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 	// Set heights according to plane, or slope, whichever
 	{
 		fixed_t left_top, right_top, left_bottom, right_bottom;
+		INT64 overflow_test;
 
-		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;
+		if (*pfloor->t_slope)
+		{
+			left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz;
+			right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
+		}
+		else
+			left_top = right_top = *pfloor->topheight - viewz;
 
-		left_top -= viewz;
-		right_top -= viewz;
-		left_bottom -= viewz;
-		right_bottom -= viewz;
+		if (*pfloor->b_slope)
+		{
+			left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz;
+			right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz;
+		}
+		else
+			left_bottom = right_bottom = *pfloor->bottomheight - viewz;
+
+		// overflow tests
+		// if any of these fail, abandon. likely we're too high up to see anything anyway
+		overflow_test = (INT64)centeryfrac - (((INT64)left_top*ds->scale1)>>FRACBITS);
+		if (overflow_test < 0) overflow_test = -overflow_test;
+		if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return;
+		overflow_test = (INT64)centeryfrac - (((INT64)left_bottom*ds->scale1)>>FRACBITS);
+		if (overflow_test < 0) overflow_test = -overflow_test;
+		if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return;
+		overflow_test = (INT64)centeryfrac - (((INT64)right_top*ds->scale2)>>FRACBITS);
+		if (overflow_test < 0) overflow_test = -overflow_test;
+		if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return;
+		overflow_test = (INT64)centeryfrac - (((INT64)right_bottom*ds->scale2)>>FRACBITS);
+		if (overflow_test < 0) overflow_test = -overflow_test;
+		if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return;
 
 		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_step = (top_step-top_frac)/(range);
+		bottom_step = (bottom_step-bottom_frac)/(range);
 
 		top_frac += top_step * (x1 - ds->x1);
 		bottom_frac += bottom_step * (x1 - ds->x1);
@@ -1043,19 +1165,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
 			if (pfloor->flags & FF_FOG && pfloor->master->frontsector->extra_colormap)
 				dc_colormap = pfloor->master->frontsector->extra_colormap->colormap + (dc_colormap - colormaps);
 
-			//Handle over/underflows before they happen.  This fixes the textures part of the FOF rendering bug.
-			//...for the most part, anyway.
-			if (((signed)dc_texturemid > 0 && (spryscale>>FRACBITS > INT32_MAX / (signed)dc_texturemid))
-			 || ((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;
@@ -1112,7 +1221,9 @@ static void R_RenderSegLoop (void)
 
 	INT32     mid;
 	fixed_t texturecolumn = 0;
+#ifdef ESLOPE
 	fixed_t oldtexturecolumn = -1;
+#endif
 	INT32     top;
 	INT32     bottom;
 	INT32     i;
@@ -1468,22 +1579,26 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	fixed_t       hyp;
 	fixed_t       sineval;
 	angle_t       distangle, offsetangle;
-	//fixed_t       vtop;
+#ifndef ESLOPE
+	fixed_t       vtop;
+#endif
 	INT32           lightnum;
 	INT32           i, p;
 	lightlist_t   *light;
 	r_lightlist_t *rlight;
+	INT32 range;
 #ifdef ESLOPE
 	vertex_t segleft, segright;
 	fixed_t ceilingfrontslide, floorfrontslide, ceilingbackslide, floorbackslide;
 #endif
 	static size_t maxdrawsegs = 0;
 
+#ifdef ESLOPE
 	maskedtextureheight = NULL;
-
 	//initialize segleft and segright
 	memset(&segleft, 0x00, sizeof(segleft));
 	memset(&segright, 0x00, sizeof(segright));
+#endif
 
 	if (ds_p == drawsegs+maxdrawsegs)
 	{
@@ -1556,7 +1671,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 	if (stop > start)
 	{
 		ds_p->scale2 = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[stop]);
-		ds_p->scalestep = rw_scalestep = (ds_p->scale2 - rw_scale) / (stop-start);
+		range = stop-start;
 	}
 	else
 	{
@@ -1577,8 +1692,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		}
 #endif
 		ds_p->scale2 = ds_p->scale1;
+		range = 1;
 	}
 
+	ds_p->scalestep = rw_scalestep = (ds_p->scale2 - rw_scale) / (range);
+
 	// calculate texture boundaries
 	//  and decide if floor / ceiling marks are needed
 #ifdef ESLOPE
@@ -1785,9 +1903,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			&& backsector->ceilingpic == skyflatnum)
 		{
 #ifdef ESLOPE
-			worldtopslope = worldhighslope =
+			worldtopslope = max(worldtopslope, worldhighslope);
+			worldhighslope = worldtopslope;
 #endif
-			worldtop = worldhigh;
+			worldtop = max(worldtop, worldhigh);
+			worldhigh = worldtop;
 		}
 
 		ds_p->sprtopclip = ds_p->sprbottomclip = NULL;
@@ -1801,7 +1921,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		{
 			ds_p->silhouette = SIL_BOTTOM;
 #ifdef ESLOPE
-			ds_p->bsilheight = (frontsector->f_slope ? INT32_MAX : frontsector->floorheight);
+			if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz)
+				ds_p->bsilheight = INT32_MAX;
+			else
+				ds_p->bsilheight = (frontsector->f_slope ? INT32_MAX : frontsector->floorheight);
 #else
 			ds_p->bsilheight = frontsector->floorheight;
 #endif
@@ -1825,7 +1948,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		{
 			ds_p->silhouette |= SIL_TOP;
 #ifdef ESLOPE
-			ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight);
+			if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz)
+				ds_p->tsilheight = INT32_MIN;
+			else
+				ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight);
 #else
 			ds_p->tsilheight = frontsector->ceilingheight;
 #endif
@@ -1863,21 +1989,25 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			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.
 		{
+#ifdef ESLOPE
+			if (doorclosed || (worldhigh <= worldbottom && worldhighslope <= worldbottomslope))
+#else
 			if (doorclosed || backsector->ceilingheight <= frontsector->floorheight)
+#endif
 			{
 				ds_p->sprbottomclip = negonearray;
 				ds_p->bsilheight = INT32_MAX;
 				ds_p->silhouette |= SIL_BOTTOM;
 			}
+#ifdef ESLOPE
+			if (doorclosed || (worldlow >= worldtop && worldlowslope >= worldtopslope))
+#else
 			if (doorclosed || backsector->floorheight >= frontsector->ceilingheight)
+#endif
 			{                   // killough 1/17/98, 2/8/98
 				ds_p->sprtopclip = screenheightarray;
 				ds_p->tsilheight = INT32_MIN;
@@ -1937,8 +2067,13 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 			markceiling = false;
 		}
 
+#ifdef ESLOPE
+		if ((worldhigh <= worldbottom && worldhighslope <= worldbottomslope) ||
+		    (worldlow >= worldtop && worldlowslope >= worldtopslope))
+#else
 		if (backsector->ceilingheight <= frontsector->floorheight ||
 		    backsector->floorheight >= frontsector->ceilingheight)
+#endif
 		{
 			// closed door
 			markceiling = markfloor = true;
@@ -2121,8 +2256,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 					for (r2 = frontsector->ffloors; r2; r2 = r2->next)
 					{
-						if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)
-						    || *r2->topheight < lowcut || *r2->bottomheight > highcut) ///TODO: make these account for slopes -Red
+						if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
 							continue;
 
 						if (r2->norender == leveltime)
@@ -2154,9 +2288,13 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 						} else
 							low2 = lowslope2 = *r2->bottomheight;
 
-						if ((high1 > high2 && highslope1 > highslope2) || (low1 < low2 && lowslope1 < lowslope2))
+						if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope))
+							continue;
+						if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2))
 							continue;
 #else
+						if (*r2->topheight < lowcut || *r2->bottomheight > highcut)
+							continue;
 						if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight)
 							continue;
 #endif
@@ -2201,8 +2339,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 					for (r2 = backsector->ffloors; r2; r2 = r2->next)
 					{
-						if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES)
-						    || *r2->topheight < lowcut || *r2->bottomheight > highcut) ///TODO: make these account for slopes -Red
+						if (!(r2->flags & FF_EXISTS) || !(r2->flags & FF_RENDERSIDES))
 							continue;
 
 						if (r2->norender == leveltime)
@@ -2234,9 +2371,13 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 						} else
 							low2 = lowslope2 = *r2->bottomheight;
 
-						if ((high1 > high2 && highslope1 > highslope2) || (low1 < low2 && lowslope1 < lowslope2))
+						if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope))
+							continue;
+						if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2))
 							continue;
 #else
+						if (*r2->topheight < lowcut || *r2->bottomheight > highcut)
+							continue;
 						if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight)
 							continue;
 #endif
@@ -2438,11 +2579,11 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 #ifdef ESLOPE
 	if (frontsector->c_slope) {
 		fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldtopslope, ds_p->scale2);
-		topstep = (topfracend-topfrac)/(stop-start+1);
+		topstep = (topfracend-topfrac)/(range);
 	}
 	if (frontsector->f_slope) {
 		fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldbottomslope, ds_p->scale2);
-		bottomstep = (bottomfracend-bottomfrac)/(stop-start+1);
+		bottomstep = (bottomfracend-bottomfrac)/(range);
 	}
 #endif
 
@@ -2503,7 +2644,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 #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);
+			rlight->heightstep = (rlight->heightstep-rlight->height)/(range);
 #else
 			rlight->height = (centeryfrac>>4) - FixedMul((light->height - viewz) >> 4, rw_scale);
 			rlight->heightstep = -FixedMul (rw_scalestep, (light->height - viewz) >> 4);
@@ -2530,7 +2671,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 
 				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);
+				rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range);
 
 #else
 				rlight->botheight = (centeryfrac >> 4) - FixedMul((*light->caster->bottomheight - viewz) >> 4, rw_scale);
@@ -2559,7 +2700,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 #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);
+			ffloor[i].f_step = ((centeryfrac>>4) - FixedMul(ffloor[i].f_pos_slope, ds_p->scale2) - ffloor[i].f_frac)/(range);
 #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);
@@ -2576,11 +2717,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		worldlowslope >>= 4;
 #endif
 
-		if (worldhigh < worldtop
-#ifdef ESLOPE
-			|| worldhighslope <= worldtopslope
-#endif
-			)
+		if (toptexture)
 		{
 			pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale);
 			pixhighstep = -FixedMul (rw_scalestep,worldhigh);
@@ -2588,23 +2725,19 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 #ifdef ESLOPE
 			if (backsector->c_slope) {
 				fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldhighslope, ds_p->scale2);
-				pixhighstep = (topfracend-pixhigh)/(stop-start+1);
+				pixhighstep = (topfracend-pixhigh)/(range);
 			}
 #endif
 		}
 
-		if (worldlow > worldbottom
-#ifdef ESLOPE
-			|| worldlowslope >= worldbottomslope
-#endif
-			)
+		if (bottomtexture)
 		{
 			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);
+				pixlowstep = (bottomfracend-pixlow)/(range);
 			}
 #endif
 		}
@@ -2612,7 +2745,7 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 		{
 			ffloor_t * rover;
 #ifdef ESLOPE
-			fixed_t rovertest;
+			fixed_t roverleft, roverright;
 			fixed_t planevistest;
 #endif
 			i = 0;
@@ -2631,44 +2764,46 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					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;
+					roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz;
+					roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz;
 					planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight);
 
-					if (rovertest>>4 <= worldhigh &&
-					    rovertest>>4 >= worldlow &&
+					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
+					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
 					    ((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 = roverleft;
+						ffloor[i].b_pos_slope = roverright;
 						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);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
 						i++;
 					}
 
 					if (i >= MAXFFLOORS)
 						break;
 
-					rovertest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, backsector->soundorg.x, backsector->soundorg.y) : *rover->topheight) - viewz;
+					roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz;
+					roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz;
 					planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight);
 
-					if (rovertest>>4 <= worldhigh &&
-					    rovertest>>4 >= worldlow &&
+					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
+					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
 					    ((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 = roverleft;
+						ffloor[i].b_pos_slope = roverright;
 						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);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
 						i++;
 					}
 #else
@@ -2716,44 +2851,46 @@ void R_StoreWallRange(INT32 start, INT32 stop)
 					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;
+					roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz;
+					roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz;
 					planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight);
 
-					if (rovertest>>4 <= worldtop &&
-					    rovertest>>4 >= worldbottom &&
+					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
+					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
 					    ((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 = roverleft;
+						ffloor[i].b_pos_slope = roverright;
 						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);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
 						i++;
 					}
 
 					if (i >= MAXFFLOORS)
 						break;
 
-					rovertest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, frontsector->soundorg.x, frontsector->soundorg.y) : *rover->topheight) - viewz;
+					roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz;
+					roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz;
 					planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight);
 
-					if (rovertest>>4 <= worldtop &&
-					    rovertest>>4 >= worldbottom &&
+					if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) &&
+					    (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) &&
 					    ((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 = roverleft;
+						ffloor[i].b_pos_slope = roverright;
 						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);
+						ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range);
 						i++;
 					}
 #else
diff --git a/src/r_things.c b/src/r_things.c
index 2ec2f6ead19e20bf784490973bc53f5b6844c1e6..c53f8914cfa94a9581b69ff80dee61ff6ce68fbc 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -744,10 +744,16 @@ static void R_DrawVisSprite(vissprite_t *vis)
 	patch_t *patch = W_CacheLumpNum(vis->patch, PU_CACHE);
 	fixed_t this_scale = vis->mobj->scale;
 	INT32 x1, x2;
+	INT64 overflow_test;
 
 	if (!patch)
 		return;
 
+	// Check for overflow
+	overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*vis->scale)>>FRACBITS);
+	if (overflow_test < 0) overflow_test = -overflow_test;
+	if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // fixed point mult would overflow
+
 	colfunc = basecolfunc; // hack: this isn't resetting properly somewhere.
 	dc_colormap = vis->colormap;
 	if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
@@ -1239,15 +1245,6 @@ static void R_ProjectSprite(mobj_t *thing)
 			return;
 	}
 
-	// quick check for possible overflows
-	// if either of these triggers then there's a possibility that drawing is unsafe
-	if (M_HighestBit(abs(gzt - viewz)) + M_HighestBit(abs(yscale)) > 47 // 31 bits + 16 from the division by FRACUNIT
-	 || M_HighestBit(abs(gz  - viewz)) + M_HighestBit(abs(yscale)) > 47)
-	{
-		CONS_Debug(DBG_RENDER, "Suspected overflow in ProjectSprite (sprite %s), ignoring\n", sprnames[thing->sprite]);
-		return;
-	}
-
 	// store information in a vissprite
 	vis = R_NewVisSprite();
 	vis->heightsec = heightsec; //SoM: 3/17/2000
@@ -1458,14 +1455,6 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
 			return;
 	}
 
-	// quick check for possible overflows
-	// if either of these triggers then there's a possibility that drawing is unsafe
-	if (M_HighestBit(abs(gzt - viewz)) + M_HighestBit(abs(yscale)) > 47) // 31 bits + 16 from the division by FRACUNIT
-	{
-		CONS_Debug(DBG_RENDER, "Suspected overflow in ProjectPrecipitationSprite (sprite %s), ignoring\n", sprnames[thing->sprite]);
-		return;
-	}
-
 	// store information in a vissprite
 	vis = R_NewVisSprite();
 	vis->scale = yscale; //<<detailshift;
diff --git a/src/st_stuff.c b/src/st_stuff.c
index 9a4df8a07b9639a127c5bb79f2e2b33e5ba29c4c..f690ca6588de41b086c4f219d8d49bbb1e47ff82 100644
--- a/src/st_stuff.c
+++ b/src/st_stuff.c
@@ -592,9 +592,13 @@ static void ST_drawDebugInfo(void)
 
 	if (cv_debug & DBG_RANDOMIZER) // randomizer testing
 	{
+		fixed_t peekres = P_RandomPeek();
+		peekres *= 10000;     // Change from fixed point
+		peekres >>= FRACBITS; // to displayable decimal
+
 		V_DrawRightAlignedString(320, height - 16, V_MONOSPACE, va("Init: %08x", P_GetInitSeed()));
 		V_DrawRightAlignedString(320, height - 8,  V_MONOSPACE, va("Seed: %08x", P_GetRandSeed()));
-		V_DrawRightAlignedString(320, height,      V_MONOSPACE, va("==  : %8d", P_RandomPeek()));
+		V_DrawRightAlignedString(320, height,      V_MONOSPACE, va("==  :    .%04d", peekres));
 
 		height -= 32;
 	}
diff --git a/src/v_video.c b/src/v_video.c
index b9bdb271fbeb9cb2ee064d7f97bbad6c09bce3c9..2d02139ff440d7a413f6146ac49563f3944da87a 100644
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -71,10 +71,12 @@ consvar_t cv_grgammagreen = {"gr_gammagreen", "127", CV_SAVE|CV_CALL, grgamma_co
                              CV_Gammaxxx_ONChange, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_grgammablue = {"gr_gammablue", "127", CV_SAVE|CV_CALL, grgamma_cons_t,
                             CV_Gammaxxx_ONChange, 0, NULL, NULL, 0, 0, NULL};
+#ifdef ALAM_LIGHTING
 consvar_t cv_grdynamiclighting = {"gr_dynamiclighting", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_grstaticlighting  = {"gr_staticlighting", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_grcoronas = {"gr_coronas", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
 consvar_t cv_grcoronasize = {"gr_coronasize", "1", CV_SAVE| CV_FLOAT, 0, NULL, 0, NULL, NULL, 0, 0, NULL};
+#endif
 
 static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}};
 // console variables in development
@@ -1989,7 +1991,7 @@ Unoptimized version
 
 			for (y = 0; y < height; y++)
 			{
-				if (M_Random() < 32)
+				if (M_RandomChance(FRACUNIT/8)) // 12.5%
 					heatshifter[y] = true;
 			}