diff --git a/src/dehacked.c b/src/dehacked.c
index 78a9912a456f999bb4deba6f5adf741238a8f5fa..c25e9e1fa8cc0de3cf4bc527ba1395797648a495 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1706,7 +1706,7 @@ static actionpointer_t actionpointers[] =
 	{{A_HoodFire},               "A_HOODFIRE"},
 	{{A_HoodThink},              "A_HOODTHINK"},
 	{{A_HoodFall},               "A_HOODFALL"},
-	{{A_ArrowCheck},             "A_ARROWCHECK"},
+	{{A_ArrowBonks},             "A_ARROWBONKS"},
 	{{A_SnailerThink},           "A_SNAILERTHINK"},
 	{{A_SharpChase},             "A_SHARPCHASE"},
 	{{A_SharpSpin},              "A_SHARPSPIN"},
@@ -4709,8 +4709,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 
 	// Arrow
 	"S_ARROW",
-	"S_ARROWUP",
-	"S_ARROWDOWN",
+	"S_TEMPSHI",
+	"S_ARROWBONK",
 
 	// Trapgoyle Demon fire
 	"S_DEMONFIRE1",
diff --git a/src/info.c b/src/info.c
index 01edc0eb2e9694cb47484aae93ae1650033be17a..e791c7728eaaa1825d9ac2a533bb790549b0be93 100644
--- a/src/info.c
+++ b/src/info.c
@@ -1933,9 +1933,9 @@ state_t states[NUMSTATES] =
 
 	{SPR_CBLL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CANNONBALL1
 
-	{SPR_AROW, 0, 1, {A_ArrowCheck}, 0, 0, S_ARROW},     // S_ARROW
-	{SPR_AROW, 1, 1, {A_ArrowCheck}, 0, 0, S_ARROWUP},   // S_ARROWUP
-	{SPR_AROW, 2, 1, {A_ArrowCheck}, 0, 0, S_ARROWDOWN}, // S_ARROWDOWN
+	{SPR_AROW, 0, -1, {NULL}, 0, 0, S_NULL}, // S_ARROW
+	{SPR_ESHI, 0, TICRATE/2, {NULL}, 0, 0, S_NULL}, // S_TEMPSHI
+	{SPR_AROW, FF_ANIMATE, TICRATE, {A_ArrowBonks}, 7, 2, S_NULL}, // S_ARROWBONK
 
 	{SPR_CFIR, FF_FULLBRIGHT,   2, {NULL}, 0, 0, S_DEMONFIRE2}, // S_DEMONFIRE1
 	{SPR_CFIR, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_DEMONFIRE3}, // S_DEMONFIRE2
@@ -2138,8 +2138,8 @@ state_t states[NUMSTATES] =
 
 	{SPR_CBBS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FACESTABBERSTATUE
 
-	{SPR_CBBS, 0,  5,        {A_Look},   768*FRACUNIT, 0, S_SUSPICIOUSFACESTABBERSTATUE_WAIT},   // S_SUSPICIOUSFACESTABBERSTATUE_WAIT
-	{SPR_CBBS, 0, 23,          {NULL},              0, 0, S_SUSPICIOUSFACESTABBERSTATUE_BURST2}, // S_SUSPICIOUSFACESTABBERSTATUE_BURST1
+	{SPR_CBBS, 0, 5, {A_Look}, 768*FRACUNIT, 0, S_SUSPICIOUSFACESTABBERSTATUE_WAIT},   // S_SUSPICIOUSFACESTABBERSTATUE_WAIT
+	{SPR_CBBS, FF_ANIMATE, 23, {NULL},    6, 1, S_SUSPICIOUSFACESTABBERSTATUE_BURST2}, // S_SUSPICIOUSFACESTABBERSTATUE_BURST1
 	{SPR_NULL, 0, 40, {A_StatueBurst}, MT_FACESTABBER, S_FACESTABBER_CHARGE2, S_NULL}, // S_SUSPICIOUSFACESTABBERSTATUE_BURST2
 
 	// Big Tumbleweed
@@ -4260,7 +4260,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // xdeathstate
 		sfx_cybdth,     // deathsound
 		3,              // speed
-		36*FRACUNIT,    // radius
+		32*FRACUNIT,    // radius
 		72*FRACUNIT,    // height
 		0,              // display offset
 		100,            // mass
@@ -4287,7 +4287,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,          // xdeathstate
 		sfx_None,        // deathsound
 		0,               // speed
-		36*FRACUNIT,     // radius
+		32*FRACUNIT,     // radius
 		72*FRACUNIT,     // height
 		0,               // display offset
 		DMG_SPIKE,       // mass
@@ -4337,7 +4337,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_s3k7b,       // painsound
 		S_NULL,          // meleestate
 		S_NULL,          // missilestate
-		S_XPLD1,         // deathstate
+		S_TEMPSHI,       // deathstate
 		S_NULL,          // xdeathstate
 		sfx_wbreak,      // deathsound
 		3,               // speed
@@ -8625,18 +8625,18 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		sfx_None,       // painsound
 		S_NULL,         // meleestate
 		S_NULL,         // missilestate
-		S_NULL,         // deathstate
-		S_ARROWDOWN,    // xdeathstate
+		S_ARROWBONK,    // deathstate
+		S_NULL,         // xdeathstate
 		sfx_s3k52,      // deathsound
 		16*FRACUNIT,    // speed
 		4*FRACUNIT,     // radius
 		8*FRACUNIT,     // height
 		0,              // display offset
-		0,              // mass
+		DMG_SPIKE,      // mass
 		1,              // damage
 		sfx_s3k51,      // activesound
 		MF_NOBLOCKMAP|MF_MISSILE, // flags
-		S_ARROWUP       // raisestate
+		S_NULL          // raisestate
 	},
 
 	{           // MT_DEMONFIRE
@@ -10519,7 +10519,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // xdeathstate
 		sfx_None,       // deathsound
 		0,              // speed
-		36*FRACUNIT,    // radius
+		32*FRACUNIT,    // radius
 		72*FRACUNIT,    // height
 		0,              // display offset
 		100,            // mass
@@ -10546,7 +10546,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // xdeathstate
 		sfx_None,       // deathsound
 		0,              // speed
-		36*FRACUNIT,    // radius
+		32*FRACUNIT,    // radius
 		72*FRACUNIT,    // height
 		0,              // display offset
 		100,            // mass
diff --git a/src/info.h b/src/info.h
index 8134a1a49abb16517e688e6524a979964e43eb9f..5f84b22d42ec645d7d4529c14e4082ca21b61291 100644
--- a/src/info.h
+++ b/src/info.h
@@ -105,7 +105,7 @@ void A_CheckBuddy();
 void A_HoodFire();
 void A_HoodThink();
 void A_HoodFall();
-void A_ArrowCheck();
+void A_ArrowBonks();
 void A_SnailerThink();
 void A_SharpChase();
 void A_SharpSpin();
@@ -2061,8 +2061,8 @@ typedef enum state
 
 	// Arrow
 	S_ARROW,
-	S_ARROWUP,
-	S_ARROWDOWN,
+	S_TEMPSHI,
+	S_ARROWBONK,
 
 	// Trapgoyle Demon fire
 	S_DEMONFIRE1,
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 8a09df286aa741f5d11219737e4d921eafdd6416..2c55210b7680c3e07e51f5a39a7572d91ce290ef 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -66,7 +66,7 @@ void A_CheckBuddy(mobj_t *actor);
 void A_HoodFire(mobj_t *actor);
 void A_HoodThink(mobj_t *actor);
 void A_HoodFall(mobj_t *actor);
-void A_ArrowCheck(mobj_t *actor);
+void A_ArrowBonks(mobj_t *actor);
 void A_SnailerThink(mobj_t *actor);
 void A_SharpChase(mobj_t *actor);
 void A_SharpSpin(mobj_t *actor);
@@ -1741,48 +1741,29 @@ void A_HoodFall(mobj_t *actor)
 	P_SetMobjState(actor, actor->info->seestate);
 }
 
-// Function: A_ArrowCheck
+// Function: A_ArrowBonks
 //
-// Description: Checks arrow direction and adjusts sprite accordingly
+// Description: Arrow momentum setting on collision
 //
 // var1 = unused
 // var2 = unused
 //
-void A_ArrowCheck(mobj_t *actor)
+void A_ArrowBonks(mobj_t *actor)
 {
-	fixed_t x,y,z;
-	angle_t angle;
-	fixed_t dist;
-
 #ifdef HAVE_BLUA
-	if (LUA_CallAction("A_ArrowCheck", actor))
+	if (LUA_CallAction("A_ArrowBonks", actor))
 		return;
 #endif
 
-	// Movement vector
-	x = actor->momx;
-	y = actor->momy;
-	z = actor->momz;
-
-	// Calculate the angle of movement.
-	/*
-	       Z
-	     / |
-	   /   |
-	 /     |
-	0------dist(X,Y)
-	*/
-
-	dist = P_AproxDistance(x, y);
+	if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)
+		|| (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz))
+		actor->angle += ANGLE_180;
 
-	angle = R_PointToAngle2(0, 0, dist, z);
+	P_SetObjectMomZ(actor, 8*actor->scale, false);
+	P_InstaThrust(actor, actor->angle, -6*actor->scale);
 
-	if (angle > ANG20 && angle <= ANGLE_180)
-		P_SetMobjStateNF(actor, actor->info->raisestate);
-	else if (angle < ANG340 && angle > ANGLE_180)
-		P_SetMobjStateNF(actor, actor->info->xdeathstate);
-	else
-		P_SetMobjStateNF(actor, actor->info->spawnstate);
+	actor->flags = (actor->flags|MF_NOCLIPHEIGHT) & ~MF_NOGRAVITY;
+	actor->z += P_MobjFlip(actor);
 }
 
 // Function: A_SnailerThink
@@ -10966,14 +10947,13 @@ void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fi
 //
 void A_FlickyFly(mobj_t *actor)
 {
-	// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyFly instead.
-	//INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
 #ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FlickyFly", actor))
 		return;
 #endif
-	P_InternalFlickyFly(actor, var1, var2,
+	P_InternalFlickyFly(actor, locvar1, locvar2,
 	FINECOSINE((((actor->fuse % 36) * ANG10) >> ANGLETOFINESHIFT) & FINEMASK)
 	);
 }
@@ -10987,14 +10967,13 @@ void A_FlickyFly(mobj_t *actor)
 //
 void A_FlickySoar(mobj_t *actor)
 {
-	// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyFly instead.
-	//INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
 #ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FlickySoar", actor))
 		return;
 #endif
-	P_InternalFlickyFly(actor, var1, var2,
+	P_InternalFlickyFly(actor, locvar1, locvar2,
 	2*(FRACUNIT/2 - abs(FINECOSINE((((actor->fuse % 144) * 5*ANG1/2) >> ANGLETOFINESHIFT) & FINEMASK)))
 	);
 
@@ -11059,14 +11038,13 @@ void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angl
 //
 void A_FlickyHop(mobj_t *actor)
 {
-	// We're not setting up locvars here - it passes var1 and var2 through to P_InternalFlickyHop instead.
-	//INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
 #ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FlickyHop", actor))
 		return;
 #endif
-	P_InternalFlickyHop(actor, var1, var2, actor->angle);
+	P_InternalFlickyHop(actor, locvar1, locvar2, actor->angle);
 }
 
 // Function: A_FlickyFlounder
@@ -11149,13 +11127,14 @@ void A_FlickyHeightCheck(mobj_t *actor)
 //
 void A_FlickyFlutter(mobj_t *actor)
 {
-	// We're not setting up locvars here - it passes var1 and var2 through to A_FlickyCheck instead.
-	//INT32 locvar1 = var1;
-	//INT32 locvar2 = var2;
+	INT32 locvar1 = var1;
+	INT32 locvar2 = var2;
 #ifdef HAVE_BLUA
 	if (LUA_CallAction("A_FlickyFlutter", actor))
 		return;
 #endif
+	var1 = locvar1;
+	var2 = locvar2;
 	A_FlickyCheck(actor);
 
 	var1 = ANG30;
diff --git a/src/p_inter.c b/src/p_inter.c
index 5161f4cc3c41e571fbd163a0fe9b79d42ae6713e..fed459d6a923e45d0b03294507f20321a97fe6e2 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -1430,13 +1430,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
 					// experimental bounce
 					if (special->target)
 						special->target->extravalue1 = -special->target->info->speed;
-					return;
 				}
-				else if (((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING))
-						|| ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
-						|| ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0))
-						|| (player->pflags & (PF_SPINNING|PF_GLIDING))
-						|| player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object?
+				else
 				{
 					// Shatter the shield!
 					toucher->momx = -toucher->momx/2;
@@ -2358,6 +2353,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
 			}
 			break;
 
+		case MT_EGGSHIELD:
+			P_SetObjectMomZ(target, 4*target->scale, false);
+			P_InstaThrust(target, target->angle, 3*target->scale);
+			target->flags = (target->flags|MF_NOCLIPHEIGHT) & ~MF_NOGRAVITY;
+			break;
+
 		case MT_EGGMOBILE3:
 			{
 				thinker_t *th;
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 3b6ea394c738740baac82d4a0f8d8e997c9f8e57..dbf5f5880a63fdc901247654bfc0e05e710d6e35 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -7238,6 +7238,9 @@ void P_MobjThinker(mobj_t *mobj)
 				return;
 			}
 			break;
+		case MT_EGGSHIELD:
+			mobj->flags2 ^= MF2_DONTDRAW;
+			break;
 		case MT_EGGTRAP: // Egg Capsule animal release
 			if (mobj->fuse > 0 && mobj->fuse < 2*TICRATE-(TICRATE/7)
 				&& (mobj->fuse & 3))
@@ -7355,18 +7358,42 @@ void P_MobjThinker(mobj_t *mobj)
 				P_MobjCheckWater(mobj);
 				break;
 			case MT_ARROW:
-				if (!(mobj->extravalue1) && (mobj->momz < 0))
+				if (mobj->flags & MF_MISSILE)
 				{
-					mobj->extravalue1 = 1;
-					S_StartSound(mobj, mobj->info->activesound);
-				}
-				if (leveltime & 1)
-				{
-					mobj_t *dust = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_PARTICLE);
-					dust->tics = 18;
-					dust->scalespeed = 4096;
-					dust->destscale = FRACUNIT/32;
+					// Calculate the angle of movement.
+					/*
+						   momz
+						 / |
+					   /   |
+					 /     |
+					0------dist(momx,momy)
+					*/
+
+					fixed_t dist = P_AproxDistance(mobj->momx, mobj->momy);
+					angle_t angle = R_PointToAngle2(0, 0, dist, mobj->momz);
+
+					if (angle > ANG20 && angle <= ANGLE_180)
+						mobj->frame = 2;
+					else if (angle < ANG340 && angle > ANGLE_180)
+						mobj->frame = 0;
+					else
+						mobj->frame = 1;
+
+					if (!(mobj->extravalue1) && (mobj->momz < 0))
+					{
+						mobj->extravalue1 = 1;
+						S_StartSound(mobj, mobj->info->activesound);
+					}
+					if (leveltime & 1)
+					{
+						mobj_t *dust = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_PARTICLE);
+						dust->tics = 18;
+						dust->scalespeed = 4096;
+						dust->destscale = FRACUNIT/32;
+					}
 				}
+				else
+					mobj->flags2 ^= MF2_DONTDRAW;
 				break;
 			case MT_EMERALDSPAWN:
 				if (mobj->threshold)