diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 36ff86abd7d0770351234913b03d837e2086b62d..f253861de36dbd65d40a108728a0f2ce91c11338 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -5378,7 +5378,10 @@ static void HWR_ProjectSprite(mobj_t *thing)
 
 		if (vflip)
 		{
-			gz = FIXED_TO_FLOAT(interp.z + thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
+			if (thing->scale != thing->old_scale) // Interpolate heights in reverse gravity when scaling mobjs
+				gz = FIXED_TO_FLOAT(interp.z + FixedMul(thing->height, FixedDiv(interp.scale, thing->scale))) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
+			else
+				gz = FIXED_TO_FLOAT(interp.z + thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
 			gzt = gz + (FIXED_TO_FLOAT(spr_height) * this_yscale);
 		}
 		else
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index d005f00377ad13999aa03346b0d3aa910f3b08ae..87881be8d66da9777f86e1472750d9c05fb4094f 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -1585,7 +1585,12 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
 		p.y = FIXED_TO_FLOAT(interp.y)+md2->offset;
 
 		if (flip)
-			p.z = FIXED_TO_FLOAT(interp.z + spr->mobj->height);
+		{
+			if (spr->mobj->scale != spr->mobj->old_scale) // Interpolate heights in reverse gravity when scaling mobjs
+				p.z = FIXED_TO_FLOAT(interp.z + FixedMul(spr->mobj->height, FixedDiv(interp.scale, spr->mobj->scale)));
+			else
+				p.z = FIXED_TO_FLOAT(interp.z + spr->mobj->height);
+		}
 		else
 			p.z = FIXED_TO_FLOAT(interp.z);
 
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 2a40175dc7a744bb6743b490f0028cc45a1a5496..9550535f10081714fb4c6ac3d27511bf57ac2ba5 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -12593,7 +12593,7 @@ static boolean P_SetupNiGHTSDrone(mapthing_t *mthing, mobj_t *mobj)
 	dronemangoaldiff = max(mobjinfo[MT_NIGHTSDRONE_MAN].height - mobjinfo[MT_NIGHTSDRONE_GOAL].height, 0);
 
 	if (flip && mobj->height != oldheight)
-		P_MoveOrigin(mobj, mobj->x, mobj->y, mobj->z - (mobj->height - oldheight));
+		P_SetOrigin(mobj, mobj->x, mobj->y, mobj->z - (mobj->height - oldheight));
 
 	if (!flip)
 	{
diff --git a/src/p_user.c b/src/p_user.c
index 84d0c0abf0789314322bc7869a25949ad54d94b5..48141815c308157a6763df432c2a09377152a777 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -8717,7 +8717,10 @@ void P_MovePlayer(player_t *player)
 			player->mo->height = P_GetPlayerHeight(player);
 
 		if (player->mo->eflags & MFE_VERTICALFLIP && player->mo->height != oldheight) // adjust z height for reverse gravity, similar to how it's done for scaling
-			player->mo->z -= player->mo->height - oldheight;
+		{
+			player->mo->z     -= player->mo->height - oldheight;
+			player->mo->old_z -= player->mo->height - oldheight; // Snap the Z adjustment, while keeping the Z interpolation
+		}
 
 		// Crush test...
 		if ((player->mo->ceilingz - player->mo->floorz < player->mo->height)
diff --git a/src/r_things.c b/src/r_things.c
index 90b80dda8f499c5f70b93b1766a305c626907e29..e69fe1b822313bbdeae871741e89924a4a678d36 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -2114,7 +2114,11 @@ static void R_ProjectSprite(mobj_t *thing)
 			// When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned.
 			// sprite height - sprite topoffset is the proper inverse of the vertical offset, of course.
 			// remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes!
-			gz = interp.z + oldthing->height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale));
+
+			if (oldthing->scale != oldthing->old_scale) // Interpolate heights in reverse gravity when scaling mobjs
+				gz = interp.z + FixedMul(oldthing->height, FixedDiv(interp.scale, oldthing->scale)) - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale));
+			else
+				gz = interp.z + oldthing->height - FixedMul(spr_topoffset, FixedMul(spriteyscale, this_scale));
 			gzt = gz + FixedMul(spr_height, FixedMul(spriteyscale, this_scale));
 		}
 		else