diff --git a/src/b_bot.c b/src/b_bot.c
index dc65c9c16b8dd8f8bfa98dca65fbfd022d6d02ea..543bcb183000d42db13f6a534c5bfad0d96460a2 100644
--- a/src/b_bot.c
+++ b/src/b_bot.c
@@ -271,6 +271,12 @@ void B_RespawnBot(INT32 playernum)
 	player->powers[pw_spacetime] = sonic->player->powers[pw_spacetime];
 	player->powers[pw_gravityboots] = sonic->player->powers[pw_gravityboots];
 	player->powers[pw_nocontrol] = sonic->player->powers[pw_nocontrol];
+	player->acceleration = sonic->player->acceleration;
+	player->accelstart = sonic->player->accelstart;
+	player->thrustfactor = sonic->player->thrustfactor;
+	player->normalspeed = sonic->player->normalspeed;
+	player->pflags |= PF_AUTOBRAKE;
+	player->pflags &= ~PF_DIRECTIONCHAR;
 
 	P_TeleportMove(tails, x, y, z);
 	if (player->charability == CA_FLY)
diff --git a/src/d_clisrv.c b/src/d_clisrv.c
index 3878d879560d0a0991a0191cfdabd9c6188c8658..2bc738dea78e6417a092688c29bcac266a7c3717 100644
--- a/src/d_clisrv.c
+++ b/src/d_clisrv.c
@@ -3097,11 +3097,15 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
 			secondarydisplayplayer = newplayernum;
 			DEBFILE("spawning me\n");
 			// Apply player flags as soon as possible!
-			players[newplayernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE);
+			players[newplayernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE);
 			if (cv_flipcam.value)
 				players[newplayernum].pflags |= PF_FLIPCAM;
 			if (cv_analog.value)
 				players[newplayernum].pflags |= PF_ANALOGMODE;
+			if (cv_directionchar.value)
+				players[newplayernum].pflags |= PF_DIRECTIONCHAR;
+			if (cv_autobrake.value)
+				players[newplayernum].pflags |= PF_AUTOBRAKE;
 		}
 		else
 		{
@@ -3110,11 +3114,15 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum)
 			if (botingame)
 				players[newplayernum].bot = 1;
 			// Same goes for player 2 when relevant
-			players[newplayernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE);
+			players[newplayernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE);
 			if (cv_flipcam2.value)
 				players[newplayernum].pflags |= PF_FLIPCAM;
 			if (cv_analog2.value)
 				players[newplayernum].pflags |= PF_ANALOGMODE;
+			if (cv_directionchar2.value)
+				players[newplayernum].pflags |= PF_DIRECTIONCHAR;
+			if (cv_autobrake2.value)
+				players[newplayernum].pflags |= PF_AUTOBRAKE;
 		}
 		D_SendPlayerConfig();
 		addedtogame = true;
diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 7f408a2b5d8b28148dd88ca30a938f07626729bd..4f9623900e3017772b8329fabcab98749471985b 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -771,6 +771,12 @@ void D_RegisterClientCommands(void)
 	CV_RegisterVar(&cv_useranalog);
 	CV_RegisterVar(&cv_useranalog2);
 
+	// deez New User eXperiences
+	CV_RegisterVar(&cv_directionchar);
+	CV_RegisterVar(&cv_directionchar2);
+	CV_RegisterVar(&cv_autobrake);
+	CV_RegisterVar(&cv_autobrake2);
+
 	// s_sound.c
 	CV_RegisterVar(&cv_soundvolume);
 	CV_RegisterVar(&cv_closedcaptioning);
@@ -1433,6 +1439,10 @@ void SendWeaponPref(void)
 		buf[0] |= 1;
 	if (players[consoleplayer].pflags & PF_ANALOGMODE)
 		buf[0] |= 2;
+	if (players[consoleplayer].pflags & PF_DIRECTIONCHAR)
+		buf[0] |= 4;
+	if (players[consoleplayer].pflags & PF_AUTOBRAKE)
+		buf[0] |= 8;
 	SendNetXCmd(XD_WEAPONPREF, buf, 1);
 }
 
@@ -1445,6 +1455,10 @@ void SendWeaponPref2(void)
 		buf[0] |= 1;
 	if (players[secondarydisplayplayer].pflags & PF_ANALOGMODE)
 		buf[0] |= 2;
+	if (players[secondarydisplayplayer].pflags & PF_DIRECTIONCHAR)
+		buf[0] |= 4;
+	if (players[secondarydisplayplayer].pflags & PF_AUTOBRAKE)
+		buf[0] |= 8;
 	SendNetXCmd2(XD_WEAPONPREF, buf, 1);
 }
 
@@ -1452,11 +1466,15 @@ static void Got_WeaponPref(UINT8 **cp,INT32 playernum)
 {
 	UINT8 prefs = READUINT8(*cp);
 
-	players[playernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE);
+	players[playernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE);
 	if (prefs & 1)
 		players[playernum].pflags |= PF_FLIPCAM;
 	if (prefs & 2)
 		players[playernum].pflags |= PF_ANALOGMODE;
+	if (prefs & 4)
+		players[playernum].pflags |= PF_DIRECTIONCHAR;
+	if (prefs & 8)
+		players[playernum].pflags |= PF_AUTOBRAKE;
 }
 
 void D_SendPlayerConfig(void)
@@ -2578,12 +2596,12 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
 		{
 			players[playernum].spectator = true;
 			players[playernum].pflags &= ~PF_TAGIT;
-			players[playernum].pflags &= ~PF_TAGGED;
+			players[playernum].pflags &= ~PF_GAMETYPEOVER;
 		}
 		else if (NetPacket.packet.newteam != 3) // .newteam == 1 or 2.
 		{
 			players[playernum].spectator = false;
-			players[playernum].pflags &= ~PF_TAGGED;//Just in case.
+			players[playernum].pflags &= ~PF_GAMETYPEOVER; //Just in case.
 
 			if (NetPacket.packet.newteam == 1) //Make the player IT.
 				players[playernum].pflags |= PF_TAGIT;
diff --git a/src/d_player.h b/src/d_player.h
index c10e59405e4fe44c48bacb130421a41217f3a9b1..bf0b303b8ece7552fb3a40c271826a3b40905fd3 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -98,66 +98,58 @@ typedef enum
 //
 typedef enum
 {
-	// Flip camera angle with gravity flip prefrence.
-	PF_FLIPCAM = 1,
+	// Cvars
+	PF_FLIPCAM       = 1, // Flip camera angle with gravity flip prefrence.
+	PF_ANALOGMODE    = 1<<1, // Analog mode?
+	PF_DIRECTIONCHAR = 1<<2, // Directional character sprites?
+	PF_AUTOBRAKE     = 1<<3, // Autobrake?
 
 	// Cheats
-	PF_GODMODE = 1<<1,
-	PF_NOCLIP  = 1<<2,
-	PF_INVIS   = 1<<3,
+	PF_GODMODE = 1<<4,
+	PF_NOCLIP  = 1<<5,
+	PF_INVIS   = 1<<6,
 
 	// True if button down last tic.
-	PF_ATTACKDOWN = 1<<4,
-	PF_USEDOWN    = 1<<5,
-	PF_JUMPDOWN   = 1<<6,
-	PF_WPNDOWN    = 1<<7,
+	PF_ATTACKDOWN = 1<<7,
+	PF_USEDOWN    = 1<<8,
+	PF_JUMPDOWN   = 1<<9,
+	PF_WPNDOWN    = 1<<10,
 
 	// Unmoving states
-	PF_STASIS     = 1<<8, // Player is not allowed to move
-	PF_JUMPSTASIS = 1<<9, // and that includes jumping.
+	PF_STASIS     = 1<<11, // Player is not allowed to move
+	PF_JUMPSTASIS = 1<<12, // and that includes jumping.
 	PF_FULLSTASIS = PF_STASIS|PF_JUMPSTASIS,
 
-	// Did you get a time-over?
-	PF_TIMEOVER = 1<<10,
+	// Applying autobrake?
+	PF_APPLYAUTOBRAKE = 1<<13,
 
 	// Character action status
-	PF_STARTJUMP = 1<<11,
-	PF_JUMPED    = 1<<12,
-	PF_SPINNING  = 1<<13,
-	PF_STARTDASH = 1<<14,
-	PF_THOKKED   = 1<<15,
+	PF_STARTJUMP     = 1<<14,
+	PF_JUMPED        = 1<<15,
+	PF_NOJUMPDAMAGE  = 1<<16,
 
-	// Are you gliding?
-	PF_GLIDING   = 1<<16,
+	PF_SPINNING      = 1<<17,
+	PF_STARTDASH     = 1<<18,
 
-	// Sliding (usually in water) like Labyrinth/Oil Ocean
-	PF_SLIDING   = 1<<17,
+	PF_THOKKED       = 1<<19,
+	PF_SHIELDABILITY = 1<<20,
+	PF_GLIDING       = 1<<21,
+	PF_BOUNCING      = 1<<22,
 
-	// Bouncing
-	PF_BOUNCING  = 1<<18,
+	// Sliding (usually in water) like Labyrinth/Oil Ocean
+	PF_SLIDING       = 1<<23,
 
-	/*** NIGHTS STUFF ***/
-	PF_TRANSFERTOCLOSEST = 1<<19,
-	PF_NIGHTSFALL        = 1<<20,
-	PF_DRILLING          = 1<<21,
-	PF_SKIDDOWN          = 1<<22,
+	// NiGHTS stuff
+	PF_TRANSFERTOCLOSEST = 1<<24,
+	PF_DRILLING          = 1<<25,
 
-	/*** TAG STUFF ***/
-	PF_TAGGED            = 1<<23, // Player has been tagged and awaits the next round in hide and seek.
-	PF_TAGIT             = 1<<24, // The player is it! For Tag Mode
+	// Gametype-specific stuff
+	PF_GAMETYPEOVER = 1<<26, // Race time over, or H&S out-of-game
+	PF_TAGIT        = 1<<27, // The player is it! For Tag Mode
 
 	/*** misc ***/
-	PF_FORCESTRAFE       = 1<<25, // Turning inputs are translated into strafing inputs
-	PF_ANALOGMODE        = 1<<26, // Analog mode?
-
-	// Can carry another player?
-	PF_CANCARRY          = 1<<27,
-
-	// Used shield ability
-	PF_SHIELDABILITY     = 1<<28,
-
-	// Jump damage?
-	PF_NOJUMPDAMAGE   = 1<<29,
+	PF_FORCESTRAFE = 1<<28, // Turning inputs are translated into strafing inputs
+	PF_CANCARRY    = 1<<29, // Can carry another player?
 
 	// up to 1<<31 is free
 } pflags_t;
@@ -234,6 +226,7 @@ typedef enum
 	CR_PLAYER,
 	// NiGHTS mode. Not technically a CARRYING, but doesn't stack with any of the others, so might as well go here.
 	CR_NIGHTSMODE,
+	CR_NIGHTSFALL,
 	// Old Brak sucks hard, but this gimmick could be used for something better, so we might as well continue supporting it.
 	CR_BRAKGOOP,
 	// Specific level gimmicks.
diff --git a/src/dehacked.c b/src/dehacked.c
index 5867eb90af49983e63ac0ea45f84f240be276fac..db559632c0385db26e112edf0ff23d8d5bafb105 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -6422,8 +6422,12 @@ static const char *const MAPTHINGFLAG_LIST[4] = {
 #endif
 
 static const char *const PLAYERFLAG_LIST[] = {
-	// Flip camera angle with gravity flip prefrence.
-	"FLIPCAM",
+
+	// Cvars
+	"FLIPCAM", // Flip camera angle with gravity flip prefrence.
+	"ANALOGMODE", // Analog mode?
+	"DIRECTIONCHAR", // Directional character sprites?
+	"AUTOBRAKE", // Autobrake?
 
 	// Cheats
 	"GODMODE",
@@ -6441,41 +6445,36 @@ static const char *const PLAYERFLAG_LIST[] = {
 	"JUMPSTASIS", // and that includes jumping.
 	// (we don't include FULLSTASIS here I guess because it's just those two together...?)
 
-	// Did you get a time-over?
-	"TIMEOVER",
+	// Applying autobrake?
+	"APPLYAUTOBRAKE",
 
 	// Character action status
 	"STARTJUMP",
 	"JUMPED",
+	"NOJUMPDAMAGE",
+
 	"SPINNING",
 	"STARTDASH",
-	"THOKKED",
 
-	// Are you gliding?
+	"THOKKED",
+	"SHIELDABILITY",
 	"GLIDING",
+	"BOUNCING",
 
 	// Sliding (usually in water) like Labyrinth/Oil Ocean
 	"SLIDING",
 
-	// Bouncing
-	"BOUNCING",
-
-	/*** NIGHTS STUFF ***/
+	// NiGHTS stuff
 	"TRANSFERTOCLOSEST",
-	"NIGHTSFALL",
 	"DRILLING",
-	"SKIDDOWN",
 
-	/*** TAG STUFF ***/
-	"TAGGED", // Player has been tagged and awaits the next round in hide and seek.
+	// Gametype-specific stuff
+	"GAMETYPEOVER", // Race time over, or H&S out-of-game
 	"TAGIT", // The player is it! For Tag Mode
 
 	/*** misc ***/
 	"FORCESTRAFE", // Translate turn inputs into strafe inputs
-	"ANALOGMODE", // Analog mode?
 	"CANCARRY", // Can carry?
-	"SHIELDABILITY", // Thokked with shield ability
-	"NOJUMPDAMAGE", // No jump damage
 
 	NULL // stop loop here.
 };
@@ -6892,6 +6891,7 @@ struct {
 	{"CR_GENERIC",CR_GENERIC},
 	{"CR_PLAYER",CR_PLAYER},
 	{"CR_NIGHTSMODE",CR_NIGHTSMODE},
+	{"CR_NIGHTSFALL",CR_NIGHTSFALL},
 	{"CR_BRAKGOOP",CR_BRAKGOOP},
 	{"CR_ZOOMTUBE",CR_ZOOMTUBE},
 	{"CR_ROPEHANG",CR_ROPEHANG},
diff --git a/src/g_game.c b/src/g_game.c
index e996938ab30ac44cc2d655406e8008e46aaca748..be53744b9a09ee208f44d99c9c1428ee376a270d 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -286,6 +286,10 @@ static void UserAnalog_OnChange(void);
 static void UserAnalog2_OnChange(void);
 static void Analog_OnChange(void);
 static void Analog2_OnChange(void);
+static void DirectionChar_OnChange(void);
+static void DirectionChar2_OnChange(void);
+static void AutoBrake_OnChange(void);
+static void AutoBrake2_OnChange(void);
 void SendWeaponPref(void);
 void SendWeaponPref2(void);
 
@@ -368,6 +372,14 @@ consvar_t cv_useranalog = {"useranalog", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserA
 consvar_t cv_useranalog2 = {"useranalog2", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog2_OnChange, 0, NULL, NULL, 0, 0, NULL};
 #endif
 
+static CV_PossibleValue_t directionchar_cons_t[] = {{0, "Camera"}, {1, "Movement"}, {0, NULL}};
+
+// deez New User eXperiences
+consvar_t cv_directionchar = {"directionchar", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar_OnChange, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_directionchar2 = {"directionchar2", "Movement", CV_SAVE|CV_CALL, directionchar_cons_t, DirectionChar2_OnChange, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_autobrake = {"autobrake", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake_OnChange, 0, NULL, NULL, 0, 0, NULL};
+consvar_t cv_autobrake2 = {"autobrake2", "On", CV_SAVE|CV_CALL, CV_OnOff, AutoBrake2_OnChange, 0, NULL, NULL, 0, 0, NULL};
+
 typedef enum
 {
 	AXISNONE = 0,
@@ -1615,6 +1627,46 @@ static void Analog2_OnChange(void)
 	SendWeaponPref2();
 }
 
+static void DirectionChar_OnChange(void)
+{
+	if (cv_directionchar.value)
+		players[consoleplayer].pflags |= PF_DIRECTIONCHAR;
+	else
+		players[consoleplayer].pflags &= ~PF_DIRECTIONCHAR;
+
+	SendWeaponPref();
+}
+
+static void DirectionChar2_OnChange(void)
+{
+	if (cv_directionchar2.value)
+		players[secondarydisplayplayer].pflags |= PF_DIRECTIONCHAR;
+	else
+		players[secondarydisplayplayer].pflags &= ~PF_DIRECTIONCHAR;
+
+	SendWeaponPref2();
+}
+
+static void AutoBrake_OnChange(void)
+{
+	if (cv_autobrake.value)
+		players[consoleplayer].pflags |= PF_AUTOBRAKE;
+	else
+		players[consoleplayer].pflags &= ~PF_AUTOBRAKE;
+
+	SendWeaponPref();
+}
+
+static void AutoBrake2_OnChange(void)
+{
+	if (cv_autobrake2.value)
+		players[secondarydisplayplayer].pflags |= PF_AUTOBRAKE;
+	else
+		players[secondarydisplayplayer].pflags &= ~PF_AUTOBRAKE;
+
+	SendWeaponPref2();
+}
+
 //
 // G_DoLoadLevel
 //
@@ -2103,7 +2155,7 @@ void G_PlayerReborn(INT32 player)
 	jointime = players[player].jointime;
 	spectator = players[player].spectator;
 	outofcoop = players[player].outofcoop;
-	pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE));
+	pflags = (players[player].pflags & (PF_FLIPCAM|PF_ANALOGMODE|PF_DIRECTIONCHAR|PF_AUTOBRAKE|PF_TAGIT|PF_GAMETYPEOVER));
 
 	// As long as we're not in multiplayer, carry over cheatcodes from map to map
 	if (!(netgame || multiplayer))
@@ -3752,7 +3804,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
 				players[i].score = 0;
 
 			// The latter two should clear by themselves, but just in case
-			players[i].pflags &= ~(PF_TAGIT|PF_TAGGED|PF_FULLSTASIS);
+			players[i].pflags &= ~(PF_TAGIT|PF_GAMETYPEOVER|PF_FULLSTASIS);
 
 			// Clear cheatcodes too, just in case.
 			players[i].pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS);
diff --git a/src/g_game.h b/src/g_game.h
index 72a6f3d6e56e2e73f909134bbdfe39c76068fdc2..cd079e844b1136f528687e00c5b0dbe0e57cb52d 100644
--- a/src/g_game.h
+++ b/src/g_game.h
@@ -59,6 +59,8 @@ extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_mousemove;
 extern consvar_t cv_invertmouse2, cv_alwaysfreelook2, cv_mousemove2;
 extern consvar_t cv_useranalog, cv_useranalog2;
 extern consvar_t cv_analog, cv_analog2;
+extern consvar_t cv_directionchar, cv_directionchar2;
+extern consvar_t cv_autobrake, cv_autobrake2;
 extern consvar_t cv_sideaxis,cv_turnaxis,cv_moveaxis,cv_lookaxis,cv_fireaxis,cv_firenaxis;
 extern consvar_t cv_sideaxis2,cv_turnaxis2,cv_moveaxis2,cv_lookaxis2,cv_fireaxis2,cv_firenaxis2;
 extern consvar_t cv_ghost_bestscore, cv_ghost_besttime, cv_ghost_bestrings, cv_ghost_last, cv_ghost_guest;
diff --git a/src/m_menu.c b/src/m_menu.c
index 64255e71a82d6630a962878cde7c634a8262af9c..84edcbfe32dedfaaff092fd8a9a01290f306b24e 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -1061,7 +1061,9 @@ static menuitem_t OP_P1ControlsMenu[] =
 	{IT_STRING  | IT_CVAR, NULL, "Flip Camera with Gravity"  , &cv_flipcam , 60},
 	{IT_STRING  | IT_CVAR, NULL, "Crosshair", &cv_crosshair, 70},
 
-	{IT_STRING  | IT_CVAR, NULL, "Analog Control", &cv_useranalog,  90},
+	//{IT_STRING  | IT_CVAR, NULL, "Analog Control", &cv_useranalog,  90},
+	{IT_STRING  | IT_CVAR, NULL, "Character angle", &cv_directionchar,  90},
+	{IT_STRING  | IT_CVAR, NULL, "Automatic braking", &cv_autobrake,  100},
 };
 
 static menuitem_t OP_P2ControlsMenu[] =
@@ -1074,7 +1076,9 @@ static menuitem_t OP_P2ControlsMenu[] =
 	{IT_STRING  | IT_CVAR, NULL, "Flip Camera with Gravity"  , &cv_flipcam2 , 60},
 	{IT_STRING  | IT_CVAR, NULL, "Crosshair", &cv_crosshair2, 70},
 
-	{IT_STRING  | IT_CVAR, NULL, "Analog Control", &cv_useranalog2,  90},
+	//{IT_STRING  | IT_CVAR, NULL, "Analog Control", &cv_useranalog2,  90},
+	{IT_STRING  | IT_CVAR, NULL, "Character angle", &cv_directionchar2,  90},
+	{IT_STRING  | IT_CVAR, NULL, "Automatic braking", &cv_autobrake2,  100},
 };
 
 static menuitem_t OP_ChangeControlsMenu[] =
diff --git a/src/p_inter.c b/src/p_inter.c
index d2101ca575ae358648a1ed863f642dce57b2d0d2..c843838b6d031459e913896f1978a34bf32bfaec 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -1871,7 +1871,7 @@ void P_CheckTimeLimit(void)
 			for (i = 0; i < MAXPLAYERS; i++)
 			{
 				if (!playeringame[i] || players[i].spectator
-				 || (players[i].pflags & PF_TAGGED) || (players[i].pflags & PF_TAGIT))
+				 || (players[i].pflags & PF_GAMETYPEOVER) || (players[i].pflags & PF_TAGIT))
 					continue;
 
 				CONS_Printf(M_GetText("%s received double points for surviving the round.\n"), player_names[i]);
@@ -2018,7 +2018,7 @@ void P_CheckSurvivors(void)
 				spectators++;
 			else if (players[i].pflags & PF_TAGIT)
 				taggers++;
-			else if (!(players[i].pflags & PF_TAGGED))
+			else if (!(players[i].pflags & PF_GAMETYPEOVER))
 			{
 				survivorarray[survivors] = i;
 				survivors++;
@@ -2325,7 +2325,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 				}
 				else
 				{
-					if (!(target->player->pflags & PF_TAGGED))
+					if (!(target->player->pflags & PF_GAMETYPEOVER))
 					{
 						//otherwise, increment the tagger's score.
 						//in hide and seek, suiciding players are counted as found.
@@ -2337,7 +2337,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 								P_AddPlayerScore(&players[w], 100);
 						}
 
-						target->player->pflags |= PF_TAGGED;
+						target->player->pflags |= PF_GAMETYPEOVER;
 						CONS_Printf(M_GetText("%s was found!\n"), player_names[target->player-players]);
 						P_CheckSurvivors();
 					}
@@ -2793,7 +2793,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou
 		}
 		else
 		{
-			player->pflags |= PF_TAGGED; //in hide and seek, the player is tagged and stays stationary.
+			player->pflags |= PF_GAMETYPEOVER; //in hide and seek, the player is tagged and stays stationary.
 			CONS_Printf(M_GetText("%s was found!\n"), player_names[player-players]); // Tell everyone who is it!
 		}
 
@@ -3208,7 +3208,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
 			if (player->pflags & PF_GODMODE)
 				return false;
 
-			if (!(target->player->powers[pw_carry] == CR_NIGHTSMODE || target->player->pflags & PF_NIGHTSFALL) && (maptol & TOL_NIGHTS))
+			if ((maptol & TOL_NIGHTS) && target->player->powers[pw_carry] != CR_NIGHTSMODE && target->player->powers[pw_carry] != CR_NIGHTSFALL)
 				return false;
 
 			switch (damagetype)
@@ -3409,7 +3409,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
 	if (player->rings <= 0)
 		num_rings = 0;
 
-	if (num_rings > 32 && !(player->pflags & PF_NIGHTSFALL))
+	if (num_rings > 32 && player->powers[pw_carry] != CR_NIGHTSFALL)
 		num_rings = 32;
 
 	if (player->powers[pw_emeralds])
@@ -3441,7 +3441,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
 
 		// Make rings spill out around the player in 16 directions like SA, but spill like Sonic 2.
 		// Technically a non-SA way of spilling rings. They just so happen to be a little similar.
-		if (player->pflags & PF_NIGHTSFALL)
+		if (player->powers[pw_carry] == CR_NIGHTSFALL)
 		{
 			ns = FixedMul(((i*FRACUNIT)/16)+2*FRACUNIT, mo->scale);
 			mo->momx = FixedMul(FINECOSINE(fa),ns);
@@ -3481,13 +3481,13 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings)
 		}
 		if (player->mo->eflags & MFE_VERTICALFLIP)
 			mo->momz *= -1;
+
+		if (P_IsObjectOnGround(player->mo))
+			player->powers[pw_carry] = CR_NONE;
 	}
 
 	player->losstime += 10*TICRATE;
 
-	if (P_IsObjectOnGround(player->mo))
-		player->pflags &= ~PF_NIGHTSFALL;
-
 	return;
 }
 
diff --git a/src/p_local.h b/src/p_local.h
index b1bfc645641b39c04728d2bc45828a01214a6228..6fc218d362a6691e3ec66c1dc2991a9073cf23d3 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -140,6 +140,7 @@ boolean P_IsObjectOnGround(mobj_t *mo);
 boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec);
 boolean P_InSpaceSector(mobj_t *mo);
 boolean P_InQuicksand(mobj_t *mo);
+boolean P_PlayerHitFloor(player_t *player);
 
 void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative);
 void P_RestoreMusic(player_t *player);
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 31262ff1600ee1dfcf4903297f02e5ab3b88f04c..c5f67d685f6983f79154d40c884a0df41a05c6b0 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -3042,110 +3042,9 @@ static void P_PlayerZMovement(mobj_t *mo)
 					}
 				}
 
-				if (mo->health && !mo->player->spectator && !P_CheckDeathPitCollide(mo))
-				{
-					if ((mo->player->charability2 == CA2_SPINDASH) && !(mo->player->pflags & PF_THOKKED) && (mo->player->cmd.buttons & BT_USE) && (FixedHypot(mo->momx, mo->momy) > (5*mo->scale)))
-					{
-						mo->player->pflags |= PF_SPINNING;
-						P_SetPlayerMobjState(mo, S_PLAY_ROLL);
-						S_StartSound(mo, sfx_spin);
-					}
-					else
-						mo->player->pflags &= ~PF_SPINNING;
-
-					if (mo->player->pflags & PF_GLIDING) // ground gliding
-					{
-						mo->player->skidtime = TICRATE;
-						mo->tics = -1;
-					}
-					else if (mo->player->charability2 == CA2_MELEE && (mo->player->panim == PA_ABILITY2 && mo->state-states != S_PLAY_MELEE_LANDING))
-					{
-						P_SetPlayerMobjState(mo, S_PLAY_MELEE_LANDING);
-						mo->tics = (mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(mo->movefactor)))>>FRACBITS;
-						S_StartSound(mo, sfx_s3k8b);
-						mo->player->pflags |= PF_FULLSTASIS;
-					}
-					else if (mo->player->pflags & PF_JUMPED || !(mo->player->pflags & PF_SPINNING)
-					|| mo->player->powers[pw_tailsfly] || mo->state-states == S_PLAY_FLY_TIRED)
-					{
-						if (mo->player->cmomx || mo->player->cmomy)
-						{
-							if (mo->player->charflags & SF_DASHMODE && mo->player->dashmode >= 3*TICRATE && mo->player->panim != PA_DASH)
-								P_SetPlayerMobjState(mo, S_PLAY_DASH);
-							else if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale)
-							&& (mo->player->panim != PA_RUN || mo->state-states == S_PLAY_FLOAT_RUN))
-								P_SetPlayerMobjState(mo, S_PLAY_RUN);
-							else if ((mo->player->rmomx || mo->player->rmomy)
-							&& (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_FLOAT))
-								P_SetPlayerMobjState(mo, S_PLAY_WALK);
-							else if (!mo->player->rmomx && !mo->player->rmomy && mo->player->panim != PA_IDLE)
-								P_SetPlayerMobjState(mo, S_PLAY_STND);
-						}
-						else
-						{
-							if (mo->player->charflags & SF_DASHMODE && mo->player->dashmode >= 3*TICRATE && mo->player->panim != PA_DASH)
-								P_SetPlayerMobjState(mo, S_PLAY_DASH);
-							else if (mo->player->speed >= FixedMul(mo->player->runspeed, mo->scale)
-							&& (mo->player->panim != PA_RUN || mo->state-states == S_PLAY_FLOAT_RUN))
-								P_SetPlayerMobjState(mo, S_PLAY_RUN);
-							else if ((mo->momx || mo->momy)
-							&& (mo->player->panim != PA_WALK || mo->state-states == S_PLAY_FLOAT))
-								P_SetPlayerMobjState(mo, S_PLAY_WALK);
-							else if (!mo->momx && !mo->momy && mo->player->panim != PA_IDLE)
-								P_SetPlayerMobjState(mo, S_PLAY_STND);
-						}
-					}
-
-					if (!(mo->player->pflags & PF_GLIDING))
-						mo->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE);
-
-					mo->player->pflags &= ~(PF_STARTJUMP|PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/);
-					mo->player->secondjump = 0;
-					mo->player->glidetime = 0;
-					mo->player->climbing = 0;
-					mo->player->powers[pw_tailsfly] = 0;
-
-					if (mo->player->pflags & PF_SHIELDABILITY)
-					{
-						mo->player->pflags &= ~PF_SHIELDABILITY;
-
-						if ((mo->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) // Elemental shield's stomp attack.
-						{
-							if (mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) // play a blunt sound
-								S_StartSound(mo, sfx_s3k4c);
-							else // create a fire pattern on the ground
-							{
-								S_StartSound(mo, sfx_s3k47);
-								P_ElementalFire(mo->player, true);
-							}
-							P_SetObjectMomZ(mo,
-							(mo->eflags & MFE_UNDERWATER)
-							? 6*FRACUNIT/5
-							: 5*FRACUNIT/2,
-							false);
-							P_SetPlayerMobjState(mo, S_PLAY_FALL);
-							mo->momx = mo->momy = 0;
-							clipmomz = false;
-						}
-						else if ((mo->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) // Bubble shield's bounce attack.
-						{
-							P_DoBubbleBounce(mo->player);
-							clipmomz = false;
-						}
-					}
-
-					if (mo->player->pflags & PF_BOUNCING)
-					{
-						P_MobjCheckWater(mo);
-						mo->momz *= -1;
-						P_DoAbilityBounce(mo->player, true);
-						if (mo->player->scoreadd)
-							mo->player->scoreadd--;
-						clipmomz = false;
-					}
-				}
+				clipmomz = P_PlayerHitFloor(mo->player);
 			}
-			if (!(mo->player->pflags & PF_SPINNING))
+			if (!(mo->player->pflags & PF_SPINNING) && mo->player->powers[pw_carry] != CR_NIGHTSMODE)
 				mo->player->pflags &= ~PF_STARTDASH;
 
 			if (clipmomz)
diff --git a/src/p_setup.c b/src/p_setup.c
index 9c4bede7474571667eff241d2736e683418ea46b..dd5ef2d3025f4dddd2c6c4a08a17871c86dd100c 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -2244,7 +2244,7 @@ static void P_LevelInitStuff(void)
 		players[i].xtralife = players[i].deadtimer = players[i].numboxes = players[i].totalring = players[i].laps = 0;
 		players[i].rings = 0;
 		players[i].aiming = 0;
-		players[i].pflags &= ~PF_TIMEOVER;
+		players[i].pflags &= ~PF_GAMETYPEOVER;
 
 		players[i].losstime = 0;
 		players[i].timeshit = 0;
diff --git a/src/p_spec.c b/src/p_spec.c
index 2cad4fc904dd8a8cae32edbabd8f2e08c957656d..035bb9d78857860cfc9a666ebcab1a2d9d5e8b5f 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -3985,7 +3985,7 @@ DoneSection2:
 				player->powers[pw_carry] = CR_ZOOMTUBE;
 				player->speed = speed;
 				player->pflags |= PF_SPINNING;
-				player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_SLIDING|PF_CANCARRY);
+				player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY);
 				player->climbing = 0;
 
 				if (player->mo->state-states != S_PLAY_ROLL)
@@ -4065,7 +4065,7 @@ DoneSection2:
 				player->powers[pw_carry] = CR_ZOOMTUBE;
 				player->speed = speed;
 				player->pflags |= PF_SPINNING;
-				player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_SLIDING|PF_CANCARRY);
+				player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY);
 				player->climbing = 0;
 
 				if (player->mo->state-states != S_PLAY_ROLL)
@@ -4373,7 +4373,7 @@ DoneSection2:
 
 				S_StartSound(player->mo, sfx_s3k4a);
 
-				player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_SLIDING|PF_CANCARRY);
+				player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY);
 				player->climbing = 0;
 				P_SetThingPosition(player->mo);
 				P_SetPlayerMobjState(player->mo, S_PLAY_RIDE);
diff --git a/src/p_tick.c b/src/p_tick.c
index a79d71ef445333ae6585087d1336657fc1a9c9d3..658b1e4ea82255519c1574bf0098a88ddeef8a15 100644
--- a/src/p_tick.c
+++ b/src/p_tick.c
@@ -533,7 +533,7 @@ static inline void P_DoTagStuff(void)
 		for (i=0; i < MAXPLAYERS; i++)
 		{
 			if (playeringame[i] && !players[i].spectator && players[i].playerstate == PST_LIVE
-			&& !(players[i].pflags & (PF_TAGIT|PF_TAGGED)))
+			&& !(players[i].pflags & (PF_TAGIT|PF_GAMETYPEOVER)))
 				//points given is the number of participating players divided by two.
 				P_AddPlayerScore(&players[i], participants/2);
 		}
diff --git a/src/p_user.c b/src/p_user.c
index 9bd38c1cb08c3998126c98f879a689ab2e66f9d3..2be03a6f42b6e88ae873dd52b65e3e215156d8d0 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -576,7 +576,7 @@ static void P_DeNightserizePlayer(player_t *player)
 	thinker_t *th;
 	mobj_t *mo2;
 
-	player->powers[pw_carry] = CR_NONE;
+	player->powers[pw_carry] = CR_NIGHTSFALL;
 
 	player->powers[pw_underwater] = 0;
 	player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SPINNING|PF_DRILLING|PF_TRANSFERTOCLOSEST);
@@ -603,7 +603,6 @@ static void P_DeNightserizePlayer(player_t *player)
 	player->marescore = 0;
 
 	P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
-	player->pflags |= PF_NIGHTSFALL;
 
 	// If in a special stage, add some preliminary exit time.
 	if (G_IsSpecialStage(gamemap))
@@ -863,7 +862,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
 
 	// Point penalty for hitting a hazard during tag.
 	// Discourages players from intentionally hurting themselves to avoid being tagged.
-	if (gametype == GT_TAG && (!(player->pflags & PF_TAGGED) && !(player->pflags & PF_TAGIT)))
+	if (gametype == GT_TAG && (!(player->pflags & PF_GAMETYPEOVER) && !(player->pflags & PF_TAGIT)))
 	{
 		if (player->score >= 50)
 			player->score -= 50;
@@ -885,7 +884,7 @@ void P_ResetPlayer(player_t *player)
 {
 	player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_THOKKED|PF_CANCARRY|PF_SHIELDABILITY|PF_BOUNCING);
 
-	if (!(player->powers[pw_carry] == CR_NIGHTSMODE || player->powers[pw_carry] == CR_BRAKGOOP))
+	if (!(player->powers[pw_carry] == CR_NIGHTSMODE || player->powers[pw_carry] == CR_NIGHTSFALL || player->powers[pw_carry] == CR_BRAKGOOP))
 		player->powers[pw_carry] = CR_NONE;
 
 	player->secondjump = 0;
@@ -1778,6 +1777,122 @@ boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space
 	return false; // No vacuum here, Captain!
 }
 
+//
+// P_PlayerHitFloor
+//
+// Handles player hitting floor surface.
+// Returns whether to clip momz.
+boolean P_PlayerHitFloor(player_t *player)
+{
+	boolean clipmomz;
+
+	I_Assert(player->mo != NULL);
+
+	if ((clipmomz = !(P_CheckDeathPitCollide(player->mo))) && player->mo->health && !player->spectator)
+	{
+		if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_THOKKED) && (player->cmd.buttons & BT_USE) && (FixedHypot(player->mo->momx, player->mo->momy) > (5*player->mo->scale)))
+		{
+			player->pflags |= PF_SPINNING;
+			P_SetPlayerMobjState(player->mo, S_PLAY_ROLL);
+			S_StartSound(player->mo, sfx_spin);
+		}
+		else
+			player->pflags &= ~PF_SPINNING;
+
+		if (player->pflags & PF_GLIDING) // ground gliding
+		{
+			player->skidtime = TICRATE;
+			player->mo->tics = -1;
+		}
+		else if (player->charability2 == CA2_MELEE && (player->panim == PA_ABILITY2 && player->mo->state-states != S_PLAY_MELEE_LANDING))
+		{
+			P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING);
+			player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS;
+			S_StartSound(player->mo, sfx_s3k8b);
+			player->pflags |= PF_FULLSTASIS;
+		}
+		else if (player->pflags & PF_JUMPED || !(player->pflags & PF_SPINNING)
+		|| player->powers[pw_tailsfly] || player->mo->state-states == S_PLAY_FLY_TIRED)
+		{
+			if (player->cmomx || player->cmomy)
+			{
+				if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH)
+					P_SetPlayerMobjState(player->mo, S_PLAY_DASH);
+				else if (player->speed >= FixedMul(player->runspeed, player->mo->scale)
+				&& (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN))
+					P_SetPlayerMobjState(player->mo, S_PLAY_RUN);
+				else if ((player->rmomx || player->rmomy)
+				&& (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT))
+					P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
+				else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE)
+					P_SetPlayerMobjState(player->mo, S_PLAY_STND);
+			}
+			else
+			{
+				if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH)
+					P_SetPlayerMobjState(player->mo, S_PLAY_DASH);
+				else if (player->speed >= FixedMul(player->runspeed, player->mo->scale)
+				&& (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN))
+					P_SetPlayerMobjState(player->mo, S_PLAY_RUN);
+				else if ((player->mo->momx || player->mo->momy)
+				&& (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT))
+					P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
+				else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE)
+					P_SetPlayerMobjState(player->mo, S_PLAY_STND);
+			}
+		}
+
+		if (!(player->pflags & PF_GLIDING))
+			player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE);
+		player->pflags &= ~(PF_STARTJUMP|PF_THOKKED|PF_CANCARRY/*|PF_GLIDING*/);
+		player->secondjump = 0;
+		player->glidetime = 0;
+		player->climbing = 0;
+		player->powers[pw_tailsfly] = 0;
+
+		if (player->pflags & PF_SHIELDABILITY)
+		{
+			player->pflags &= ~PF_SHIELDABILITY;
+
+			if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) // Elemental shield's stomp attack.
+			{
+				if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) // play a blunt sound
+					S_StartSound(player->mo, sfx_s3k4c);
+				else // create a fire pattern on the ground
+				{
+					S_StartSound(player->mo, sfx_s3k47);
+					P_ElementalFire(player, true);
+				}
+				P_SetObjectMomZ(player->mo,
+				(player->mo->eflags & MFE_UNDERWATER)
+				? 6*FRACUNIT/5
+				: 5*FRACUNIT/2,
+				false);
+				P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
+				player->mo->momx = player->mo->momy = 0;
+				clipmomz = false;
+			}
+			else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) // Bubble shield's bounce attack.
+			{
+				P_DoBubbleBounce(player);
+				clipmomz = false;
+			}
+		}
+
+		if (player->pflags & PF_BOUNCING)
+		{
+			P_MobjCheckWater(player->mo);
+			player->mo->momz *= -1;
+			P_DoAbilityBounce(player, true);
+			if (player->scoreadd)
+				player->scoreadd--;
+			clipmomz = false;
+		}
+	}
+
+	return clipmomz;
+}
+
 boolean P_InQuicksand(mobj_t *mo) // Returns true if you are in quicksand
 {
 	sector_t *sector = mo->subsector->sector;
@@ -2153,6 +2268,9 @@ static void P_CheckQuicksand(player_t *player)
 
 				if (player->mo->z + player->mo->height >= ceilingheight)
 					player->mo->z = ceilingheight - player->mo->height;
+
+				if (player->mo->momz <= 0)
+					P_PlayerHitFloor(player);
 			}
 			else
 			{
@@ -2162,6 +2280,9 @@ static void P_CheckQuicksand(player_t *player)
 
 				if (player->mo->z <= floorheight)
 					player->mo->z = floorheight;
+
+				if (player->mo->momz >= 0)
+					P_PlayerHitFloor(player);
 			}
 
 			friction = abs(rover->master->v1->y - rover->master->v2->y)>>6;
@@ -6282,7 +6403,7 @@ static void P_NiGHTSMovement(player_t *player)
 	 && ((cmd->buttons & (BT_CAMLEFT|BT_CAMRIGHT)) == (BT_CAMLEFT|BT_CAMRIGHT)
 	  || (cmd->buttons & BT_USE)))
 	{
-		if (!(player->pflags & PF_SKIDDOWN))
+		if (!(player->pflags & PF_STARTDASH))
 			S_StartSound(player->mo, sfx_ngskid);
 
 		// You can tap the button to only slow down a bit,
@@ -6300,10 +6421,10 @@ static void P_NiGHTSMovement(player_t *player)
 			}
 		}
 
-		player->pflags |= PF_SKIDDOWN;
+		player->pflags |= PF_STARTDASH;
 	}
 	else
-		player->pflags &= ~PF_SKIDDOWN;
+		player->pflags &= ~PF_STARTDASH;
 
 	{
 		const angle_t fa = (FixedAngle(player->flyangle*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK;
@@ -6749,7 +6870,7 @@ static void P_MovePlayer(player_t *player)
 			if (!(player->pflags & PF_TAGIT))
 			{
 				forcestasis = true;
-				if (player->pflags & PF_TAGGED) // Already hit.
+				if (player->pflags & PF_GAMETYPEOVER) // Already hit.
 					player->powers[pw_flashing] = 5;
 			}
 		}
@@ -6819,8 +6940,7 @@ static void P_MovePlayer(player_t *player)
 				P_CheckQuicksand(player);
 			return;
 		}
-
-		if (player->pflags & PF_NIGHTSFALL && P_IsObjectOnGround(player->mo))
+		else if (player->powers[pw_carry] == CR_NIGHTSFALL && P_IsObjectOnGround(player->mo))
 		{
 			if (G_IsSpecialStage(gamemap))
 			{
@@ -6832,7 +6952,7 @@ static void P_MovePlayer(player_t *player)
 			}
 			else if (player->rings > 0)
 				P_DamageMobj(player->mo, NULL, NULL, 1, 0);
-			player->pflags &= ~PF_NIGHTSFALL;
+			player->powers[pw_carry] = CR_NONE;
 		}
 	}
 
@@ -7192,7 +7312,7 @@ static void P_MovePlayer(player_t *player)
 	////////////////////////////
 
 	// If the player isn't on the ground, make sure they aren't in a "starting dash" position.
-	if (!onground)
+	if (!onground && player->powers[pw_carry] != CR_NIGHTSMODE)
 	{
 		player->pflags &= ~PF_STARTDASH;
 		player->dashspeed = 0;
@@ -7209,7 +7329,7 @@ static void P_MovePlayer(player_t *player)
 	P_DoJumpStuff(player, cmd);
 
 	// If you're not spinning, you'd better not be spindashing!
-	if (!(player->pflags & PF_SPINNING))
+	if (!(player->pflags & PF_SPINNING) && player->powers[pw_carry] != CR_NIGHTSMODE)
 		player->pflags &= ~PF_STARTDASH;
 
 	//////////////////
@@ -8390,7 +8510,7 @@ static void P_DeathThink(player_t *player)
 	if (gametype == GT_RACE || gametype == GT_COMPETITION || (gametype == GT_COOP && (multiplayer || netgame)))
 	{
 		// Keep time rolling in race mode
-		if (!(countdown2 && !countdown) && !player->exiting && !(player->pflags & PF_TIMEOVER))
+		if (!(countdown2 && !countdown) && !player->exiting && !(player->pflags & PF_GAMETYPEOVER))
 		{
 			if (gametype == GT_RACE || gametype == GT_COMPETITION)
 			{
@@ -9415,7 +9535,7 @@ void P_PlayerThink(player_t *player)
 			if (netgame && player->mo->health > 0)
 				CONS_Printf(M_GetText("%s ran out of time.\n"), player_names[player-players]);
 
-			player->pflags |= PF_TIMEOVER;
+			player->pflags |= PF_GAMETYPEOVER;
 
 			if (player->powers[pw_carry] == CR_NIGHTSMODE)
 			{
@@ -9614,55 +9734,116 @@ void P_PlayerThink(player_t *player)
 	if (!player->mo)
 		return; // P_MovePlayer removed player->mo.
 
-	if ((player->climbing // stuff where the direction is forced at all times
-	|| (player->pflags & (PF_GLIDING|PF_SLIDING)))
-	|| (player->powers[pw_carry] == CR_NIGHTSMODE)
-	|| P_AnalogMove(player) // keep things synchronised up there, since the camera IS seperate from player motion when that happens
-	|| G_RingSlingerGametype()) // no firing rings in directions your player isn't aiming
-		player->drawangle = player->mo->angle;
-	else if (player->pflags & PF_STARTDASH) // fun spindash experiment
-	{
-		angle_t diff = (player->mo->angle - player->drawangle);
-		if (diff > ANGLE_180)
-			diff = InvAngle(InvAngle(diff)/4);
-		else
-			diff /= 4;
-		player->drawangle += diff;
-	}
-	else if (P_PlayerInPain(player))
-		;
-	else if (player->powers[pw_carry] && player->mo->tracer) // carry
+	// deez New User eXperiences.
 	{
-		switch (player->powers[pw_carry])
+		// Directionchar!
+		// Camera angle stuff.
+		if (player->exiting) // no control, no modification
+			;
+		else if (!(player->pflags & PF_DIRECTIONCHAR)
+		|| (player->climbing // stuff where the direction is forced at all times
+		|| (player->pflags & PF_GLIDING))
+		|| (player->powers[pw_carry] == CR_NIGHTSMODE)
+		|| (P_AnalogMove(player) || twodlevel || player->mo->flags2 & MF2_TWOD) // keep things synchronised up there, since the camera IS seperate from player motion when that happens
+		|| G_RingSlingerGametype()) // no firing rings in directions your player isn't aiming
+			player->drawangle = player->mo->angle;
+		else if (P_PlayerInPain(player))
+			;
+		else if (player->powers[pw_carry] && player->mo->tracer) // carry
 		{
-			case CR_PLAYER:
-				player->drawangle = (player->mo->tracer->player ? player->mo->tracer->player->drawangle : player->mo->tracer->angle);
-				break;
-			/* -- in case we wanted to have the camera freely movable during zoom tube style stuff
-			case CR_ZOOMTUBE:
-			case CR_ROPEHANG:
-				player->drawangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
-				break;
-			*/
-			default:
-				player->drawangle = player->mo->angle;
-				break;
+			switch (player->powers[pw_carry])
+			{
+				case CR_PLAYER:
+					player->drawangle = (player->mo->tracer->player ? player->mo->tracer->player->drawangle : player->mo->tracer->angle);
+					break;
+				/* -- in case we wanted to have the camera freely movable during zoom tube style stuff
+				case CR_ZOOMTUBE:
+				case CR_ROPEHANG:
+					player->drawangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
+					break;
+				*/
+				default:
+					player->drawangle = player->mo->angle;
+					break;
+			}
 		}
-	}
-	else if ((player->pflags & PF_SPINNING) && (abs(player->rmomx) > 5*player->mo->scale || abs(player->rmomy) > 5*player->mo->scale)) // spin force
-		player->drawangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
-	else if (((player->charability2 == CA2_GUNSLINGER || player->charability2 == CA2_MELEE) && player->panim == PA_ABILITY2) || player->pflags & PF_STASIS || player->skidtime)
-		;
-	else if (cmd->forwardmove || cmd->sidemove) // only when you're pressing movement keys
-	{
-		angle_t diff = ((player->mo->angle + R_PointToAngle2(0, 0, cmd->forwardmove<<FRACBITS, -cmd->sidemove<<FRACBITS)) - player->drawangle);
-		if (diff > ANGLE_180)
-			diff = InvAngle(InvAngle(diff)/4);
+		else if ((player->skidtime > (TICRATE/2 - 2) || ((player->pflags & (PF_SPINNING|PF_STARTDASH)) == PF_SPINNING)) && (abs(player->rmomx) > 5*player->mo->scale || abs(player->rmomy) > 5*player->mo->scale)) // spin/skid force
+			player->drawangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
+		else if (((player->charability2 == CA2_GUNSLINGER || player->charability2 == CA2_MELEE) && player->panim == PA_ABILITY2) || player->pflags & PF_STASIS || player->skidtime)
+			;
 		else
-			diff /= 4;
-		player->drawangle += diff;
-	}
+		{
+			angle_t diff;
+			UINT8 factor;
+
+			if (player->pflags & PF_SLIDING)
+			{
+#if 0 // fun hydrocity style horizontal spin
+				if (player->mo->eflags & MFE_TOUCHWATER || player->powers[pw_flashing] > (flashingtics/4)*3)
+				{
+					diff = (player->mo->angle - player->drawangle);
+					factor = 4;
+				}
+				else
+				{
+					diff = factor = 0;
+					player->drawangle += ANGLE_22h;
+				}
+#else
+				diff = (player->mo->angle - player->drawangle);
+				factor = 4;
+#endif
+			}
+			else if (cmd->forwardmove || cmd->sidemove) // only when you're pressing movement keys
+			{
+				diff = ((player->mo->angle + R_PointToAngle2(0, 0, cmd->forwardmove<<FRACBITS, -cmd->sidemove<<FRACBITS)) - player->drawangle);
+				factor = 4;
+			}
+			else if (player->rmomx || player->rmomy)
+				diff = factor = 0;
+			else
+			{
+				diff = (player->mo->angle - player->drawangle);
+				factor = ((player->pflags & PF_STARTDASH) ? 4 : 8);
+			}
 
+			if (diff)
+			{
+				if (diff > ANGLE_180)
+					diff = InvAngle(InvAngle(diff)/factor);
+				else
+					diff /= factor;
+				player->drawangle += diff;
+			}
+		}
+
+		// Autobrake!
+		{
+			boolean currentlyonground = P_IsObjectOnGround(player->mo);
+
+			if (((player->pflags & (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE)) == (PF_AUTOBRAKE|PF_APPLYAUTOBRAKE))
+			&& !(cmd->forwardmove || cmd->sidemove)
+			&& (player->rmomx || player->rmomy))
+			{
+				fixed_t acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration * player->thrustfactor * 20;
+				angle_t moveAngle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
+
+				if (!currentlyonground)
+					acceleration /= 2;
+
+				P_Thrust(player->mo, moveAngle, -acceleration);
+			}
+
+			if (!(player->pflags & PF_AUTOBRAKE)
+			|| player->panim == PA_SPRING
+			|| player->panim == PA_PAIN
+			|| !player->mo->health
+			|| player->pflags & PF_SPINNING)
+				player->pflags &= ~PF_APPLYAUTOBRAKE;
+			else if (currentlyonground)
+				player->pflags |= PF_APPLYAUTOBRAKE;
+		}
+	}
 
 	if (player->powers[pw_pushing])
 		player->powers[pw_pushing]--;
diff --git a/src/y_inter.c b/src/y_inter.c
index a102aa99f6b62daa6b4112cabd1e6d2ef909b614..3b7f082f9cb2b1f4a1afcb8358bfaa5dd9888553 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -475,7 +475,7 @@ void Y_IntermissionDrawer(void)
 						V_DrawRightAlignedString(x+152, y, 0, va("%i", data.match.scores[i]));
 					else if (intertype == int_race)
 					{
-						if (players[data.match.num[i]].pflags & PF_TIMEOVER)
+						if (players[data.match.num[i]].pflags & PF_GAMETYPEOVER)
 							snprintf(strtime, sizeof strtime, "DNF");
 						else
 							snprintf(strtime, sizeof strtime,
@@ -493,7 +493,7 @@ void Y_IntermissionDrawer(void)
 						V_DrawRightAlignedString(x+152+BASEVIDWIDTH/2, y, 0, va("%u", data.match.scores[i]));
 					else if (intertype == int_race)
 					{
-						if (players[data.match.num[i]].pflags & PF_TIMEOVER)
+						if (players[data.match.num[i]].pflags & PF_GAMETYPEOVER)
 							snprintf(strtime, sizeof strtime, "DNF");
 						else
 							snprintf(strtime, sizeof strtime, "%i:%02i.%02i", G_TicsToMinutes(data.match.scores[i], true),
@@ -643,7 +643,7 @@ void Y_IntermissionDrawer(void)
 				// already constrained to 8 characters
 				V_DrawString(x+36, y, V_ALLOWLOWERCASE, data.competition.name[i]);
 
-				if (players[data.competition.num[i]].pflags & PF_TIMEOVER)
+				if (players[data.competition.num[i]].pflags & PF_GAMETYPEOVER)
 					snprintf(sstrtime, sizeof sstrtime, "Time Over");
 				else if (players[data.competition.num[i]].lives <= 0)
 					snprintf(sstrtime, sizeof sstrtime, "Game Over");