diff --git a/src/dehacked.c b/src/dehacked.c
index b52c79461f80d0e9ec55d05b01ee70f61081f089..78a9912a456f999bb4deba6f5adf741238a8f5fa 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -1703,7 +1703,9 @@ static actionpointer_t actionpointers[] =
 	{{A_JetJawChomp},            "A_JETJAWCHOMP"},
 	{{A_PointyThink},            "A_POINTYTHINK"},
 	{{A_CheckBuddy},             "A_CHECKBUDDY"},
+	{{A_HoodFire},               "A_HOODFIRE"},
 	{{A_HoodThink},              "A_HOODTHINK"},
+	{{A_HoodFall},               "A_HOODFALL"},
 	{{A_ArrowCheck},             "A_ARROWCHECK"},
 	{{A_SnailerThink},           "A_SNAILERTHINK"},
 	{{A_SharpChase},             "A_SHARPCHASE"},
@@ -3757,11 +3759,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 
 	// Robo-Hood
 	"S_ROBOHOOD_LOOK",
-	"S_ROBOHOOD_STND",
-	"S_ROBOHOOD_SHOOT",
-	"S_ROBOHOOD_JUMP",
+	"S_ROBOHOOD_STAND",
+	"S_ROBOHOOD_FIRE1",
+	"S_ROBOHOOD_FIRE2",
+	"S_ROBOHOOD_JUMP1",
 	"S_ROBOHOOD_JUMP2",
-	"S_ROBOHOOD_FALL",
+	"S_ROBOHOOD_JUMP3",
 
 	// CastleBot FaceStabber
 	"S_FACESTABBER_STND1",
diff --git a/src/info.c b/src/info.c
index 4f4dc1aa7bf22ddaadcd3375cfdfd2cd4089a0c7..01edc0eb2e9694cb47484aae93ae1650033be17a 100644
--- a/src/info.c
+++ b/src/info.c
@@ -981,12 +981,13 @@ state_t states[NUMSTATES] =
 	{SPR_PNTY, 1,  1, {A_CheckBuddy}, 0, 0, S_POINTYBALL1}, // S_POINTYBALL1
 
 	// Robo-Hood
-	{SPR_ARCH, 0, 14,       {A_Look}, (512<<16),   0, S_ROBOHOOD_LOOK},  // S_ROBOHOOD_LOOK
-	{SPR_ARCH, 2,  1,  {A_HoodThink},         0,   0, S_ROBOHOOD_STND},  // S_ROBOHOOD_STND
-	{SPR_ARCH, 0, 35,   {A_FireShot},  MT_ARROW, -24, S_ROBOHOOD_STND},  // S_ROBOHOOD_SHOOT
-	{SPR_ARCH, 1,  1,   {A_BunnyHop},         8,   5, S_ROBOHOOD_JUMP2}, // S_ROBOHOOD_JUMP
-	{SPR_ARCH, 1,  1,  {A_HoodThink},         0,   0, S_ROBOHOOD_JUMP2}, // S_ROBOHOOD_JUMP2
-	{SPR_ARCH, 0,  1,  {A_HoodThink},         0,   0, S_ROBOHOOD_FALL},  // S_ROBOHOOD_FALL
+	{SPR_ARCH, 0,       4,            {A_Look}, 2048<<FRACBITS,   0, S_ROBOHOOD_LOOK},  // S_ROBOHOOD_LOOK
+	{SPR_ARCH, 0,       1,       {A_HoodThink},              0,   0, S_ROBOHOOD_STAND}, // S_ROBOHOOD_STAND
+	{SPR_ARCH, 2, TICRATE, {A_PlayActiveSound},              0,   0, S_ROBOHOOD_FIRE2}, // S_ROBOHOOD_FIRE1
+	{SPR_ARCH, 2,      20,        {A_HoodFire},       MT_ARROW,   0, S_ROBOHOOD_STAND}, // S_ROBOHOOD_FIRE2
+	{SPR_ARCH, 1,       1,      {A_FaceTarget},              0,   0, S_ROBOHOOD_JUMP2}, // S_ROBOHOOD_JUMP1
+	{SPR_ARCH, 1,       1,        {A_BunnyHop},              4, -10, S_ROBOHOOD_JUMP3}, // S_ROBOHOOD_JUMP2
+	{SPR_ARCH, 1,       1,        {A_HoodFall},              0,   0, S_ROBOHOOD_JUMP3}, // S_ROBOHOOD_JUMP3
 
 	// Castlebot Facestabber
 	{SPR_CBFS, 0,  1,        {A_Chase},  0, 0, S_FACESTABBER_STND2},   // S_FACESTABBER_STND1
@@ -2941,8 +2942,8 @@ state_t states[NUMSTATES] =
 	{SPR_SEED, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 2, 2, S_NULL}, // S_SEED
 
 	// Particle sprite
-	{SPR_PRTL, FF_FULLBRIGHT|FF_TRANS70, 2*TICRATE, {NULL}, 0, 0, S_NULL}, // S_PARTICLE
-	{SPR_NULL,     0,          3, {A_ParticleSpawn}, 0, 0, S_PARTICLEGEN}, // S_PARTICLEGEN
+	{SPR_PRTL, 0, 2*TICRATE, {NULL}, 0, 0, S_NULL}, // S_PARTICLE
+	{SPR_NULL, 0, 3, {A_ParticleSpawn}, 0, 0, S_PARTICLEGEN}, // S_PARTICLEGEN
 
 	{SPR_SCOR, 0, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRA  - 100
 	{SPR_SCOR, 1, 32, {A_ScoreRise}, 0, 0, S_NULL}, // S_SCRB  - 200
@@ -4219,27 +4220,27 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		117,              // doomednum
 		S_ROBOHOOD_LOOK,  // spawnstate
 		1,                // spawnhealth
-		S_ROBOHOOD_STND,  // seestate
+		S_ROBOHOOD_STAND, // seestate
 		sfx_None,         // seesound
 		TICRATE,          // reactiontime
 		sfx_None,         // attacksound
-		S_ROBOHOOD_JUMP,  // painstate
+		S_NULL,           // painstate
 		0,                // painchance
 		sfx_None,         // painsound
-		S_NULL,           // meleestate
-		S_ROBOHOOD_SHOOT, // missilestate
+		S_ROBOHOOD_JUMP3, // meleestate
+		S_ROBOHOOD_FIRE1, // missilestate
 		S_XPLD_FLICKY,    // deathstate
-		S_ROBOHOOD_JUMP2, // xdeathstate
+		S_NULL,           // xdeathstate
 		sfx_pop,          // deathsound
-		0,                // speed
+		3,                // speed
 		24*FRACUNIT,      // radius
 		32*FRACUNIT,      // height
 		0,                // display offset
 		100,              // mass
 		0,                // damage
-		sfx_None,         // activesound
+		sfx_s3k4a,        // activesound
 		MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE, // flags
-		S_ROBOHOOD_FALL   // raisestate
+		S_ROBOHOOD_JUMP1  // raisestate
 	},
 
 	{           // MT_FACESTABBER
@@ -8616,7 +8617,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_ARROW,        // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
-		sfx_None,       // seesound
+		sfx_s3ka0,      // seesound
 		32,             // reactiontime
 		sfx_None,       // attacksound
 		S_NULL,         // painstate
@@ -8626,15 +8627,15 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // missilestate
 		S_NULL,         // deathstate
 		S_ARROWDOWN,    // xdeathstate
-		sfx_None,       // deathsound
+		sfx_s3k52,      // deathsound
 		16*FRACUNIT,    // speed
 		4*FRACUNIT,     // radius
 		8*FRACUNIT,     // height
 		0,              // display offset
 		0,              // mass
 		1,              // damage
-		sfx_None,       // activesound
-		MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY, // flags
+		sfx_s3k51,      // activesound
+		MF_NOBLOCKMAP|MF_MISSILE, // flags
 		S_ARROWUP       // raisestate
 	},
 
diff --git a/src/info.h b/src/info.h
index c75ed0e6fb735d7b2c8d0ce1cac4cbb73debd42b..8134a1a49abb16517e688e6524a979964e43eb9f 100644
--- a/src/info.h
+++ b/src/info.h
@@ -102,7 +102,9 @@ void A_JetJawRoam();
 void A_JetJawChomp();
 void A_PointyThink();
 void A_CheckBuddy();
+void A_HoodFire();
 void A_HoodThink();
+void A_HoodFall();
 void A_ArrowCheck();
 void A_SnailerThink();
 void A_SharpChase();
@@ -1107,11 +1109,12 @@ typedef enum state
 
 	// Robo-Hood
 	S_ROBOHOOD_LOOK,
-	S_ROBOHOOD_STND,
-	S_ROBOHOOD_SHOOT,
-	S_ROBOHOOD_JUMP,
+	S_ROBOHOOD_STAND,
+	S_ROBOHOOD_FIRE1,
+	S_ROBOHOOD_FIRE2,
+	S_ROBOHOOD_JUMP1,
 	S_ROBOHOOD_JUMP2,
-	S_ROBOHOOD_FALL,
+	S_ROBOHOOD_JUMP3,
 
 	// Castlebot Facestabber
 	S_FACESTABBER_STND1,
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 20b32f2202415f8a884e7181c5c560bf092b4025..8a09df286aa741f5d11219737e4d921eafdd6416 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -63,7 +63,9 @@ void A_JetJawRoam(mobj_t *actor);
 void A_JetJawChomp(mobj_t *actor);
 void A_PointyThink(mobj_t *actor);
 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_SnailerThink(mobj_t *actor);
 void A_SharpChase(mobj_t *actor);
@@ -1591,6 +1593,62 @@ void A_CheckBuddy(mobj_t *actor)
 		P_RemoveMobj(actor);
 }
 
+// Helper function for the Robo Hood.
+// Don't ask me how it works. Nev3r made it with dark majyks.
+void P_ParabolicMove(mobj_t *actor, fixed_t x, fixed_t y, fixed_t z, fixed_t speed)
+{
+	fixed_t dh;
+
+	x -= actor->x;
+	y -= actor->y;
+	z -= actor->z;
+
+	dh = P_AproxDistance(x, y);
+
+	actor->momx = FixedMul(FixedDiv(x, dh), speed);
+	actor->momy = FixedMul(FixedDiv(y, dh), speed);
+
+	if (!gravity)
+		return;
+
+	dh = FixedDiv(FixedMul(dh, gravity), speed);
+	actor->momz = (dh>>1) + FixedDiv(z, dh<<1);
+}
+
+// Function: A_HoodFire
+//
+// Description: Firing Robo-Hood
+//
+// var1 = object type to fire
+// var2 = unused
+//
+void A_HoodFire(mobj_t *actor)
+{
+	mobj_t *arrow;
+	INT32 locvar1 = var1;
+	//INT32 locvar2 = var2;
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_HoodFire", actor))
+		return;
+#endif
+
+	// Check target first.
+	if (!actor->target)
+	{
+		actor->reactiontime = actor->info->reactiontime;
+		P_SetMobjState(actor, actor->info->spawnstate);
+		return;
+	}
+
+	A_FaceTarget(actor);
+
+	if (!(arrow = P_SpawnMissile(actor, actor->target, (mobjtype_t)locvar1)))
+		return;
+
+	// Set a parabolic trajectory for the arrow.
+	P_ParabolicMove(arrow, actor->target->x, actor->target->y, actor->target->z, arrow->info->speed);
+}
+
 // Function: A_HoodThink
 //
 // Description: Thinker for Robo-Hood
@@ -1600,53 +1658,87 @@ void A_CheckBuddy(mobj_t *actor)
 //
 void A_HoodThink(mobj_t *actor)
 {
+	fixed_t dx, dy, dz, dm;
+	boolean checksight;
 #ifdef HAVE_BLUA
 	if (LUA_CallAction("A_HoodThink", actor))
 		return;
 #endif
-	// Currently in the air...
-	if (!(actor->eflags & MFE_VERTICALFLIP) && actor->z > actor->floorz)
+
+	// Check target first.
+	if (!actor->target)
 	{
-		if (actor->momz > 0)
-			P_SetMobjStateNF(actor, actor->info->xdeathstate); // Rising
-		else
-			P_SetMobjStateNF(actor, actor->info->raisestate); // Falling
+		actor->reactiontime = actor->info->reactiontime;
+		P_SetMobjState(actor, actor->info->spawnstate);
+		return;
+	}
 
+	dx = (actor->target->x - actor->x), dy = (actor->target->y - actor->y), dz = (actor->target->z - actor->z);
+	dm = P_AproxDistance(dx, dy);
+	// Target dangerously close to robohood, retreat then.
+	if ((dm < 256<<FRACBITS) && (abs(dz) < 128<<FRACBITS))
+	{
+		P_SetMobjState(actor, actor->info->raisestate);
 		return;
 	}
-	else if ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height < actor->ceilingz)
+
+	// If target on sight, look at it.
+	if ((checksight = P_CheckSight(actor, actor->target)))
 	{
-		if (actor->momz < 0)
-			P_SetMobjStateNF(actor, actor->info->xdeathstate); // Rising
+		angle_t dang = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y);
+		if (actor->angle >= ANGLE_180)
+		{
+			actor->angle = InvAngle(actor->angle)>>1;
+			actor->angle = InvAngle(actor->angle);
+		}
 		else
-			P_SetMobjStateNF(actor, actor->info->raisestate); // Falling
+			actor->angle >>= 1;
 
-		return;
-	}
+		if (dang >= ANGLE_180)
+		{
+			dang = InvAngle(dang)>>1;
+			dang = InvAngle(dang);
+		}
+		else
+			dang >>= 1;
 
-	if (actor->state == &states[actor->info->xdeathstate]
-		|| actor->state == &states[actor->info->raisestate])
-		P_SetMobjStateNF(actor, actor->info->seestate);
+		actor->angle += dang;
+	}
 
-	if (!actor->target)
+	// Check whether to do anything.
+	if ((--actor->reactiontime) <= 0)
 	{
-		P_SetMobjState(actor, actor->info->spawnstate);
-		return;
-	}
+		actor->reactiontime = actor->info->reactiontime;
 
-	A_FaceTarget(actor); // Aiming... aiming...
+		// If way too far, don't shoot.
+		if ((dm < (3072<<FRACBITS)) && checksight)
+		{
+			P_SetMobjState(actor, actor->info->missilestate);
+			return;
+		}
+	}
+}
 
-	if (--actor->reactiontime > 0)
+// Function: A_HoodFall
+//
+// Description: Falling Robo-Hood
+//
+// var1 = unused
+// var2 = unused
+//
+void A_HoodFall(mobj_t *actor)
+{
+#ifdef HAVE_BLUA
+	if (LUA_CallAction("A_HoodFall", actor))
 		return;
+#endif
 
-	// Shoot, if not too close (cheap shots are lame)
-	if ((P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) > FixedMul(192*FRACUNIT, actor->scale))
-	|| (actor->spawnpoint && (actor->spawnpoint->options & MTF_AMBUSH))) // If you can't jump, might as well shoot regardless of distance!
-		P_SetMobjState(actor, actor->info->missilestate);
-	else if (!(actor->spawnpoint && (actor->spawnpoint->options & MTF_AMBUSH)))// But we WILL jump!
-		P_SetMobjState(actor, actor->info->painstate);
+	if (!P_IsObjectOnGround(actor))
+		return;
 
+	actor->momx = actor->momy = 0;
 	actor->reactiontime = actor->info->reactiontime;
+	P_SetMobjState(actor, actor->info->seestate);
 }
 
 // Function: A_ArrowCheck
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 8232586b2e3192acee06c33732015de6151d0ad6..3b6ea394c738740baac82d4a0f8d8e997c9f8e57 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -7354,6 +7354,20 @@ void P_MobjThinker(mobj_t *mobj)
 				}
 				P_MobjCheckWater(mobj);
 				break;
+			case MT_ARROW:
+				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;
+				}
+				break;
 			case MT_EMERALDSPAWN:
 				if (mobj->threshold)
 				{