diff --git a/src/dehacked.c b/src/dehacked.c index b52c79461..78a9912a4 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 4f4dc1aa7..01edc0eb2 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<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) - { - if (actor->momz > 0) - P_SetMobjStateNF(actor, actor->info->xdeathstate); // Rising - else - P_SetMobjStateNF(actor, actor->info->raisestate); // Falling - - return; - } - else if ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height < actor->ceilingz) - { - if (actor->momz < 0) - P_SetMobjStateNF(actor, actor->info->xdeathstate); // Rising - else - P_SetMobjStateNF(actor, actor->info->raisestate); // Falling - - return; - } - - if (actor->state == &states[actor->info->xdeathstate] - || actor->state == &states[actor->info->raisestate]) - P_SetMobjStateNF(actor, actor->info->seestate); + // Check target first. if (!actor->target) { + actor->reactiontime = actor->info->reactiontime; P_SetMobjState(actor, actor->info->spawnstate); return; } - A_FaceTarget(actor); // Aiming... aiming... + 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<info->raisestate); + return; + } - if (--actor->reactiontime > 0) + // If target on sight, look at it. + if ((checksight = P_CheckSight(actor, actor->target))) + { + 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 + actor->angle >>= 1; + + if (dang >= ANGLE_180) + { + dang = InvAngle(dang)>>1; + dang = InvAngle(dang); + } + else + dang >>= 1; + + actor->angle += dang; + } + + // Check whether to do anything. + if ((--actor->reactiontime) <= 0) + { + actor->reactiontime = actor->info->reactiontime; + + // If way too far, don't shoot. + if ((dm < (3072<info->missilestate); + return; + } + } +} + +// 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 + + if (!P_IsObjectOnGround(actor)) return; - // 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); - + 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 8232586b2..3b6ea394c 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) {