// 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;
		}
	}
}