#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_battleboar (userEntity_t *self);

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

void	battleboar_melee_attack (userEntity_t *self);
void	battleboar_ranged_attack (userEntity_t *self);

////////////////////////////////
//	battleboar_init_frametable
//
////////////////////////////////

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

	ai_set_sequence_data (self, hook->frames->run [0], 1, NULL, 6, NULL, 0, -1, 0, -1, FRAME_ONCE);

	ai_set_sequence_data (self, hook->frames->atak [0], 1, "monsters/battleboar/battleboarattack1.wav", 6, NULL, 0, -1, 0, -1, FRAME_ONCE);
	ai_set_sequence_data (self, hook->frames->atak [1], 1, "monsters/battleboar/battleboarattack2.wav", 6, NULL, 0, -1, 0, -1, FRAME_ONCE);
}

////////////////////////////////
//	battleboar_set_attack_seq
//
////////////////////////////////

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

	ai_init_sequence (self, hook->frames->run [0], SEQUENCE_RUN, 0);
	battleboar_ranged_attack (self);

	hook->frame_flags = FRAME_ONCE;
	hook->frameInc = 1;
}

///////////////////////////
//	battleboar_ranged_attack
//
///////////////////////////

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

	ai_face_enemy (self);

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

	if (hook->frame_flags & FRAME_PLAYSOUND1)
	{
		hook->frame_flags = hook->frame_flags - FRAME_PLAYSOUND1;

		if (hook->sound1)
			gstate->sound (self, CHAN_AUTO, hook->sound1, 128, ATTN_NORM);

		ai_fire_curWeapon (self, Vector (self->s.origin) + Vector (self->view_ofs), Vector (self->enemy->s.origin) + Vector (self->enemy->view_ofs), 0, 0);
	}
	
	if (hook->frame_flags & FRAME_PLAYSOUND2)
	{
		hook->frame_flags = hook->frame_flags - FRAME_PLAYSOUND2;
		
		if (hook->sound2)
			gstate->sound (self, CHAN_AUTO, hook->sound2, 128, ATTN_NORM);

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

		if (self->enemy->deadflag != DEAD_NO)
		{
			//	leaving, so pop off TASK_ATTACK
			task_pop (&hook->task_stack);

			ai_killed_enemy (self);

			return;
		}
		else// if (dist > hook->attack_dist || !com->Visible (self, self->enemy))
		{
			//	leaving, so pop off TASK_ATTACK
			task_pop (&hook->task_stack);

			ai_should_follow (self);

			return;
		}
/*
		else
		{
			battleboar_set_attack_seq (self);

			return;
		}
*/
	}

	ai_attack_move (self);

	if (!(hook->ai_flags & AI_JUMP) && !(hook->ai_flags & AI_TURN))
		ai_set_think (self, battleboar_ranged_attack, "battleboar_ranged_attack");
}

////////////////////////////
//	battleboar_begin_attack
//
////////////////////////////

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

	com->ZeroVector (self->velocity);

	battleboar_set_attack_seq (self);

	hook->th_state = TH_ATTACK;
	hook->attack_finished = gstate->time + (hook->endFrame - hook->endFrame) * 0.1;
}

////////////////////////////
//	battleboar_prethink
//
////////////////////////////

void	battleboar_prethink (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	Vector			end, m_ang, f_ang, m_norm, f_norm;
	float			theta, pitch, dot;

	if (self->flags & FL_INWARP)
			return;

	// determine if the player/bot has left the ground between nodes
	// used for determining when to link nodes back
	if (!(self->flags & FL_ONGROUND) && !(self->flags & FL_PARTIALGROUND))
		hook->off_ground = TRUE;

	// get the bot's water level for this frame
	ai_water_level (self);

	// do damage to bot if in water/lava/slime
	ai_water_damage (self);

	ai_frame_update (self);

	//	rotate battle boar to pitch of plane its on
	end = Vector (self->s.origin);
	end.z -= 32;
	
	gstate->TraceLine (self->s.origin, end.vec (), TRUE, self, &trace);
	if (trace.fraction != 1.0)
	{
		f_norm = Vector (trace.planeNormal);
		f_norm.Normalize ();

		//	get floor normal's angles
		com->VecToAngles (f_ang, f_norm);
		
		m_ang = Vector (self->s.angles);

		//	get angle between floor normal's yaw and model's yaw
		theta = com->AngleDiff (f_ang.y, m_ang.y);

		if (theta > 90)
		{
			pitch = 90 - f_ang.x;

			self->ideal_ang [PITCH] = ((theta - 90) / 90) * pitch;
			self->ideal_ang [ROLL] = pitch - self->ideal_ang [PITCH];
		}
		else if (theta < -90)
		{
			pitch = 90 - f_ang.x;

			self->ideal_ang [PITCH] = ((theta + 90) / 90) * (- pitch);
			self->ideal_ang [ROLL] = - (pitch - self->ideal_ang [PITCH]);
		}
		else if (theta > 0)  // && theta <= 90
		{
			pitch = f_ang.x - 90;

			self->ideal_ang [ROLL] = (theta / 90) * (- pitch);
			self->ideal_ang [PITCH] = pitch + self->ideal_ang [ROLL];
		}
		else // theta < 0 && theta >= -90
		{
			pitch = f_ang.x - 90;
			
			self->ideal_ang [ROLL] = (theta / 90) * (- pitch);
			self->ideal_ang [PITCH] = pitch - self->ideal_ang [ROLL];
		}

		//	gl hack
		self->ideal_ang [ROLL] = -self->ideal_ang [ROLL];

//		gstate->Con_Printf ("theta = %.2f, pitch = %.2f ideal_pitch = %.2f roll = %.2f\n", theta, pitch, self->ideal_ang [0], self->s.angles [2]);
	}
	else
	{
		self->ideal_ang [PITCH] = 0;
		self->ideal_ang [ROLL] = 0;
	}

	com->ChangePitch (self);
	com->ChangeRoll (self);
}


//////////////////////////
//	monster_battleboar
//
//	creates the superfly entity and sets him up to smack down
//	everything that gets in his way.
//////////////////////////

void	monster_battleboar (userEntity_t *self)
{
	playerHook_t		*hook;
	int					i;
	float				f;
	Vector				v;

	hook = ai_init_monster (self, TYPE_BATTLEBOAR);

	self->className = "monster_battleboar";
	self->netname = "RoboCo Battle Boar";
	gstate->SoundIndex ("monsters/battleboar/battleboarattack1.wav");
	gstate->SoundIndex ("monsters/battleboar/battleboarattack2.wav");
	gstate->SoundIndex ("monsters/battleboar/battleboarwander1.wav");
	gstate->SoundIndex ("monsters/battleboar/battleboarwander2.wav");
	gstate->SoundIndex ("monsters/battleboar/battleboarwander3.wav");
	gstate->SoundIndex ("monsters/battleboar/battleboarsight1.wav");
	gstate->SoundIndex ("monsters/battleboar/battleboarsight2.wav");
	gstate->SoundIndex ("monsters/battleboar/battleboarpain1.wav");
	gstate->SoundIndex ("monsters/battleboar/battleboarpain2.wav");
	gstate->SoundIndex ("monsters/battleboar/battleboardie1.wav");
	gstate->SoundIndex ("monsters/battleboar/battleboardie2.wav");

	self->s.modelindex = gstate->ModelIndex ("models/battleboar/battleboar.md2");

	gstate->SetSize (self, -16.0, -16.0, -24.0, 16.0, 16.0, 32.0);
	
	gstate->LinkEntity (self);

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

	ai_get_sequences (self);
	battleboar_init_frametable (self);

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

//	hook->dflags -= DFL_EVIL;
//	hook->dflags |= DFL_GOOD;

	hook->begin_attack = battleboar_begin_attack;

	hook->run_speed = 200;
	hook->attack_speed = 200;
	hook->walk_speed = 140;
	hook->attack_dist = 400;

	self->health = 200;
	hook->dflags |= (DFL_RANGEDATTACK);// + DFL_ORIENTTOFLOOR);
	hook->dflags -= (DFL_CANSTRAFE);
	hook->max_health = 200;
	hook->pain_chance = 10;
	self->mass = 2.0;

	self->ang_speed [PITCH] = 90;
	self->ang_speed [YAW] = 360;
	self->ang_speed [ROLL] = 90;

//	self->prethink = battleboar_prethink;

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

	self->translucent = 0;

	///////////////////////////////////////////////////////////////////////////
	//	give monster its weapon
	///////////////////////////////////////////////////////////////////////////
/*
	self->curWeapon = ai_weapon_create ("psiblast", psiblast_fire, NULL);
	i = 10; ai_weapon_command (self->curWeapon, "base_damage", &i);
	i = 10;	ai_weapon_command (self->curWeapon, "rnd_damage", &i);
	f = 0.0; ai_weapon_command (self->curWeapon, "spread_x", &f);
	f = 0.0; ai_weapon_command (self->curWeapon, "spread_z", &f);
	f = 250.0;	ai_weapon_command (self->curWeapon, "speed", &f);
	v = Vector (0, 16, 6);	ai_weapon_command (self->curWeapon, "ofs", &v);
*/
	self->inventory = gstate->InventoryNew ();

	self->curWeapon = ai_init_weapon (self, 4, 0, 0.064, 0.064, 0, hook->attack_dist, Vector (8, 0, 8), "boargun right", boargun_fire, WEAPON_BULLET);
	gstate->InventoryAddItem (self->inventory, self->curWeapon);

	self->curWeapon = ai_init_weapon (self, 4, 0, 0, 0.064, 0.064, hook->attack_dist, Vector (-8, 0, 8), "boargun left", boargun_fire, WEAPON_BULLET);
	gstate->InventoryAddItem (self->inventory, self->curWeapon);
}

