// Function: A_Boss2PogoTarget
//
// Description: Pogoing for Boss 2, tries to actually land on the player directly.
//
// var1 = pogo jump strength
// var2 = idle pogo speed
//
void A_Boss2PogoTarget(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_Boss2PogoTarget", actor))
return;
#endif
if (!actor->target || !(actor->target->flags & MF_SHOOTABLE) || (actor->target->player && actor->target->player->powers[pw_flashing])
|| P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) >= FixedMul(512*FRACUNIT, actor->scale))
{
// look for a new target
if (P_LookForPlayers(actor, true, false, 512*FRACUNIT))
; // got a new target
else if (P_LookForPlayers(actor, true, false, 0))
; // got a new target
else
return;
}
// Target hit, retreat!
if (actor->target->player->powers[pw_flashing] > TICRATE || actor->flags2 & MF2_FRET)
{
UINT8 prandom = P_RandomByte();
actor->z++; // unstick from the floor
actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); // Pick a direction, and randomize it.
P_InstaThrust(actor, actor->angle+ANGLE_180, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed
}
// Try to land on top of the player.
else if (P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) < FixedMul(512*FRACUNIT, actor->scale))
{
fixed_t airtime, gravityadd, zoffs;
// check gravity in the sector (for later math)
P_CheckGravity(actor, true);
gravityadd = actor->momz;
actor->z++; // unstick from the floor
actor->momz = FixedMul(locvar1 + (locvar1>>2), actor->scale); // Bounce up in air
/*badmath = 0;
airtime = 0;
do {
badmath += momz;
momz += gravityadd;
airtime++;
} while(badmath > 0);
airtime = 2*airtime<<FRACBITS;
*/
// Remember, kids!
// Reduced down Calculus lets you avoid bad 'logic math' loops!
//airtime = FixedDiv(-actor->momz<<1, gravityadd)<<1; // going from 0 to 0 is much simpler
zoffs = (P_GetPlayerHeight(actor->target->player)>>1) + (actor->target->floorz - actor->floorz); // offset by the difference in floor height plus half the player height,
airtime = FixedDiv((-actor->momz - FixedSqrt(FixedMul(actor->momz,actor->momz)+zoffs)), gravityadd)<<1; // to try and land on their head rather than on their feet
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y);
P_InstaThrust(actor, actor->angle, FixedDiv(P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y), airtime));
}
// Wander semi-randomly towards the player to get closer.
else
{
UINT8 prandom = P_RandomByte();
actor->z++; // unstick from the floor
actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); // Pick a direction, and randomize it.
P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed
}
// Boing!
if (actor->info->activesound) S_StartSound(actor, actor->info->activesound);
if (actor->info->missilestate) // spawn the pogo stick collision box
{
mobj_t *pogo = P_SpawnMobj(actor->x, actor->y, actor->z - mobjinfo[actor->info->missilestate].height, (mobjtype_t)actor->info->missilestate);
P_SetTarget(&pogo->target, actor);
}
actor->reactiontime = 1;
}