#include "actor.h"
#include "info.h"
#include "m_random.h"
#include "p_local.h"
#include "s_sound.h"

static FRandom pr_batspawn ("BatSpawn");
static FRandom pr_batmove ("BatMove");

void A_BatSpawnInit (AActor *);
void A_BatSpawn (AActor *);
void A_BatMove (AActor *);

// Bat Spawner --------------------------------------------------------------

class ABatSpawner : public AActor
{
	DECLARE_ACTOR (ABatSpawner, AActor)
public:
	void Activate (AActor *activator);
	void Deactivate (AActor *activator);
};

FState ABatSpawner::States[] =
{
#define S_SPAWNBATS1 0
	S_NORMAL (TNT1, 'A',	2, NULL					    , &States[S_SPAWNBATS1+1]),
	S_NORMAL (TNT1, 'A',	2, A_BatSpawnInit		    , &States[S_SPAWNBATS1+2]),
	S_NORMAL (TNT1, 'A',	2, A_BatSpawn			    , &States[S_SPAWNBATS1+2]),

#define S_SPAWNBATS_OFF (S_SPAWNBATS1+3)
	S_NORMAL (TNT1, 'A',   -1, NULL					    , NULL)
};

IMPLEMENT_ACTOR (ABatSpawner, Hexen, 10225, 0)
	PROP_Flags (MF_NOSECTOR|MF_NOBLOCKMAP|MF_NOGRAVITY)
	PROP_RenderStyle (STYLE_None)

	PROP_SpawnState (S_SPAWNBATS1)
END_DEFAULTS

void ABatSpawner::Activate (AActor *activator)
{
	SetState (&States[S_SPAWNBATS1]);
}

void ABatSpawner::Deactivate (AActor *activator)
{
	SetState (&States[S_SPAWNBATS_OFF]);
}

// Bat ----------------------------------------------------------------------

class ABat : public AActor
{
	DECLARE_ACTOR (ABat, AActor)
};

FState ABat::States[] =
{
#define S_BAT1 0
	S_NORMAL (ABAT, 'A',	2, A_BatMove			    , &States[S_BAT1+1]),
	S_NORMAL (ABAT, 'B',	2, A_BatMove			    , &States[S_BAT1+2]),
	S_NORMAL (ABAT, 'C',	2, A_BatMove			    , &States[S_BAT1]),

#define S_BAT_DEATH (S_BAT1+3)
	S_NORMAL (ABAT, 'A',	2, NULL					    , NULL),
};

IMPLEMENT_ACTOR (ABat, Hexen, -1, 0)
	PROP_SpeedFixed (5)
	PROP_RadiusFixed (3)
	PROP_HeightFixed (3)
	PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_MISSILE)
	PROP_Flags2 (MF2_NOTELEPORT|MF2_PASSMOBJ)

	PROP_SpawnState (S_BAT1)
	PROP_DeathState (S_BAT_DEATH)
END_DEFAULTS

//===========================================================================
// Bat Spawner Variables
//	special1	frequency counter
//	special2	
//	args[0]		frequency of spawn (1=fastest, 10=slowest)
//	args[1]		spread angle (0..255)
//	args[2]		
//	args[3]		duration of bats (in octics)
//	args[4]		turn amount per move (in degrees)
//
// Bat Variables
//	special2	lifetime counter
//	args[4]		turn amount per move (in degrees)
//===========================================================================

void A_BatSpawnInit (AActor *actor)
{
	actor->special1 = 0;	// Frequency count
}

void A_BatSpawn (AActor *actor)
{
	AActor *mo;
	int delta;
	angle_t angle;

	// Countdown until next spawn
	if (actor->special1-- > 0) return;
	actor->special1 = actor->args[0];		// Reset frequency count

	delta = actor->args[1];
	if (delta==0) delta=1;
	angle = actor->angle + (((pr_batspawn()%delta)-(delta>>1))<<24);
	mo = P_SpawnMissileAngle (actor, RUNTIME_CLASS(ABat), angle, 0);
	if (mo)
	{
		mo->args[0] = pr_batspawn()&63;			// floatbob index
		mo->args[4] = actor->args[4];			// turn degrees
		mo->special2 = actor->args[3]<<3;		// Set lifetime
		mo->target = actor;
	}
}


void A_BatMove (AActor *actor)
{
	angle_t newangle;

	if (actor->special2 < 0)
	{
		actor->SetState (actor->DeathState);
	}
	actor->special2 -= 2;		// Called every 2 tics

	if (pr_batmove()<128)
	{
		newangle = actor->angle + ANGLE_1*actor->args[4];
	}
	else
	{
		newangle = actor->angle - ANGLE_1*actor->args[4];
	}

	// Adjust momentum vector to new direction
	newangle >>= ANGLETOFINESHIFT;
	actor->momx = FixedMul (actor->Speed, finecosine[newangle]);
	actor->momy = FixedMul (actor->Speed, finesine[newangle]);

	if (pr_batmove()<15)
	{
		S_Sound (actor, CHAN_VOICE, "BatScream", 1, ATTN_IDLE);
	}

	// Handle Z movement
	actor->z = actor->target->z + 2*FloatBobOffsets[actor->args[0]];
	actor->args[0] = (actor->args[0]+3)&63;	
}
