#include	"world.h"

#include	"ai.h"
#include	"ai_utils.h"

#include	"ai_move.h"
#include	"ai_weapons.h"
#include	"ai_task.h"
#include	"ai_frames.h"

#include	"skat.h"
#include	"nodelist.h"

////////////////////////////////////////////////////////////////////////////////
// exports
////////////////////////////////////////////////////////////////////////////////

DllExport	void	monster_satyr (userEntity_t *self);

///////////////////////////////////////////////////////////////////////////////////
// satyr specific funcitons
///////////////////////////////////////////////////////////////////////////////////

void	satyr_close_melee (userEntity_t *self);
void	satyr_far_melee (userEntity_t *self);

////////////////////////////////
//	satyr_init_frametable
//
////////////////////////////////

void	satyr_init_frametable (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	
	ai_set_sequence_data (self, hook->frames->atak [0], -1, NULL, 10, "monsters/satyr/satyrattack1.wav", 0, -1, 0, -1, FRAME_ONCE);
	ai_set_sequence_data (self, hook->frames->atak [1], 0, "monsters/satyr/satyrattack1.wav", 9, "monsters/satyr/satyrattack1.wav", SEQUENCE_TRANS, 0, SEQUENCE_TRANS, 1, FRAME_LOOP);

	ai_set_sequence_data (self, hook->frames->stand [0], -1, NULL, -1, NULL, 0, -1, 0, -1, FRAME_LOOP);
	ai_set_sequence_data (self, hook->frames->stand [2], 0, "monsters/satyr/satyrscream1.wav", -1, NULL, 0, -1, 0, -1, FRAME_ONCE);
}

////////////////////////////////
//	satyr_set_attack_seq
//
////////////////////////////////

void	satyr_set_attack_seq (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	float			dist;

	dist = qv_dist (self->s.origin, self->enemy->s.origin);

	if (dist > 80)
	{
		ai_init_sequence (self, hook->frames->atak [0], SEQUENCE_ATAK, 0);
	}
	else
		ai_init_sequence (self, hook->frames->atak [1], SEQUENCE_ATAK, 1);
}

////////////////////////////////////////
//	satyr_roar
////////////////////////////////////////

void	satyr_roar (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;

	// killed the player, so roar
//	ai_set_sequence_sounds (self, hook->frames->stand [2]->soundframe1, hook->frames->stand [2]->sound1, 
//								  hook->frames->stand [2]->soundframe2, hook->frames->stand [2]->sound2);
//	ai_begin_transition (self, hook->frames->stand [2]->first, hook->frames->stand [2]->last, hook->temp_think);
	ai_begin_transition (self, hook->frames->stand [2], SEQUENCE_STAND, 2, hook->temp_think);
}

////////////////////////////////////////
//	satyr_roar_killed_enemy
////////////////////////////////////////

void	satyr_roar_killed_enemy (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;

	// killed the player, so roar
//	ai_set_sequence_sounds (self, hook->frames->stand [2]->soundframe1, hook->frames->stand [2]->sound1, 
//								  hook->frames->stand [2]->soundframe2, hook->frames->stand [2]->sound2);
//	ai_begin_transition (self, hook->frames->stand [2]->first, hook->frames->stand [2]->last, ai_killed_enemy);
	ai_begin_transition (self, hook->frames->stand [2], SEQUENCE_STAND, 2, ai_killed_enemy);
}

///////////////////////////
//	satyr_close_melee
//
///////////////////////////

void	satyr_close_melee (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	Vector			temp;
	float			dist;

/*	
	temp = self->goalentity->s.origin;
	com->CopyVector (self->goalentity->s.origin, self->enemy->s.origin);
	ai_face_goal (self);
	temp.set (self->goalentity->s.origin);
*/
	hook->dflags |= DFL_FACEENEMY;

	dist = qv_dist (self->s.origin, self->enemy->s.origin);

	// are we in a transition sequence?
	if (hook->frame_flags & FRAME_TRANS)
	{
		if (hook->frame_flags & FRAME_STATIC)
			ai_post_trans (self, FRAME_LOOP + FRAME_NEEDTRANS);
	}
	else
	{
		if (hook->frame_flags & FRAME_PLAYSOUND1)
		{
			hook->frame_flags = hook->frame_flags - FRAME_PLAYSOUND1;
					
//			if (ai_trace_attack (self, 24.0 * rnd () + 8.0, hook->attack_dist))
//				gstate->sound (self, CHAN_AUTO, hook->sound1, 128, ATTN_NORM);
			ai_fire_curWeapon (self, Vector (self->s.origin), Vector (self->enemy->s.origin), 0, 0);
		}
		
		if (hook->frame_flags & FRAME_PLAYSOUND2)
		{
			hook->frame_flags = hook->frame_flags - FRAME_PLAYSOUND2;
					
//			if (ai_trace_attack (self, 24.0 * rnd () + 8.0, hook->attack_dist))
//				gstate->sound (self, CHAN_AUTO, hook->sound2, 128, ATTN_NORM);
			ai_fire_curWeapon (self, Vector (self->s.origin), Vector (self->enemy->s.origin), 0, 0);
		}
		
		if (hook->frame_flags & FRAME_LAST)
		{
			hook->frame_flags -= FRAME_LAST;

			if (self->enemy->deadflag != DEAD_NO)
			{
				hook->temp_think = hook->begin_wander;

				//	killed the player, so roar
				//	we've got to transition back to stand first
//				ai_begin_transition (self, hook->frames->trans [hook->end_seq_num]->first, hook->frames->trans [hook->end_seq_num]->last, satyr_roar_killed_enemy);
				ai_begin_transition (self, hook->frames->trans [hook->end_seq_num], SEQUENCE_TRANS, hook->end_seq_num, satyr_roar_killed_enemy);

				//	leaving, so pop off TASK_ATTACK
				task_pop (&hook->task_stack);

				return;
			}
			else if (dist > hook->attack_dist || !com->Visible (self, self->enemy))
			{
				ai_should_follow (self);
				hook->temp_think = self->think;							

				//	player ran away, so roar sometimes
				//	always transition back to stand first
				if (rnd () < 0.2)
//					ai_begin_transition (self, hook->frames->trans [hook->end_seq_num]->first, hook->frames->trans [hook->end_seq_num]->last, satyr_roar);
					ai_begin_transition (self, hook->frames->trans [hook->end_seq_num], SEQUENCE_TRANS, hook->end_seq_num, satyr_roar);
				else
//					ai_begin_transition (self, hook->frames->trans [hook->end_seq_num]->first, hook->frames->trans [hook->end_seq_num]->last, self->think);
					ai_begin_transition (self, hook->frames->trans [hook->end_seq_num], SEQUENCE_TRANS, hook->end_seq_num, self->think);

				//	leaving, so pop off TASK_ATTACK
				task_pop (&hook->task_stack);

				return;
			}
			else if (dist > 80.0)
			{
				satyr_set_attack_seq (self);
				satyr_far_melee (self);

				return;
			}
		}
	}

	ai_set_think (self, satyr_close_melee, "satyr_close_melee");
}

///////////////////////////
//	satyr_far_melee
//
///////////////////////////

void	satyr_far_melee (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	Vector			temp;
	float			dist;

/*	
	temp = self->goalentity->s.origin;
	com->CopyVector (self->goalentity->s.origin, self->enemy->s.origin);
	ai_face_goal (self);
	temp.set (self->goalentity->s.origin);
*/

	hook->dflags |= DFL_FACEENEMY;

	dist = qv_dist (self->s.origin, self->enemy->s.origin);

	if (hook->frame_flags & FRAME_PLAYSOUND2)
	{
		hook->frame_flags = hook->frame_flags - FRAME_PLAYSOUND2;
	
		ai_fire_curWeapon (self, Vector (self->s.origin), Vector (self->enemy->s.origin), 0, 0);
	}

	// attack without any transitions
	if (hook->frame_flags & FRAME_STATIC)
	{
		hook->frame_flags -= FRAME_STATIC;	

		if (self->enemy->deadflag != DEAD_NO)
		{
			hook->temp_think = hook->begin_wander;

			satyr_roar (self);

			//	pop off everything thru TASK_CHASE for this enemy
			ai_killed_enemy (self);

			return;
		}
		else if (dist > hook->attack_dist || !com->Visible (self, self->enemy))
		{
			ai_should_follow (self);
			hook->temp_think = self->think;

			if (rnd () < 0.2)
				satyr_roar (self);

			//	leaving, so pop off TASK_ATTACK
			task_pop (&hook->task_stack);

			return;
		}
		else if (dist <= 80.0)
		{
			satyr_set_attack_seq (self);
			satyr_close_melee (self);

			return;
		}

		satyr_set_attack_seq (self);
	}

	ai_set_think (self, satyr_far_melee, "satyr_far_melee");
}

////////////////////////////
//	satyr_begin_attack
//
////////////////////////////

void	satyr_begin_attack (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	float			dist;

	com->ZeroVector (self->velocity);

	hook->th_state = TH_ATTACK;
	hook->attack_finished = gstate->time + 1.0;

	satyr_set_attack_seq (self);

	dist = qv_dist (self->enemy->s.origin, self->s.origin);

	if (dist > 80.0)
		satyr_far_melee (self);
	else
		satyr_close_melee (self);
}

///////////////////////////////
//	monster_satyr
//
//	spawns a satyr during level load
///////////////////////////////

void	monster_satyr (userEntity_t *self)
{
	playerHook_t		*hook;
	int					i;

	hook = ai_init_monster (self, 0 /*TYPE_SATYR*/);

	self->className = "monster_satyr";
	self->netname = "horny goat";
/*
	gstate->Precache_Sound ("monsters/satyr/satyrattack1.wav");
	gstate->Precache_Sound ("monsters/satyr/satyrattack2.wav");
	gstate->Precache_Sound ("monsters/satyr/satyrdeath1.wav");
	gstate->Precache_Sound ("monsters/satyr/satyrdeath2.wav");
	gstate->Precache_Sound ("monsters/satyr/satyrpain1.wav");
	gstate->Precache_Sound ("monsters/satyr/satyrpain2.wav");
	gstate->Precache_Sound ("monsters/satyr/satyrsight1.wav");
	gstate->Precache_Sound ("monsters/satyr/satyrsight2.wav");
	gstate->Precache_Sound ("monsters/satyr/satyrwander1.wav");
	gstate->Precache_Sound ("monsters/satyr/satyrwander2.wav");
*/
	gstate->Precache_Sound ("monsters/satyr/satyrscream1.wav");
	gstate->Precache_Sound ("monsters/satyr/satyrattack1.wav");

	self->s.modelindex = gstate->ModelIndex ("models/satyr/satyr.md2");
	gstate->SetSize (self, -16.0, -16.0, -24.0, 16.0, 16.0, 32.0);

	////////////////////////////////////////////////////////////////
	// set up animation stuff
	////////////////////////////////////////////////////////////////

	ai_get_sequences (self);

	satyr_init_frametable (self);

	///////////////////////////////////////////////////////////
	// set up pointers to this creature's ai functions
	///////////////////////////////////////////////////////////

	hook->begin_attack = satyr_begin_attack;

//	hook->dflags |= DFL_ORIENTTOFLOOR;

	hook->run_speed = 250;
	hook->walk_speed = 120;
	hook->attack_dist = 108;

	self->health = 200;
	hook->max_health = 200;
	hook->pain_chance = 10;
	self->mass = 2.0;

	self->think = ai_get_spawn_node;
	self->nextthink = gstate->time + 0.2;

	self->translucent = 0;

	//////////////////////////////////////////////
	//	give satyr its melee weapon
	//////////////////////////////////////////////
/*
	self->curWeapon = ai_weapon_create ("punch", melee_punch, ai_weapon_command);
	i = 10;
	ai_weapon_command (self->curWeapon, "base_damage", &i);
	ai_weapon_command (self->curWeapon, "rnd_damage", &i);
*/
	self->curWeapon = ai_init_weapon (self, 10, 10, 0, 0, 0, 108, Vector (0, 0, 0), "punch", melee_punch, WEAPON_TRACE);
//	gstate->InventoryAddItem (self->inventory, self->curWeapon);

	com->SetVector (self->s.render_scale, 1.3, 1.3, 1.3);
}

