diff --git a/src/dehacked.c b/src/dehacked.c
index aafdcf2899fc78513cfa2dc342d2cce0103b0d83..cc8bd44a053200ce5585ccdcb6be89be7bc50ff6 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -6967,6 +6967,8 @@ struct {
 
 	// Frame settings
 	{"FF_FRAMEMASK",FF_FRAMEMASK},
+	{"FF_SPR2ENDSTATE",FF_SPR2ENDSTATE},
+	{"FF_MIDDLESTARTCHANCE",FF_MIDDLESTARTCHANCE},
 	{"FF_ANIMATE",FF_ANIMATE},
 	{"FF_FULLBRIGHT",FF_FULLBRIGHT},
 	{"FF_TRANSMASK",FF_TRANSMASK},
diff --git a/src/info.c b/src/info.c
index 93c32801ec56d1949c28f373aebf016ba34d28bf..badc285458755018d1dfc114e6b81193352ca6e3 100644
--- a/src/info.c
+++ b/src/info.c
@@ -131,8 +131,8 @@ state_t states[NUMSTATES] =
 	// 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_WALK|FF_MIDDLESTARTCHANCE, 4, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_WALK
+	{SPR_PLAY, SPR2_RUN |FF_MIDDLESTARTCHANCE, 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
@@ -153,7 +153,7 @@ state_t states[NUMSTATES] =
 	// 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
+	{SPR_PLAY, SPR2_CLMB|FF_MIDDLESTARTCHANCE, 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
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 373326999c03cc46e62c8e3a13a11d64bccd3104..61049d9e15db49576c0ba6ea186a5258ecb5d2e9 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -329,6 +329,8 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 			}
 		}
 
+		mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
+
 		// Player animations
 		if (st->sprite == SPR_PLAY)
 		{
@@ -336,9 +338,9 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 			boolean noalt = false;
 			UINT8 spr2 = st->frame & FF_FRAMEMASK;
 			UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
-		mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
+			UINT8 numframes;
 
-			while (skin->sprites[spr2].numframes <= 0
+			while (skin && ((numframes = skin->sprites[spr2].numframes) <= 0)
 				&& spr2 != SPR2_STND)
 			{
 				switch(spr2)
@@ -447,17 +449,39 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 					break;
 			}
 
+			if (!skin)
+			{
+				frame = 0;
+				numframes = 0;
+			}
+
 			if (mobj->sprite != SPR_PLAY)
 			{
 				mobj->sprite = SPR_PLAY;
 				frame = 0;
 			}
 			else if (mobj->sprite2 != spr2)
-				frame = 0;
+			{
+				if ((st->frame & FF_MIDDLESTARTCHANCE) && numframes && P_RandomChance(FRACUNIT/2))
+					frame = numframes/2;
+				else
+					frame = 0;
+			}
+
+			if (frame >= numframes)
+			{
+				if (st->frame & FF_SPR2ENDSTATE)
+				{
+					if (st->var1 == S_NULL)
+						frame--; // no frame advancement
+					else
+						return P_SetPlayerMobjState(mobj, st->var1);
+				}
+				else
+					frame = 0;
+			}
 
 			mobj->sprite2 = spr2;
-			if (!mobj->skin || frame >= ((skin_t *)mobj->skin)->sprites[spr2].numframes)
-				frame = 0;
 			mobj->frame = frame|(st->frame&~FF_FRAMEMASK);
 		}
 		// Regular sprites
@@ -465,6 +489,8 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 		{
 			mobj->sprite = st->sprite;
 			mobj->frame = st->frame;
+			if ((st->frame & (FF_ANIMATE|FF_MIDDLESTARTCHANCE)) == (FF_ANIMATE|FF_MIDDLESTARTCHANCE))
+				mobj->frame += (st->var1)/2;
 		}
 
 		// Modified handling.
@@ -536,18 +562,46 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
 		// Player animations
 		if (st->sprite == SPR_PLAY)
 		{
+			skin_t *skin = ((skin_t *)mobj->skin);
 			UINT8 spr2 = st->frame & FF_FRAMEMASK;
 			UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1;
+			UINT8 numframes;
+
+			if (skin)
+				numframes = skin->sprites[spr2].numframes;
+			else
+			{
+				frame = 0;
+				numframes = 0;
+			}
+
 			if (mobj->sprite != SPR_PLAY)
 			{
 				mobj->sprite = SPR_PLAY;
 				frame = 0;
 			}
 			else if (mobj->sprite2 != spr2)
-				frame = 0;
+			{
+				if ((st->frame & FF_MIDDLESTARTCHANCE) && numframes && P_RandomChance(FRACUNIT/2))
+					frame = numframes/2;
+				else
+					frame = 0;
+			}
+
+			if (frame >= numframes)
+			{
+				if (st->frame & FF_SPR2ENDSTATE)
+				{
+					if (st->var1 == S_NULL)
+						frame--; // no frame advancement
+					else
+						return P_SetPlayerMobjState(mobj, st->var1);
+				}
+				else
+					frame = 0;
+			}
+
 			mobj->sprite2 = spr2;
-			if (!mobj->skin || frame >= ((skin_t *)mobj->skin)->sprites[spr2].numframes)
-				frame = 0;
 			mobj->frame = frame|(st->frame&~FF_FRAMEMASK);
 		}
 		// Regular sprites
@@ -555,6 +609,8 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
 		{
 			mobj->sprite = st->sprite;
 			mobj->frame = st->frame;
+			if ((st->frame & (FF_ANIMATE|FF_MIDDLESTARTCHANCE)) == (FF_ANIMATE|FF_MIDDLESTARTCHANCE))
+				mobj->frame += (st->var1)/2;
 		}
 
 		// Modified handling.
diff --git a/src/p_pspr.h b/src/p_pspr.h
index 2fb232e7382149bd12ba97221b7852a14e4b79c4..4117a53f145e17591bed046cd73f0598c669e98a 100644
--- a/src/p_pspr.h
+++ b/src/p_pspr.h
@@ -35,8 +35,12 @@
 #pragma interface
 #endif
 
-/// \brief Frame flags: only the frame number
-#define FF_FRAMEMASK 0x3fff
+/// \brief Frame flags: only the frame number - 0 to 127 (Frames and Sprite2)
+#define FF_FRAMEMASK 0x7f
+/// \brief Frame flags: A change of state at the end of Sprite2 animation
+#define FF_SPR2ENDSTATE 0x1000
+/// \brief Frame flags: 50% of starting in middle of animation (Sprite2 and FF_ANIMATE)
+#define FF_MIDDLESTARTCHANCE 0x2000
 /// \brief Frame flags: Simple stateless animation
 #define FF_ANIMATE 0x4000
 /// \brief Frame flags: frame always appears full bright