diff --git a/src/r_things.c b/src/r_things.c
index 174ada10ae080455292e53c67df653a41b1fd325..628239957f4e3877f231e5d28f399f5f9c3ff7ee 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -876,6 +876,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
 	if (!(vis->scalestep))
 	{
 		sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
+		sprtopscreen += vis->paperdistance * vis->paperoffset;
 		dc_iscale = FixedDiv(FRACUNIT, vis->scale);
 	}
 
@@ -921,7 +922,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
 	else
 	{
 		// Non-paper drawing loop
-		for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale)
+		for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->paperdistance)
 		{
 #ifdef RANGECHECK
 			texturecolumn = frac>>FRACBITS;
@@ -1098,30 +1099,59 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix
 {
 	vissprite_t *shadow;
 	patch_t *patch;
-	fixed_t xscale, yscale, shadowxscale, shadowyscale, x1, x2;
+	fixed_t xscale, yscale, shadowxscale, shadowyscale, shadowskew, x1, x2;
 	INT32 light = 0;
 	fixed_t scalemul; UINT8 trans;
 	fixed_t floordiff;
 	fixed_t floorz;
+	pslope_t *floorslope;
 
 	// Get floorz as the first floor below the object that's visible
 	floorz = (vis->heightsec != -1) ? sectors[vis->heightsec].floorheight : thing->floorz;
-	if (vis->sector->ffloors)
+	floorslope = (vis->heightsec != -1) ? NULL : thing->standingslope;
+
 	{
-		ffloor_t *rover = vis->sector->ffloors;
+		boolean original = true;
 		fixed_t z;
 
-		for (; rover; rover = rover->next)
+		if (vis->sector->ffloors)
 		{
-			if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE)))
-				continue;
+			ffloor_t *rover = vis->sector->ffloors;
 
-			z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight;
-			if (z < thing->z+thing->height/3 && z > floorz)
+			for (; rover; rover = rover->next)
+			{
+				if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE)))
+					continue;
+
+				z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight;
+				if (z < thing->z+thing->height/3 && z > floorz)
+				{
+					floorz = z;
+					floorslope = *rover->t_slope;
+					original = false;
+				}
+				else if (original && (*rover->t_slope) && z < thing->z+thing->height/3 && z > floorz - FixedMul(abs((*rover->t_slope)->zdelta), thing->radius*2))
+				{
+					// Guesstimated to be a usable floor. This is here to handle floorslope of non-grounded things, I guess.
+					floorz = z;
+					floorslope = *rover->t_slope;
+					original = false;
+				}
+			}
+		}
+
+		if (original && vis->sector->f_slope)
+		{
+			z = P_GetZAt(vis->sector->f_slope, thing->x, thing->y);
+			if (z < thing->z+thing->height/3 && z > floorz - FixedMul(abs(vis->sector->f_slope->zdelta), thing->radius*2))
+			{
 				floorz = z;
+				floorslope = vis->sector->f_slope;
+			}
 		}
 	}
 
+
 	if (abs(floorz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes
 
 	floordiff = abs(thing->z - floorz);
@@ -1136,6 +1166,28 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix
 	yscale = FixedDiv(projectiony, tz);
 	shadowxscale = FixedMul(thing->radius*2, scalemul) / patch->width;
 	shadowyscale = FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), FixedDiv(abs(floorz - viewz), tz));
+	shadowskew = 0;
+
+	if (floorslope)
+	{
+		// haha let's try some dumb stuff
+		fixed_t xslope, zslope;
+		angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - floorslope->xydirection) >> ANGLETOFINESHIFT;
+
+		xslope = FixedMul(FINESINE(sloperelang), floorslope->zdelta);
+		zslope = FixedMul(FINECOSINE(sloperelang), floorslope->zdelta);
+
+		//CONS_Printf("Shadow is sloped by %d %d\n", xslope, zslope);
+
+		if (viewz < floorz)
+			shadowyscale += FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope);
+		else
+			shadowyscale -= FixedMul(FixedMul(thing->radius*2 / patch->height, scalemul), zslope);
+
+		shadowyscale = abs(shadowyscale);
+
+		shadowskew = xslope;
+	}
 
 	tx -= patch->width * shadowxscale/2;
 	x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
@@ -1164,6 +1216,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix
 	shadow->gz = shadow->gzt - shadow->patch->height * shadowyscale;
 	shadow->texturemid = FixedDiv(shadow->gzt - viewz, shadowyscale);
 	shadow->scalestep = 0;
+	shadow->paperdistance = shadowskew; // repurposed variable
 
 	shadow->mobj = thing; // Easy access! Tails 06-07-2002
 
@@ -1183,6 +1236,10 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t tx, fix
 	if (shadow->x1 > x1)
 		shadow->startfrac += shadow->xiscale*(shadow->x1-x1);
 
+	// reusing x1 variable
+	x1 += (x2-x1)/2;
+	shadow->paperoffset = (vis->x1-x1)/2;
+
 	if (thing->subsector->sector->numlights)
 	{
 		INT32 lightnum;
@@ -1878,6 +1935,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
 	vis->pzt = vis->pz + vis->thingheight;
 	vis->texturemid = vis->gzt - viewz;
 	vis->scalestep = 0;
+	vis->paperdistance = 0;
 
 	vis->x1 = x1 < 0 ? 0 : x1;
 	vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;