diff --git a/src/p_map.c b/src/p_map.c
index e1f204a8c30cd3ad968f9856f735c29e70fc10e6..b4fecd6148464d0ff759c43db2496baedd6eaeea 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -971,15 +971,15 @@ static boolean PIT_CheckThing(mobj_t *thing)
 
 		if (thing->z + thing->height > bottomz // above bottom
 		&&  thing->z < topz) // below top
-		{ // don't check angle, the player was clearly in the way in this case
+		// don't check angle, the player was clearly in the way in this case
 			P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE);
-		}
 	}
 	else if (thing->type == MT_WALLSPIKE && thing->flags & MF_SOLID && tmthing->player)
 	{
 		fixed_t bottomz, topz;
 		bottomz = thing->z;
 		topz = thing->z + thing->height;
+
 		if (thing->eflags & MFE_VERTICALFLIP)
 			bottomz -= FixedMul(FRACUNIT, thing->scale);
 		else
@@ -1151,12 +1151,14 @@ static boolean PIT_CheckThing(mobj_t *thing)
 		}
 	}
 
-	if (thing->flags & MF_SPRING && (tmthing->player || tmthing->flags & MF_PUSHABLE))
+	if (!(tmthing->player) && (thing->player))
+		; // no solid thing should ever be able to step up onto a player
+	else if (thing->flags & MF_SPRING && (tmthing->player || tmthing->flags & MF_PUSHABLE))
 	{
 		if (iwassprung) // this spring caused you to gain MFE_SPRUNG just now...
 			return false; // "cancel" P_TryMove via blocking so you keep your current position
 	}
-	else if (tmthing->flags & MF_SPRING && (thing->player || thing->flags & MF_PUSHABLE))
+	else if (tmthing->flags & MF_SPRING && (thing->flags & MF_PUSHABLE))
 		; // Fix a few nasty spring-jumping bugs that happen sometimes.
 	// Monitors are not treated as solid to players who are jumping, spinning or gliding,
 	// unless it's a CTF team monitor and you're on the wrong team
@@ -3092,6 +3094,7 @@ void P_SlideMove(mobj_t *mo)
 	fixed_t leadx, leady, trailx, traily, newx, newy;
 	INT16 hitcount = 0;
 	boolean success = false;
+	boolean papercol = false;
 
 	if (tmhitthing && mo->z + mo->height > tmhitthing->z && mo->z < tmhitthing->z + tmhitthing->height)
 	{
@@ -3099,6 +3102,80 @@ void P_SlideMove(mobj_t *mo)
 		if (tmhitthing->flags & MF_PUSHABLE)
 			return;
 
+		if (tmhitthing->flags & MF_PAPERCOLLISION)
+		{
+			fixed_t cosradius, sinradius;
+			vertex_t v1, v2; // fake vertexes
+			line_t junk; // fake linedef - does this need to be static? toast does not know
+
+			fixed_t num, den;
+
+			// trace along the three leading corners
+			if (mo->momx > 0)
+			{
+				leadx = mo->x + mo->radius;
+				trailx = mo->x - mo->radius;
+			}
+			else
+			{
+				leadx = mo->x - mo->radius;
+				trailx = mo->x + mo->radius;
+			}
+
+			if (mo->momy > 0)
+			{
+				leady = mo->y + mo->radius;
+				traily = mo->y - mo->radius;
+			}
+			else
+			{
+				leady = mo->y - mo->radius;
+				traily = mo->y + mo->radius;
+			}
+
+			papercol = true;
+			slidemo = mo;
+			bestslideline = &junk;
+
+			cosradius = FixedMul(tmhitthing->radius, FINECOSINE(tmhitthing->angle>>ANGLETOFINESHIFT));
+			sinradius = FixedMul(tmhitthing->radius, FINESINE(tmhitthing->angle>>ANGLETOFINESHIFT));
+
+			v1.x = tmhitthing->x - cosradius;
+			v1.y = tmhitthing->y - sinradius;
+			v2.x = tmhitthing->x + cosradius;
+			v2.y = tmhitthing->y + sinradius;
+
+			junk.v1 = &v1;
+			junk.v2 = &v2;
+			junk.dx = 2*cosradius; // v2.x - v1.x;
+			junk.dy = 2*sinradius; // v2.y - v1.y;
+
+			junk.slopetype = !cosradius ? ST_VERTICAL : !sinradius ? ST_HORIZONTAL :
+			((sinradius > 0) == (cosradius > 0)) ? ST_POSITIVE : ST_NEGATIVE;
+
+			bestslidefrac = FRACUNIT+1;
+
+			den = FixedMul(junk.dy>>8, mo->momx) - FixedMul(junk.dx>>8, mo->momy);
+
+			if (!den)
+				bestslidefrac = 0;
+			else
+			{
+				fixed_t frac;
+#define P_PaperTraverse(startx, starty) \
+				num = FixedMul((v1.x - leadx)>>8, junk.dy) + FixedMul((leady - v1.y)>>8, junk.dx); \
+				frac = FixedDiv(num, den); \
+				if (frac < bestslidefrac) \
+					bestslidefrac = frac
+				P_PaperTraverse(leadx, leady);
+				P_PaperTraverse(trailx, leady);
+				P_PaperTraverse(leadx, traily);
+#undef dowork
+			}
+
+			goto papercollision;
+		}
+
 		// Thankfully box collisions are a lot simpler than arbitrary lines. There's only four possible cases.
 		if (mo->y + mo->radius <= tmhitthing->y - tmhitthing->radius)
 		{
@@ -3129,7 +3206,7 @@ void P_SlideMove(mobj_t *mo)
 	bestslideline = NULL;
 
 retry:
-	if (++hitcount == 3)
+	if ((++hitcount == 3) || papercol)
 		goto stairstep; // don't loop forever
 
 	// trace along the three leading corners
@@ -3171,6 +3248,7 @@ retry:
 		return;
 	}
 
+papercollision:
 	// move up to the wall
 	if (bestslidefrac == FRACUNIT+1)
 	{
diff --git a/src/p_mobj.c b/src/p_mobj.c
index ddb36afa5c2ec0ddad26f7f49848db47d8450b23..1bb6a2f0111ea9fba734821ca61b70d06ca51c7b 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -7383,7 +7383,7 @@ void P_MobjThinker(mobj_t *mobj)
 			if (mobj->angle != mobj->target->angle + ANGLE_90) // reposition if not the correct angle
 			{
 				mobj_t *target = mobj->target; // shortcut
-				const fixed_t baseradius = target->radius - (target->scale/4); //FixedMul(FRACUNIT/4, target->scale);
+				const fixed_t baseradius = target->radius - (target->scale/2); //FixedMul(FRACUNIT/2, target->scale);
 				P_UnsetThingPosition(mobj);
 				mobj->x = target->x - P_ReturnThrustX(target, target->angle, baseradius);
 				mobj->y = target->y - P_ReturnThrustY(target, target->angle, baseradius);
@@ -10148,7 +10148,7 @@ ML_NOCLIMB : Direction not controllable
 		// spawn base
 		{
 			const angle_t mobjangle = FixedAngle(mthing->angle*FRACUNIT); // the mobj's own angle hasn't been set quite yet so...
-			const fixed_t baseradius = mobj->radius - (mobj->scale/4); //FixedMul(FRACUNIT/4, mobj->scale);
+			const fixed_t baseradius = mobj->radius - (mobj->scale/2); //FixedMul(FRACUNIT/2, mobj->scale);
 			mobj_t *base = P_SpawnMobj(
 					mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius),
 					mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius),
diff --git a/src/p_polyobj.c b/src/p_polyobj.c
index 7776ab19a601fd807278ad40dd22c8e8d8a607ac..fd3237c9da8f71f53686270f6ff7ee5daa9fb465 100644
--- a/src/p_polyobj.c
+++ b/src/p_polyobj.c
@@ -1237,7 +1237,7 @@ static void Polyobj_rotateLine(line_t *ld)
 
 	// determine slopetype
 	ld->slopetype = !ld->dx ? ST_VERTICAL : !ld->dy ? ST_HORIZONTAL :
-			FixedDiv(ld->dy, ld->dx) > 0 ? ST_POSITIVE : ST_NEGATIVE;
+			((ld->dy > 0) == (ld->dx > 0)) ? ST_POSITIVE : ST_NEGATIVE;
 
 	// update bounding box
 	if (v1->x < v2->x)
diff --git a/src/p_setup.c b/src/p_setup.c
index 4f11c10d06e243098fa71f7585c9a15f8cffb4cb..217f087cd77db2918c4ee77be3afd5da421636c7 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1212,7 +1212,7 @@ static void P_LoadLineDefs(lumpnum_t lumpnum)
 			ld->slopetype = ST_VERTICAL;
 		else if (!ld->dy)
 			ld->slopetype = ST_HORIZONTAL;
-		else if (FixedDiv(ld->dy, ld->dx) > 0)
+		else if ((ld->dy > 0) == (ld->dx > 0))
 			ld->slopetype = ST_POSITIVE;
 		else
 			ld->slopetype = ST_NEGATIVE;
diff --git a/src/p_user.c b/src/p_user.c
index 9ae79e5e2bae81013df66ed480e6c9355ceb5b7e..58593eca1d33975afdcdca3194e5f0c30848fa18 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -821,7 +821,10 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
 
 		if (inflictor)
 		{
-			ang = R_PointToAngle2(inflictor->x-inflictor->momx, inflictor->y - inflictor->momy, player->mo->x - player->mo->momx, player->mo->y - player->mo->momy);
+			if (inflictor->type == MT_WALLSPIKE)
+				ang = inflictor->angle;
+			else
+				ang = R_PointToAngle2(inflictor->x-inflictor->momx, inflictor->y - inflictor->momy, player->mo->x - player->mo->momx, player->mo->y - player->mo->momy);
 
 			// explosion and rail rings send you farther back, making it more difficult
 			// to recover