// Function: A_UnidusBall
//
// Description: Rotates a spike ball around its target.
//
// var1:
// 0 = Don't throw
// 1 = Throw
// 2 = Throw when target leaves MF2_SKULLFLY.
// var2 = unused
//
void A_UnidusBall(mobj_t *actor)
{
INT32 locvar1 = var1;
boolean canthrow = false;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_UnidusBall", actor))
return;
#endif
actor->angle += ANGLE_11hh;
if (actor->movecount)
{
if (P_AproxDistance(actor->momx, actor->momy) < FixedMul(actor->info->damage/2, actor->scale))
P_ExplodeMissile(actor);
return;
}
if (!actor->target || !actor->target->health)
{
CONS_Debug(DBG_GAMELOGIC, "A_UnidusBall: Removing unthrown spikeball from nonexistant Unidus\n");
P_RemoveMobj(actor);
return;
}
P_UnsetThingPosition(actor);
{
const angle_t angle = actor->movedir + FixedAngle(actor->info->speed*(leveltime%360));
const UINT16 fa = angle>>ANGLETOFINESHIFT;
actor->x = actor->target->x + FixedMul(FINECOSINE(fa),actor->threshold);
actor->y = actor->target->y + FixedMul( FINESINE(fa),actor->threshold);
actor->z = actor->target->z + actor->target->height/2 - actor->height/2;
if (locvar1 == 1 && actor->target->target)
{
const angle_t tang = R_PointToAngle2(actor->target->x, actor->target->y, actor->target->target->x, actor->target->target->y);
const angle_t mina = tang-ANGLE_11hh;
canthrow = (angle-mina < FixedAngle(actor->info->speed*3));
}
}
P_SetThingPosition(actor);
if (locvar1 == 1 && canthrow)
{
if (P_AproxDistance(actor->target->target->x - actor->target->x, actor->target->target->y - actor->target->y) > FixedMul(MISSILERANGE>>1, actor->scale)
|| !P_CheckSight(actor, actor->target->target))
return;
actor->movecount = actor->info->damage>>FRACBITS;
actor->flags &= ~(MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING);
P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, actor->target->target->x, actor->target->target->y), FixedMul(actor->info->damage, actor->scale));
}
else if (locvar1 == 2)
{
boolean skull = (actor->target->flags2 & MF2_SKULLFLY) == MF2_SKULLFLY;
if (actor->target->state == &states[actor->target->info->painstate])
{
P_KillMobj(actor, NULL, NULL, 0);
return;
}
switch(actor->extravalue2)
{
case 0: // at least one frame where not dashing
if (!skull) ++actor->extravalue2;
else break;
/* FALLTHRU */
case 1: // at least one frame where ARE dashing
if (skull) ++actor->extravalue2;
else break;
/* FALLTHRU */
case 2: // not dashing again?
if (skull) break;
// launch.
{
mobj_t *target = actor->target;
if (actor->target->target)
target = actor->target->target;
actor->movecount = actor->info->damage>>FRACBITS;
actor->flags &= ~(MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING);
P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, target->x, target->y), FixedMul(actor->info->damage, actor->scale));
}
default: // from our compiler appeasement program (CAP).
break;
}
}
}