diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 01e94485d85696736fa334ecbe40225ba77b66da..78e07a39796c0164bd1479f61c530815df880339 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -579,6 +579,7 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
 	rsp->starpostnum = LONG(players[i].starpostnum);
 	rsp->starposttime = (tic_t)LONG(players[i].starposttime);
 	rsp->starpostangle = (angle_t)LONG(players[i].starpostangle);
+	rsp->starpostscale = (fixed_t)LONG(players[i].starpostscale);
 
 	rsp->maxlink = LONG(players[i].maxlink);
 	rsp->dashspeed = (fixed_t)LONG(players[i].dashspeed);
@@ -714,6 +715,7 @@ static void resynch_read_player(resynch_pak *rsp)
 	players[i].starpostnum = LONG(rsp->starpostnum);
 	players[i].starposttime = (tic_t)LONG(rsp->starposttime);
 	players[i].starpostangle = (angle_t)LONG(rsp->starpostangle);
+	players[i].starpostscale = (fixed_t)LONG(rsp->starpostscale);
 
 	players[i].maxlink = LONG(rsp->maxlink);
 	players[i].dashspeed = (fixed_t)LONG(rsp->dashspeed);
diff --git a/src/d_clisrv.h b/src/d_clisrv.h
index a2f140f330a2fad15e362cb7deb632f87ba667f6..3bfabfc03760ab6e4c853bda98fd516e0519df87 100644
--- a/src/d_clisrv.h
+++ b/src/d_clisrv.h
@@ -228,6 +228,7 @@ typedef struct
 	INT32 starpostnum;
 	tic_t starposttime;
 	angle_t starpostangle;
+	fixed_t starpostscale;
 
 	INT32 maxlink;
 	fixed_t dashspeed;
diff --git a/src/d_player.h b/src/d_player.h
index 5860cf1de4b05f86b7567c4d87c3699475513c71..69080bd9dc230450241fb0ca668a53c32d54889c 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -441,6 +441,7 @@ typedef struct player_s
 	INT32 starpostnum; // The number of the last starpost you hit
 	tic_t starposttime; // Your time when you hit the starpost
 	angle_t starpostangle; // Angle that the starpost is facing - you respawn facing this way
+	fixed_t starpostscale; // Scale of the player; if negative, player is gravflipped
 
 	/////////////////
 	// NiGHTS Stuff//
diff --git a/src/g_game.c b/src/g_game.c
index d5faf68468cc2b1b0f01a09083210a6cb7dd2da6..89a96f3d0a2aeb424c1e0fc9ab06718503e8065e 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -2083,6 +2083,7 @@ static inline void G_PlayerFinishLevel(INT32 player)
 
 	p->mo->flags2 &= ~MF2_SHADOW; // cancel invisibility
 	P_FlashPal(p, 0, 0); // Resets
+	p->starpostscale = 0;
 	p->starpostangle = 0;
 	p->starposttime = 0;
 	p->starpostx = 0;
@@ -2129,6 +2130,7 @@ void G_PlayerReborn(INT32 player)
 	INT16 starpostz;
 	INT32 starpostnum;
 	INT32 starpostangle;
+	fixed_t starpostscale;
 	fixed_t jumpfactor;
 	fixed_t height;
 	fixed_t spinheight;
@@ -2184,6 +2186,7 @@ void G_PlayerReborn(INT32 player)
 	starpostz = players[player].starpostz;
 	starpostnum = players[player].starpostnum;
 	starpostangle = players[player].starpostangle;
+	starpostscale = players[player].starpostscale;
 	jumpfactor = players[player].jumpfactor;
 	height = players[player].height;
 	spinheight = players[player].spinheight;
@@ -2239,6 +2242,7 @@ void G_PlayerReborn(INT32 player)
 	p->starpostz = starpostz;
 	p->starpostnum = starpostnum;
 	p->starpostangle = starpostangle;
+	p->starpostscale = starpostscale;
 	p->jumpfactor = jumpfactor;
 	p->height = height;
 	p->spinheight = spinheight;
@@ -2657,6 +2661,7 @@ void G_DoReborn(INT32 playernum)
 			{
 				if (!playeringame[i])
 					continue;
+				players[i].starpostscale = 0;
 				players[i].starpostangle = 0;
 				players[i].starposttime = 0;
 				players[i].starpostx = 0;
@@ -2779,6 +2784,7 @@ void G_AddPlayer(INT32 playernum)
 			if (!(cv_coopstarposts.value && (gametype == GT_COOP) && (p->starpostnum < players[i].starpostnum)))
 				continue;
 
+			p->starpostscale = players[i].starpostscale;
 			p->starposttime = players[i].starposttime;
 			p->starpostx = players[i].starpostx;
 			p->starposty = players[i].starposty;
@@ -3866,7 +3872,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
 		for (i = 0; i < MAXPLAYERS; i++)
 		{
 			players[i].playerstate = PST_REBORN;
-			players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0;
+			players[i].starpostscale = players[i].starpostangle = players[i].starpostnum = players[i].starposttime = 0;
 			players[i].starpostx = players[i].starposty = players[i].starpostz = 0;
 
 			if (netgame || multiplayer)
diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c
index addd707e16da8e86254cedb7393788091678744f..dd9959afbdf3300bc150438e2e5cedce2f40d298 100644
--- a/src/lua_playerlib.c
+++ b/src/lua_playerlib.c
@@ -262,6 +262,8 @@ static int player_get(lua_State *L)
 		lua_pushinteger(L, plr->starposttime);
 	else if (fastcmp(field,"starpostangle"))
 		lua_pushangle(L, plr->starpostangle);
+	else if (fastcmp(field,"starpostscale"))
+		lua_pushfixed(L, plr->starpostscale);
 	else if (fastcmp(field,"angle_pos"))
 		lua_pushangle(L, plr->angle_pos);
 	else if (fastcmp(field,"old_angle_pos"))
@@ -570,6 +572,8 @@ static int player_set(lua_State *L)
 		plr->starposttime = (tic_t)luaL_checkinteger(L, 3);
 	else if (fastcmp(field,"starpostangle"))
 		plr->starpostangle = luaL_checkangle(L, 3);
+	else if (fastcmp(field,"starpostscale"))
+		plr->starpostscale = luaL_checkfixed(L, 3);
 	else if (fastcmp(field,"angle_pos"))
 		plr->angle_pos = luaL_checkangle(L, 3);
 	else if (fastcmp(field,"old_angle_pos"))
diff --git a/src/m_cheat.c b/src/m_cheat.c
index da449b2f7a0713286d85a753895a6024a2b209cf..bb757839aeb140105b3d06f335a19691bffc2099 100644
--- a/src/m_cheat.c
+++ b/src/m_cheat.c
@@ -831,6 +831,12 @@ void Command_Savecheckpoint_f(void)
 	players[consoleplayer].starposty = players[consoleplayer].mo->y>>FRACBITS;
 	players[consoleplayer].starpostz = players[consoleplayer].mo->floorz>>FRACBITS;
 	players[consoleplayer].starpostangle = players[consoleplayer].mo->angle;
+	players[consoleplayer].starpostscale = players[consoleplayer].mo->destscale;
+	if (players[consoleplayer].mo->flags2 & MF2_OBJECTFLIP)
+	{
+		players[consoleplayer].starpostscale *= -1;
+		players[consoleplayer].starpostz += players[consoleplayer].mo->height;
+	}
 
 	CONS_Printf(M_GetText("Temporary checkpoint created at %d, %d, %d\n"), players[consoleplayer].starpostx, players[consoleplayer].starposty, players[consoleplayer].starpostz);
 }
diff --git a/src/p_enemy.c b/src/p_enemy.c
index a93d3a2689a65092de59206d0048ffefdc203555..bc3665237d326e7045cad7a9c305d6c96f554fbb 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -6466,6 +6466,7 @@ void A_MixUp(mobj_t *actor)
 		INT32 starpostnum;
 		tic_t starposttime;
 		angle_t starpostangle;
+		fixed_t starpostscale;
 
 		INT32 mflags2;
 
@@ -6513,6 +6514,7 @@ void A_MixUp(mobj_t *actor)
 		starposty = players[one].starposty;
 		starpostz = players[one].starpostz;
 		starpostangle = players[one].starpostangle;
+		starpostscale = players[one].starpostscale;
 		starpostnum = players[one].starpostnum;
 		starposttime = players[one].starposttime;
 
@@ -6521,15 +6523,11 @@ void A_MixUp(mobj_t *actor)
 		P_MixUp(players[one].mo, players[two].mo->x, players[two].mo->y, players[two].mo->z, players[two].mo->angle,
 				players[two].starpostx, players[two].starposty, players[two].starpostz,
 				players[two].starpostnum, players[two].starposttime, players[two].starpostangle,
-				players[two].mo->flags2);
-
-		players[one].drawangle = players[two].drawangle;
+				players[two].starpostscale, players[two].drawangle, players[two].mo->flags2);
 
 		P_MixUp(players[two].mo, x, y, z, angle, starpostx, starposty, starpostz,
 				starpostnum, starposttime, starpostangle,
-				mflags2);
-
-		players[two].drawangle = drawangle;
+				starpostscale, drawangle, mflags2);
 
 		//carry set after mixup.  Stupid P_ResetPlayer() takes away some of the stuff we look for...
 		//but not all of it!  So we need to make sure they aren't set wrong or anything.
@@ -6556,6 +6554,7 @@ void A_MixUp(mobj_t *actor)
 		INT32 starpostnum[MAXPLAYERS];
 		tic_t starposttime[MAXPLAYERS];
 		angle_t starpostangle[MAXPLAYERS];
+		fixed_t starpostscale[MAXPLAYERS];
 
 		INT32 flags2[MAXPLAYERS];
 
@@ -6593,6 +6592,7 @@ void A_MixUp(mobj_t *actor)
 				starpostnum[counter] = players[i].starpostnum;
 				starposttime[counter] = players[i].starposttime;
 				starpostangle[counter] = players[i].starpostangle;
+				starpostscale[counter] = players[i].starpostscale;
 
 				flags2[counter] = players[i].mo->flags2;
 
@@ -6633,9 +6633,7 @@ void A_MixUp(mobj_t *actor)
 				P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom][0],
 					spposition[teleportfrom][0], spposition[teleportfrom][1], spposition[teleportfrom][2],
 					starpostnum[teleportfrom], starposttime[teleportfrom], starpostangle[teleportfrom],
-					flags2[teleportfrom]);
-
-				players[i].drawangle = anglepos[teleportfrom][1];
+					starpostscale[teleportfrom], anglepos[teleportfrom][1], flags2[teleportfrom]);
 
 				//...carry after.  same reasoning.
 				players[i].powers[pw_carry] = transcarry[teleportfrom];
diff --git a/src/p_inter.c b/src/p_inter.c
index ae610d0fc4c21a493073dfdf5806d86eb08e74ad..ae5fce6ff07acf581c60ed45beab376aa43ee26b 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -1427,6 +1427,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 						players[i].starposty = player->mo->y>>FRACBITS;
 						players[i].starpostz = special->z>>FRACBITS;
 						players[i].starpostangle = special->angle;
+						players[i].starpostscale = player->mo->destscale;
+						if (special->flags2 & MF2_OBJECTFLIP)
+						{
+							players[i].starpostscale *= -1;
+							players[i].starpostz += special->height>>FRACBITS;
+						}
 						players[i].starpostnum = special->health;
 
 						if (cv_coopstarposts.value == 2 && (players[i].playerstate == PST_DEAD || players[i].spectator) && P_GetLives(&players[i]))
@@ -1443,6 +1449,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 				player->starposty = toucher->y>>FRACBITS;
 				player->starpostz = special->z>>FRACBITS;
 				player->starpostangle = special->angle;
+				player->starpostscale = player->mo->destscale;
+				if (special->flags2 & MF2_OBJECTFLIP)
+				{
+					player->starpostscale *= -1;
+					player->starpostz += special->height>>FRACBITS;
+				}
 				player->starpostnum = special->health;
 				S_StartSound(toucher, special->info->painsound);
 			}
diff --git a/src/p_local.h b/src/p_local.h
index 3a0146e541fc9f3737239df62a3139db3f7a3258..662eb691a0a685747bd8e9b2b06e49101eeee8e0 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -509,7 +509,7 @@ extern INT32 ceilmovesound;
 void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
 			INT16 starpostx, INT16 starposty, INT16 starpostz,
 			INT32 starpostnum, tic_t starposttime, angle_t starpostangle,
-			INT32 flags2);
+			fixed_t starpostscale, angle_t drawangle, INT32 flags2);
 boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove);
 boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state);
 boolean P_CheckMissileSpawn(mobj_t *th);
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 1f42e3664e23dcbbc18bce57f2879e775cdfd8bb..5a70932de06d5e54b8bf0b9078ec94cadccf289a 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -10546,10 +10546,6 @@ void P_AfterPlayerSpawn(INT32 playernum)
 	else
 		p->viewz = p->mo->z + p->viewheight;
 
-	if (p->powers[pw_carry] != CR_NIGHTSMODE)
-		P_SetPlayerMobjState(p->mo, S_PLAY_STND);
-	p->pflags &= ~PF_SPINNING;
-
 	if (playernum == consoleplayer)
 	{
 		// wake up the status bar
@@ -10634,6 +10630,8 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
 			mobj->eflags |= MFE_VERTICALFLIP;
 			mobj->flags2 |= MF2_OBJECTFLIP;
 		}
+		if (mthing->options & MTF_AMBUSH)
+			P_SetPlayerMobjState(mobj, S_PLAY_FALL);
 	}
 	else
 		z = floor;
@@ -10652,7 +10650,12 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing)
 	P_SetThingPosition(mobj);
 
 	mobj->z = z;
-	if (mobj->z == mobj->floorz)
+	if (mobj->flags2 & MF2_OBJECTFLIP)
+	{
+		if (mobj->z + mobj->height == mobj->ceilingz)
+			mobj->eflags |= MFE_ONGROUND;
+	}
+	else if (mobj->z == mobj->floorz)
 		mobj->eflags |= MFE_ONGROUND;
 
 	mobj->angle = angle;
@@ -10688,17 +10691,29 @@ void P_MovePlayerToStarpost(INT32 playernum)
 	sector->ceilingheight;
 
 	z = p->starpostz << FRACBITS;
-	if (z < floor)
+
+	P_SetScale(mobj, (mobj->destscale = abs(p->starpostscale)));
+
+	if (p->starpostscale < 0)
+	{
+		mobj->flags2 |= MF2_OBJECTFLIP;
+		if (z >= ceiling)
+		{
+			mobj->eflags |= MFE_ONGROUND;
+			z = ceiling;
+		}
+		z -= mobj->height;
+	}
+	else if (z <= floor)
+	{
+		mobj->eflags |= MFE_ONGROUND;
 		z = floor;
-	else if (z > ceiling - mobjinfo[MT_PLAYER].height)
-		z = ceiling - mobjinfo[MT_PLAYER].height;
+	}
 
 	mobj->floorz = floor;
 	mobj->ceilingz = ceiling;
 
 	mobj->z = z;
-	if (mobj->z == mobj->floorz)
-		mobj->eflags |= MFE_ONGROUND;
 
 	mobj->angle = p->starpostangle;
 
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 7c073b1514762b74ab6d352d2cdbebb755670ff1..12f14e99da1d2c42131b099961a90b052547bc49 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -189,6 +189,7 @@ static void P_NetArchivePlayers(void)
 		WRITEINT16(save_p, players[i].starpostz);
 		WRITEINT32(save_p, players[i].starpostnum);
 		WRITEANGLE(save_p, players[i].starpostangle);
+		WRITEFIXED(save_p, players[i].starpostscale);
 
 		WRITEANGLE(save_p, players[i].angle_pos);
 		WRITEANGLE(save_p, players[i].old_angle_pos);
@@ -397,6 +398,7 @@ static void P_NetUnArchivePlayers(void)
 		players[i].starpostz = READINT16(save_p);
 		players[i].starpostnum = READINT32(save_p);
 		players[i].starpostangle = READANGLE(save_p);
+		players[i].starpostscale = READFIXED(save_p);
 
 		players[i].angle_pos = READANGLE(save_p);
 		players[i].old_angle_pos = READANGLE(save_p);
diff --git a/src/p_spec.c b/src/p_spec.c
index 37a1652f0d77cc7f8b262d80769cd998cc241657..fbf896a2bcea4d032f5cf5831374a685fe54d47f 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -4942,7 +4942,7 @@ DoneSection2:
 						CONS_Printf(M_GetText("%s started lap %u\n"), player_names[player-players], (UINT32)player->laps+1);
 
 					// Reset starposts (checkpoints) info
-					player->starpostangle = player->starposttime = player->starpostnum = 0;
+					player->starpostscale = player->starpostangle = player->starposttime = player->starpostnum = 0;
 					player->starpostx = player->starposty = player->starpostz = 0;
 					P_ResetStarposts();
 
diff --git a/src/p_telept.c b/src/p_telept.c
index e80dd04284778301e8210e45349be8d66a2e8a3d..632b81e0488bc3ebeb1306365f2f7e2a476e248f 100644
--- a/src/p_telept.c
+++ b/src/p_telept.c
@@ -33,7 +33,7 @@
 void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
 			INT16 starpostx, INT16 starposty, INT16 starpostz,
 			INT32 starpostnum, tic_t starposttime, angle_t starpostangle,
-			INT32 flags2)
+			fixed_t starpostscale, angle_t drawangle, INT32 flags2)
 {
 	const INT32 takeflags2 = MF2_TWOD|MF2_OBJECTFLIP;
 
@@ -89,8 +89,11 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
 		thing->player->starpostz = starpostz;
 		thing->player->starposttime = starposttime;
 		thing->player->starpostangle = starpostangle;
+		thing->player->starpostscale = starpostscale;
 		thing->player->starpostnum = starpostnum;
 
+		thing->player->drawangle = drawangle;
+
 		// Reset map starposts for the player's new info.
 		P_ResetStarposts();
 		P_ClearStarPost(starpostnum);