diff --git a/src/d_player.h b/src/d_player.h
index b9fcdef75f34af7e533f263d8d5126cfd501683f..e2a1081b00b1dfb954076368d3cb8d5d80b44f49 100644
--- a/src/d_player.h
+++ b/src/d_player.h
@@ -161,11 +161,15 @@ typedef enum
 	// Are animation frames playing?
 	PA_ETC=0,
 	PA_IDLE,
+	PA_EDGE,
 	PA_WALK,
 	PA_RUN,
+	PA_PAIN,
 	PA_ROLL,
+	PA_JUMP,
 	PA_FALL,
-	PA_ABILITY
+	PA_ABILITY,
+	PA_RIDE
 } panim_t;
 
 typedef enum
diff --git a/src/dehacked.c b/src/dehacked.c
index 2ca201b84a1438d308b5a5c718a0a1ae6299bba7..0ba054f07c8be58349ce7373524170633165abfa 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -3750,7 +3750,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_PLAY_RUN",
 	"S_PLAY_PAIN",
 	"S_PLAY_DEAD",
+	"S_PLAY_DRWN",
 	"S_PLAY_SPIN",
+	"S_PLAY_DASH",
 	"S_PLAY_GASP",
 	"S_PLAY_JUMP",
 	"S_PLAY_FALL",
@@ -3770,8 +3772,17 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_PLAY_SUPER_STND",
 	"S_PLAY_SUPER_WALK",
 	"S_PLAY_SUPER_RUN",
-	"S_PLAY_SUPER_EDGE",
 	"S_PLAY_SUPER_PAIN",
+	"S_PLAY_SUPER_STUN",
+	"S_PLAY_SUPER_DEAD",
+	"S_PLAY_SUPER_DRWN",
+	"S_PLAY_SUPER_SPIN",
+	"S_PLAY_SUPER_GASP",
+	"S_PLAY_SUPER_JUMP",
+	"S_PLAY_SUPER_FALL",
+	"S_PLAY_SUPER_EDGE",
+	"S_PLAY_SUPER_RIDE",
+	"S_PLAY_SUPER_FLOAT",
 
 	// SF_SUPER
 	"S_PLAY_SUPERTRANS1",
@@ -7659,11 +7670,15 @@ struct {
 	// Player animation (panim_t)
 	{"PA_ETC",PA_ETC},
 	{"PA_IDLE",PA_IDLE},
+	{"PA_EDGE",PA_EDGE},
 	{"PA_WALK",PA_WALK},
 	{"PA_RUN",PA_RUN},
+	{"PA_PAIN",PA_PAIN},
 	{"PA_ROLL",PA_ROLL},
+	{"PA_JUMP",PA_JUMP},
 	{"PA_FALL",PA_FALL},
 	{"PA_ABILITY",PA_ABILITY},
+	{"PA_RIDE",PA_RIDE},
 
 	// Current weapon
 	{"WEP_AUTO",WEP_AUTO},
diff --git a/src/info.c b/src/info.c
index 7759960920c0534077b1aa1386715760ae347c52..8d7c249adf02e473e336f349d057685d3fe5379a 100644
--- a/src/info.c
+++ b/src/info.c
@@ -64,7 +64,9 @@ char spr2names[NUMPLAYERSPRITES][5] =
 	"RUN_",
 	"PAIN",
 	"DEAD",
+	"DRWN",
 	"SPIN",
+	"DASH",
 	"GASP",
 	"JUMP",
 	"FALL",
@@ -85,8 +87,17 @@ char spr2names[NUMPLAYERSPRITES][5] =
 	"SSTD",
 	"SWLK",
 	"SRUN",
+	"SPAN",
+	"SMSL",
+	"SDTH",
+	"SDRN",
+	"SSPN",
+	"SGSP",
+	"SJMP",
+	"SFAL",
 	"SEDG",
-	"SHIT"
+	"SRID",
+	"SFLT"
 };
 
 // Doesn't work with g++, needs actionf_p1 (don't modify this comment)
@@ -114,32 +125,47 @@ state_t states[NUMSTATES] =
 	{SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL}, // S_THOK
 
 	// Player
-	{SPR_PLAY, SPR2_STND, 105, {NULL},   0, 0, S_PLAY_WAIT}, // S_PLAY_STND
-	{SPR_PLAY, SPR2_WAIT,  16, {NULL},   0, 0, S_PLAY_WAIT}, // S_PLAY_WAIT
-	{SPR_PLAY, SPR2_WALK,   4, {NULL},   0, 0, S_PLAY_WALK}, // S_PLAY_WALK
-	{SPR_PLAY, SPR2_RUN ,   2, {NULL},   0, 0, S_PLAY_RUN},  // S_PLAY_RUN
-	{SPR_PLAY, SPR2_PAIN, 350, {NULL},   0, 0, S_PLAY_FALL}, // S_PLAY_PAIN
-	{SPR_PLAY, SPR2_DEAD,   4, {A_Fall}, 0, 0, S_PLAY_DEAD}, // S_PLAY_DEAD
-	{SPR_PLAY, SPR2_SPIN,   1, {NULL},   0, 0, S_PLAY_SPIN}, // S_PLAY_SPIN
-	{SPR_PLAY, SPR2_GASP,  14, {NULL},   0, 0, S_PLAY_WALK}, // S_PLAY_GASP
-	{SPR_PLAY, SPR2_JUMP,  -1, {NULL},   0, 0, S_PLAY_FALL}, // S_PLAY_JUMP
-	{SPR_PLAY, SPR2_FALL,   2, {NULL},   0, 0, S_PLAY_FALL}, // S_PLAY_FALL
-	{SPR_PLAY, SPR2_EDGE,  12, {NULL},   0, 0, S_PLAY_EDGE}, // S_PLAY_EDGE
-	{SPR_PLAY, SPR2_RIDE,   4, {NULL},   0, 0, S_PLAY_RIDE}, // S_PLAY_RIDE
-
-	{SPR_PLAY, SPR2_FLY ,   2, {NULL},   0, 0, S_PLAY_FLY},  // S_PLAY_FLY
-	{SPR_PLAY, SPR2_TIRE,  12, {NULL},   0, 0, S_PLAY_FLY_TIRED}, // S_PLAY_FLY_TIRED
-
-	{SPR_PLAY, SPR2_GLID,   2, {NULL},   0, 0, S_PLAY_GLIDE}, // S_PLAY_GLIDE
-	{SPR_PLAY, SPR2_CLNG,   6, {NULL},   0, 0, S_PLAY_CLING}, // S_PLAY_CLING
-	{SPR_PLAY, SPR2_CLMB,   5, {NULL},   0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB
-
-	{SPR_PLAY, SPR2_SSTD,   7, {NULL},   0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_STND
-	{SPR_PLAY, SPR2_SWLK,   7, {NULL},   0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_WALK
-	{SPR_PLAY, SPR2_SRUN,   7, {NULL},   0, 0, S_PLAY_SUPER_RUN},  // S_PLAY_SUPER_RUN
-	{SPR_PLAY, SPR2_SEDG,  12, {NULL},   0, 0, S_PLAY_SUPER_EDGE}, // S_PLAY_SUPER_EDGE
-	{SPR_PLAY, SPR2_SHIT,  -1, {NULL},   0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_PAIN
-
+	{SPR_PLAY, SPR2_STND, 105, {NULL}, 0, 0, S_PLAY_WAIT}, // S_PLAY_STND
+	{SPR_PLAY, SPR2_WAIT,  16, {NULL}, 0, 0, S_PLAY_WAIT}, // S_PLAY_WAIT
+	{SPR_PLAY, SPR2_WALK,   4, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_WALK
+	{SPR_PLAY, SPR2_RUN ,   2, {NULL}, 0, 0, S_PLAY_RUN},  // S_PLAY_RUN
+	{SPR_PLAY, SPR2_PAIN, 350, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_PAIN
+	{SPR_PLAY, SPR2_DEAD,   4, {NULL}, 0, 0, S_PLAY_DEAD}, // S_PLAY_DEAD
+	{SPR_PLAY, SPR2_DRWN,   4, {NULL}, 0, 0, S_PLAY_DRWN}, // S_PLAY_DRWN
+	{SPR_PLAY, SPR2_SPIN,   1, {NULL}, 0, 0, S_PLAY_SPIN}, // S_PLAY_SPIN
+	{SPR_PLAY, SPR2_DASH,   2, {NULL}, 0, 0, S_PLAY_DASH}, // S_PLAY_DASH
+	{SPR_PLAY, SPR2_GASP,  14, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_GASP
+	{SPR_PLAY, SPR2_JUMP,   2, {NULL}, 0, 0, S_PLAY_JUMP}, // S_PLAY_JUMP
+	{SPR_PLAY, SPR2_FALL,   2, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_FALL
+	{SPR_PLAY, SPR2_EDGE,  12, {NULL}, 0, 0, S_PLAY_EDGE}, // S_PLAY_EDGE
+	{SPR_PLAY, SPR2_RIDE,   4, {NULL}, 0, 0, S_PLAY_RIDE}, // S_PLAY_RIDE
+
+	// Tails abilities
+	{SPR_PLAY, SPR2_FLY ,   2, {NULL}, 0, 0, S_PLAY_FLY},  // S_PLAY_FLY
+	{SPR_PLAY, SPR2_TIRE,  12, {NULL}, 0, 0, S_PLAY_FLY_TIRED}, // S_PLAY_FLY_TIRED
+
+	// Knuckles abilities
+	{SPR_PLAY, SPR2_GLID,   2, {NULL}, 0, 0, S_PLAY_GLIDE}, // S_PLAY_GLIDE
+	{SPR_PLAY, SPR2_CLNG,   6, {NULL}, 0, 0, S_PLAY_CLING}, // S_PLAY_CLING
+	{SPR_PLAY, SPR2_CLMB,   5, {NULL}, 0, 0, S_PLAY_CLIMB}, // S_PLAY_CLIMB
+
+	// Super Sonic
+	{SPR_PLAY, SPR2_SSTD,   7, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_STND
+	{SPR_PLAY, SPR2_SWLK,   7, {NULL}, 0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_WALK
+	{SPR_PLAY, SPR2_SRUN,   7, {NULL}, 0, 0, S_PLAY_SUPER_RUN},  // S_PLAY_SUPER_RUN
+	{SPR_PLAY, SPR2_SPAN,  -1, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_PAIN
+	{SPR_PLAY, SPR2_SMSL,  -1, {NULL}, 0, 0, S_PLAY_SUPER_STND}, // S_PLAY_SUPER_STUN
+	{SPR_PLAY, SPR2_SDTH,   4, {NULL}, 0, 0, S_PLAY_SUPER_DEAD}, // S_PLAY_SUPER_DEAD
+	{SPR_PLAY, SPR2_SDRN,   4, {NULL}, 0, 0, S_PLAY_SUPER_DRWN}, // S_PLAY_SUPER_DRWN
+	{SPR_PLAY, SPR2_SSPN,   1, {NULL}, 0, 0, S_PLAY_SUPER_SPIN}, // S_PLAY_SUPER_SPIN
+	{SPR_PLAY, SPR2_SGSP,  14, {NULL}, 0, 0, S_PLAY_SUPER_WALK}, // S_PLAY_SUPER_GASP
+	{SPR_PLAY, SPR2_SJMP,   2, {NULL}, 0, 0, S_PLAY_SUPER_JUMP}, // S_PLAY_SUPER_JUMP
+	{SPR_PLAY, SPR2_SFAL,   2, {NULL}, 0, 0, S_PLAY_SUPER_FALL}, // S_PLAY_SUPER_FALL
+	{SPR_PLAY, SPR2_SEDG,  12, {NULL}, 0, 0, S_PLAY_SUPER_EDGE}, // S_PLAY_SUPER_EDGE
+	{SPR_PLAY, SPR2_SRID,   4, {NULL}, 0, 0, S_PLAY_SUPER_RIDE}, // S_PLAY_SUPER_RIDE
+	{SPR_PLAY, SPR2_SFLT,   7, {NULL}, 0, 0, S_PLAY_SUPER_FLOAT}, // S_PLAY_SUPER_FLOAT
+
+	// Transforming into Super
 	{SPR_PLAY, SPR2_TRNS,                4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS2}, // S_PLAY_SUPER_TRANS
 	{SPR_PLAY, SPR2_TRNS,                4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS3}, // S_PLAY_SUPER_TRANS2
 	{SPR_PLAY, SPR2_TRNS|FF_FULLBRIGHT,  4, {NULL}, 0, 0, S_PLAY_SUPER_TRANS4}, // S_PLAY_SUPER_TRANS3
@@ -3130,8 +3156,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_PLAY_SPIN,    // missilestate
-		S_PLAY_DEAD,     // deathstate
-		S_NULL,         // xdeathstate
+		S_PLAY_DEAD,    // deathstate
+		S_PLAY_DRWN,    // xdeathstate
 		sfx_None,       // deathsound
 		1,              // speed
 		16*FRACUNIT,    // radius
diff --git a/src/info.h b/src/info.h
index 44a3dd012bb83fcab932329d3a2eebb935f482ae..e313526b92b18950114c1996c170cb56d7822d31 100644
--- a/src/info.h
+++ b/src/info.h
@@ -583,7 +583,9 @@ enum playersprite
 	SPR2_RUN ,
 	SPR2_PAIN,
 	SPR2_DEAD,
+	SPR2_DRWN,
 	SPR2_SPIN,
+	SPR2_DASH,
 	SPR2_GASP,
 	SPR2_JUMP,
 	SPR2_FALL,
@@ -604,8 +606,17 @@ enum playersprite
 	SPR2_SSTD,
 	SPR2_SWLK,
 	SPR2_SRUN,
+	SPR2_SPAN,
+	SPR2_SMSL,
+	SPR2_SDTH,
+	SPR2_SDRN,
+	SPR2_SSPN,
+	SPR2_SGSP,
+	SPR2_SJMP,
+	SPR2_SFAL,
 	SPR2_SEDG,
-	SPR2_SHIT,
+	SPR2_SRID,
+	SPR2_SFLT,
 
 	NUMPLAYERSPRITES
 };
@@ -634,7 +645,9 @@ typedef enum state
 	S_PLAY_RUN,
 	S_PLAY_PAIN,
 	S_PLAY_DEAD,
+	S_PLAY_DRWN,
 	S_PLAY_SPIN,
+	S_PLAY_DASH,
 	S_PLAY_GASP,
 	S_PLAY_JUMP,
 	S_PLAY_FALL,
@@ -654,8 +667,17 @@ typedef enum state
 	S_PLAY_SUPER_STND,
 	S_PLAY_SUPER_WALK,
 	S_PLAY_SUPER_RUN,
-	S_PLAY_SUPER_EDGE,
 	S_PLAY_SUPER_PAIN,
+	S_PLAY_SUPER_STUN,
+	S_PLAY_SUPER_DEAD,
+	S_PLAY_SUPER_DRWN,
+	S_PLAY_SUPER_SPIN,
+	S_PLAY_SUPER_GASP,
+	S_PLAY_SUPER_JUMP,
+	S_PLAY_SUPER_FALL,
+	S_PLAY_SUPER_EDGE,
+	S_PLAY_SUPER_RIDE,
+	S_PLAY_SUPER_FLOAT,
 
 	// SF_SUPER
 	S_PLAY_SUPER_TRANS,
diff --git a/src/p_inter.c b/src/p_inter.c
index 244d736ed3d2a9af6ae1ce711fed44e9fca2b443..f65a1127770d8a42a938d88aa75363f252745d70 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -1953,7 +1953,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 	{
 		target->flags &= ~(MF_SOLID|MF_SHOOTABLE); // does not block
 		P_UnsetThingPosition(target);
-		target->flags |= MF_NOBLOCKMAP;
+		target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY;
 		P_SetThingPosition(target);
 
 		if (!target->player->bot && !G_IsSpecialStage(gamemap)
@@ -2289,7 +2289,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 		}
 	}
 	else if (target->player)
-		P_SetPlayerMobjState(target, target->info->deathstate);
+	{
+		if (damagetype == DMG_DROWNED || damagetype == DMG_SPACEDROWN)
+			P_SetPlayerMobjState(target, target->info->xdeathstate);
+		else
+			P_SetPlayerMobjState(target, target->info->deathstate);
+	}
 	else
 #ifdef DEBUG_NULL_DEATHSTATE
 		P_SetMobjState(target, S_NULL);
@@ -2582,7 +2587,7 @@ static inline void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *so
 	P_InstaThrust(player->mo, ang, fallbackspeed);
 
 	if (player->charflags & SF_SUPERANIMS)
-		P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_PAIN);
+		P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_STUN);
 	else
 		P_SetPlayerMobjState(player->mo, player->mo->info->painstate);
 
diff --git a/src/p_map.c b/src/p_map.c
index f80578868d346bff7793ff1480145bddcc9bc664..d1b3c7b0b7ae15c04e89d39fac6dd5750edff164 100644
--- a/src/p_map.c
+++ b/src/p_map.c
@@ -1853,7 +1853,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
 
 				// Don't 'step up' while springing,
 				// Only step up "if needed".
-				if (thing->state-states == S_PLAY_JUMP
+				if (thing->player->panim == PA_JUMP
 				&& P_MobjFlip(thing)*thing->momz > FixedMul(FRACUNIT, thing->scale))
 					maxstep = 0;
 			}
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 05b409085d2aad55f578086b4c9bb28bb790c6cd..8ea71d6c7ca9a1fecec9405390ff118cf2d19a83 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -142,24 +142,29 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 		{
 		case S_PLAY_STND:
 		case S_PLAY_WAIT:
-		case S_PLAY_GASP:
-			P_SetPlayerMobjState(mobj, S_PLAY_SUPER_STND);
-			return true;
-		case S_PLAY_FALL:
-		case S_PLAY_JUMP:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_STND);
 		case S_PLAY_WALK:
-			P_SetPlayerMobjState(mobj, S_PLAY_SUPER_WALK);
-			return true;
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_WALK);
 		case S_PLAY_RUN:
-			P_SetPlayerMobjState(mobj, S_PLAY_SUPER_RUN);
-			return true;
-		case S_PLAY_EDGE:
-			P_SetPlayerMobjState(mobj, S_PLAY_SUPER_EDGE);
-			return true;
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_RUN);
+		case S_PLAY_PAIN:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_PAIN);
+		case S_PLAY_DEAD:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_DEAD);
+		case S_PLAY_DRWN:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_DRWN);
 		case S_PLAY_SPIN:
 			if (!(player->charflags & SF_SUPERSPIN))
 				return true;
-			break;
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_SPIN);
+		case S_PLAY_GASP:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_GASP);
+		case S_PLAY_JUMP:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_JUMP);
+		case S_PLAY_FALL:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_FALL);
+		case S_PLAY_EDGE:
+			return P_SetPlayerMobjState(mobj, S_PLAY_SUPER_EDGE);
 		default:
 			break;
 		}
@@ -178,30 +183,48 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 	{
 	case S_PLAY_STND:
 	case S_PLAY_WAIT:
-	case S_PLAY_EDGE:
-	case S_PLAY_RIDE:
 	case S_PLAY_SUPER_STND:
-	case S_PLAY_SUPER_EDGE:
 		player->panim = PA_IDLE;
 		break;
+	case S_PLAY_EDGE:
+	case S_PLAY_SUPER_EDGE:
+		player->panim = PA_EDGE;
+		break;
 	case S_PLAY_WALK:
 	case S_PLAY_SUPER_WALK:
+	case S_PLAY_SUPER_FLOAT:
 		player->panim = PA_WALK;
 		break;
 	case S_PLAY_RUN:
 	case S_PLAY_SUPER_RUN:
 		player->panim = PA_RUN;
 		break;
+	case S_PLAY_PAIN:
+	case S_PLAY_SUPER_PAIN:
+	case S_PLAY_SUPER_STUN:
+		player->panim = PA_PAIN;
+		break;
 	case S_PLAY_SPIN:
+	case S_PLAY_DASH:
+	case S_PLAY_SUPER_SPIN:
 		player->panim = PA_ROLL;
 		break;
+	case S_PLAY_JUMP:
+	case S_PLAY_SUPER_JUMP:
+		player->panim = PA_JUMP;
+		break;
 	case S_PLAY_FALL:
+	case S_PLAY_SUPER_FALL:
 		player->panim = PA_FALL;
 		break;
 	case S_PLAY_FLY:
 	case S_PLAY_GLIDE:
 		player->panim = PA_ABILITY;
 		break;
+	case S_PLAY_RIDE:
+	case S_PLAY_SUPER_RIDE:
+		player->panim = PA_RIDE;
+		break;
 	default:
 		player->panim = PA_ETC;
 		break;
@@ -272,8 +295,109 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 		// Player animations
 		if (st->sprite == SPR_PLAY)
 		{
+			boolean noalt = false;
 			UINT8 spr2 = st->frame & FF_FRAMEMASK;
 			UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
+
+			while (((skin_t *)mobj->skin)->sprites[spr2].numframes <= 0
+				&& spr2 != SPR2_STND)
+			{
+				switch(spr2)
+				{
+				case SPR2_RUN:
+					spr2 = SPR2_WALK;
+					break;
+				case SPR2_DRWN:
+					spr2 = SPR2_DEAD;
+					break;
+				case SPR2_DASH:
+					spr2 = SPR2_SPIN;
+					break;
+				case SPR2_GASP:
+					spr2 = SPR2_JUMP;
+					break;
+				case SPR2_JUMP:
+					spr2 = SPR2_FALL;
+					break;
+				case SPR2_FALL:
+					spr2 = SPR2_WALK;
+					break;
+				case SPR2_RIDE:
+					spr2 = SPR2_FALL;
+					break;
+
+				case SPR2_FLY:
+					spr2 = SPR2_JUMP;
+					break;
+				case SPR2_TIRE:
+					spr2 = SPR2_FLY;
+					break;
+
+				case SPR2_GLID:
+					spr2 = SPR2_FLY;
+					break;
+				case SPR2_CLMB:
+					spr2 = SPR2_WALK;
+					break;
+				case SPR2_CLNG:
+					spr2 = SPR2_CLMB;
+					break;
+
+				case SPR2_SIGN:
+				case SPR2_LIFE:
+					noalt = true;
+					break;
+
+				// Super sprites fallback to regular sprites
+				case SPR2_SWLK:
+					spr2 = SPR2_WALK;
+					break;
+				case SPR2_SRUN:
+					spr2 = SPR2_RUN;
+					break;
+				case SPR2_SPAN:
+					spr2 = SPR2_PAIN;
+					break;
+				case SPR2_SMSL:
+					spr2 = SPR2_SPAN;
+					break;
+				case SPR2_SDTH:
+					spr2 = SPR2_DEAD;
+					break;
+				case SPR2_SDRN:
+					spr2 = SPR2_DRWN;
+					break;
+				case SPR2_SSPN:
+					spr2 = SPR2_SPIN;
+					break;
+				case SPR2_SGSP:
+					spr2 = SPR2_GASP;
+					break;
+				case SPR2_SJMP:
+					spr2 = SPR2_JUMP;
+					break;
+				case SPR2_SFAL:
+					spr2 = SPR2_FALL;
+					break;
+				case SPR2_SEDG:
+					spr2 = SPR2_EDGE;
+					break;
+				case SPR2_SRID:
+					spr2 = SPR2_RIDE;
+					break;
+				case SPR2_SFLT:
+					spr2 = SPR2_SWLK;
+					break;
+
+				// Dunno? Just go to standing then.
+				default:
+					spr2 = SPR2_STND;
+					break;
+				}
+				if (noalt)
+					break;
+			}
+
 			if (mobj->sprite != SPR_PLAY)
 			{
 				mobj->sprite = SPR_PLAY;
@@ -281,6 +405,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 			}
 			else if (mobj->sprite2 != spr2)
 				frame = 0;
+
 			mobj->sprite2 = spr2;
 			if (!mobj->skin || frame >= ((skin_t *)mobj->skin)->sprites[spr2].numframes)
 				frame = 0;
@@ -2056,7 +2181,7 @@ static void P_PlayerZMovement(mobj_t *mo)
 			goto nightsdone;
 		}
 		// Get up if you fell.
-		if (mo->state == &states[mo->info->painstate] || mo->state-states == S_PLAY_SUPER_PAIN)
+		if (mo->player->panim == PA_PAIN)
 			P_SetPlayerMobjState(mo, S_PLAY_STND);
 
 		if (P_MobjFlip(mo)*mo->momz < 0) // falling
diff --git a/src/p_user.c b/src/p_user.c
index e75d81a950795d8b7bffc9079b2220fca2549114..34c5b5dec19cb23a9e4eb796365e059be3caa4fd 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -3078,10 +3078,10 @@ teeterdone:
 	}
 	if (teeter)
 	{
-		if (player->panim == PA_IDLE && player->mo->state-states != S_PLAY_EDGE)
+		if (player->panim == PA_IDLE)
 			P_SetPlayerMobjState(player->mo, S_PLAY_EDGE);
 	}
-	else if (checkedforteeter && (player->mo->state-states == S_PLAY_EDGE || player->mo->state-states == S_PLAY_SUPER_EDGE))
+	else if (checkedforteeter && player->panim == PA_EDGE)
 		P_SetPlayerMobjState(player->mo, S_PLAY_STND);
 }
 
@@ -3436,14 +3436,35 @@ static void P_DoSuperStuff(player_t *player)
 
 			if (player->mo->health > 0)
 			{
-				if ((player->pflags & PF_JUMPED) || (player->pflags & PF_SPINNING))
+				if ((player->pflags & PF_JUMPED || player->pflags & PF_SPINNING)
+				&& player->mo->state-states != S_PLAY_DASH)
 					P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
-				else if (player->panim == PA_RUN)
-					P_SetPlayerMobjState(player->mo, S_PLAY_RUN);
-				else if (player->panim == PA_WALK)
-					P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
-				else
+				else switch (player->mo->state-states)
+				{
+				default:
 					P_SetPlayerMobjState(player->mo, S_PLAY_STND);
+					break;
+				case S_PLAY_DASH:
+					break;
+				case S_PLAY_SUPER_WALK:
+					P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
+					break;
+				case S_PLAY_SUPER_RUN:
+					P_SetPlayerMobjState(player->mo, S_PLAY_RUN);
+					break;
+				case S_PLAY_SUPER_PAIN:
+					P_SetPlayerMobjState(player->mo, S_PLAY_PAIN);
+					break;
+				case S_PLAY_SUPER_JUMP:
+					P_SetPlayerMobjState(player->mo, S_PLAY_JUMP);
+					break;
+				case S_PLAY_SUPER_FALL:
+					P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
+					break;
+				case S_PLAY_SUPER_RIDE:
+					P_SetPlayerMobjState(player->mo, S_PLAY_RIDE);
+					break;
+				}
 
 				if (!player->exiting)
 				{
@@ -3690,7 +3711,7 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
 			player->pflags |= PF_STARTDASH|PF_SPINNING;
 			player->dashspeed = FixedMul(FRACUNIT, player->mo->scale);
 			player->dashtime = 0;
-			P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
+			P_SetPlayerMobjState(player->mo, S_PLAY_DASH);
 			player->pflags |= PF_USEDOWN;
 		}
 		else if ((cmd->buttons & BT_USE) && (player->pflags & PF_STARTDASH))
@@ -3703,9 +3724,12 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
 					S_StartSound(player->mo, sfx_spndsh); // Make the rev sound!
 
 				// Now spawn the color thok circle.
-				P_SpawnSpinMobj(player, player->revitem);
-				if (demorecording)
-					G_GhostAddRev();
+				if (player->mo->sprite2 != SPR2_DASH)
+				{
+					P_SpawnSpinMobj(player, player->revitem);
+					if (demorecording)
+						G_GhostAddRev();
+				}
 			}
 		}
 		// If not moving up or down, and travelling faster than a speed of four while not holding
@@ -3747,6 +3771,7 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
 		player->pflags &= ~PF_STARTDASH;
 		if (!((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE))
 		{
+			P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
 			P_InstaThrust(player->mo, player->mo->angle, player->dashspeed); // catapult forward ho!!
 			if (!player->spectator)
 				S_StartSound(player->mo, sfx_zoom);
@@ -3754,7 +3779,9 @@ static void P_DoSpinDash(player_t *player, ticcmd_t *cmd)
 		player->dashspeed = 0;
 	}
 
-	if (onground && (player->pflags & PF_SPINNING) && !(player->panim == PA_ROLL))
+	if (onground && player->pflags & PF_STARTDASH && player->mo->state-states != S_PLAY_DASH)
+		P_SetPlayerMobjState(player->mo, S_PLAY_DASH);
+	else if (onground && player->pflags & PF_SPINNING && !(player->panim == PA_ROLL))
 		P_SetPlayerMobjState(player->mo, S_PLAY_SPIN);
 }
 
@@ -6422,13 +6449,17 @@ static void P_MovePlayer(player_t *player)
 	// MOVEMENT ANIMATIONS //
 	/////////////////////////
 
-	if ((cmd->forwardmove != 0 || cmd->sidemove != 0) || (player->powers[pw_super] && player->mo->z > player->mo->floorz))
+	if ((cmd->forwardmove != 0 || cmd->sidemove != 0) || (player->powers[pw_super] && !onground))
 	{
 		// If the player is moving fast enough,
 		// break into a run!
 		if (player->speed >= runspd && player->panim == PA_WALK && !player->skidtime && (onground || player->powers[pw_super]))
 			P_SetPlayerMobjState (player->mo, S_PLAY_RUN);
 
+		// Super floating at slow speeds has its own special animation.
+		else if (player->powers[pw_super] && player->panim == PA_IDLE && !onground)
+			P_SetPlayerMobjState (player->mo, S_PLAY_SUPER_FLOAT);
+
 		// Otherwise, just walk.
 		else if ((player->rmomx || player->rmomy) && player->panim == PA_IDLE)
 			P_SetPlayerMobjState (player->mo, S_PLAY_WALK);
@@ -6437,13 +6468,18 @@ static void P_MovePlayer(player_t *player)
 	// If your running animation is playing, and you're
 	// going too slow, switch back to the walking frames.
 	if (player->panim == PA_RUN && player->speed < runspd)
-		P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
+	{
+		if (!onground && player->powers[pw_super])
+			P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_FLOAT);
+		else
+			P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
+	}
 
 	// If Springing, but travelling DOWNWARD, change back!
-	if (player->mo->state == &states[S_PLAY_JUMP] && P_MobjFlip(player->mo)*player->mo->momz < 0)
+	if (player->panim == PA_JUMP && P_MobjFlip(player->mo)*player->mo->momz < 0)
 		P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
 	// If Springing but on the ground, change back!
-	else if (onground && (player->mo->state == &states[S_PLAY_JUMP] || player->panim == PA_FALL || player->mo->state == &states[S_PLAY_RIDE]) && !player->mo->momz)
+	else if (onground && (player->panim == PA_JUMP || player->panim == PA_FALL || player->panim == PA_RIDE) && !player->mo->momz)
 		P_SetPlayerMobjState(player->mo, S_PLAY_STND);
 
 	// If you are stopped and are still walking, stand still!
@@ -6808,8 +6844,8 @@ static void P_MovePlayer(player_t *player)
 			if (player->charflags & SF_SUPER && player->powers[pw_super] && player->speed > FixedMul(5<<FRACBITS, player->mo->scale)
 			&& P_MobjFlip(player->mo)*player->mo->momz <= 0)
 			{
-				if (player->panim == PA_ROLL || player->mo->state-states == S_PLAY_PAIN)
-					P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_WALK);
+				if (player->panim == PA_ROLL || player->mo->state-states == S_PLAY_PAIN || player->panim == PA_WALK)
+					P_SetPlayerMobjState(player->mo, S_PLAY_SUPER_FLOAT);
 
 				player->mo->momz = 0;
 				player->pflags &= ~PF_SPINNING;
@@ -6868,7 +6904,7 @@ static void P_MovePlayer(player_t *player)
 	}
 
 	// Make sure you're not teetering when you shouldn't be.
-	if ((player->mo->state-states == S_PLAY_EDGE || player->mo->state-states == S_PLAY_SUPER_EDGE)
+	if (player->panim == PA_EDGE
 	&& (player->mo->momx || player->mo->momy || player->mo->momz))
 		P_SetPlayerMobjState(player->mo, S_PLAY_STND);