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

////////////////////////////////////////////////////////////////////////////////
//	globals
////////////////////////////////////////////////////////////////////////////////

static	int	spider_count	= 0;

///////////////////////////////////////////////////////////////////////////////////
// spider specific funcitons
///////////////////////////////////////////////////////////////////////////////////

void	spider_jump_attack (userEntity_t *self);
void	spider_attack		(userEntity_t *self);

///////////////////////////////////////////////////////////////////////////////////
//	spider_init_frametable
//
///////////////////////////////////////////////////////////////////////////////////

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

	//	ambients
	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 [1], -1, NULL, -1, NULL, 0, -1, 0, -1, FRAME_ONCE);

	//	attacks
	ai_set_sequence_data (self, hook->frames->atak [0], 15, "monsters/spider/spiderattack1.wav", -1, NULL, 0, -1, 0, -1, FRAME_ONCE);

	//	deaths
	ai_set_sequence_data (self, hook->frames->death [0], -1, NULL, -1, NULL, 0, -1, 0, -1, FRAME_ONCE);

	//	jump
	ai_set_sequence_data (self, hook->frames->jump [0], 8, "monsters/spider/spiderattack2.wav", 22, "monsters/spider/spiderattack1.wav", 0, -1, 0, -1, FRAME_ONCE);

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

///////////////////////////////////////////////////////////////////////////////
//	spider_set_attack_seq
//
///////////////////////////////////////////////////////////////////////////////

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

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

	if (dist > 80 && hook->dflags & DFL_JUMPATTACK)
	{
		ai_init_sequence (self, hook->frames->jump [0], SEQUENCE_JUMP, 0);

		spider_jump_attack (self);
	}
	else
	{
		ai_init_sequence (self, hook->frames->atak [0], SEQUENCE_ATAK, 0);
		hook->frameInc = 2;

		spider_attack (self);
	}
}

///////////////////////////////////////////////////////////////////////////////
//	spider_jump_attack
//
///////////////////////////////////////////////////////////////////////////////

void	spider_jump_attack (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	float			dist;
	Vector			jump_ang, vel;
	
	//ai_face_enemy (self);
	hook->dflags |= DFL_FACEENEMY;

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

	if (hook->frame_flags & FRAME_PLAYSOUND1)
	{
		//	jump on this frame
		self->groundEntity = NULL;

		jump_ang = Vector (self->s.angles);
		jump_ang.AngleVectors (forward, right, up);

		vel = forward * hook->run_speed * 1.5;
		vel.set (self->velocity);
		self->velocity [2] = hook->upward_vel;

		hook->frame_flags = hook->frame_flags - FRAME_PLAYSOUND1;
	}
	
	if (hook->frame_flags & FRAME_PLAYSOUND2)
	{
		//	attack on this frame
		hook->frame_flags = hook->frame_flags - FRAME_PLAYSOUND2;
				
		ai_fire_curWeapon (self, Vector (self->s.origin), Vector (self->enemy->s.origin), 0, 0);
	}
	
	if (hook->frame_flags & FRAME_STATIC)
	{
		hook->frame_flags -= FRAME_STATIC;

		spider_set_attack_seq (self);

		if (self->enemy->deadflag != DEAD_NO)
		{
			//	pop off everything thru TASK_CHASE and begin wandering
			ai_killed_enemy (self);

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

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

			return;
		}
	}

	ai_set_think (self, spider_jump_attack, "spider_attack");
}

///////////////////////////////////////////////////////////////////////////////
//	spider_attack
//
///////////////////////////////////////////////////////////////////////////////

void	spider_attack (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	float			dist;
	
	//ai_face_enemy (self);
	hook->dflags |= DFL_FACEENEMY;

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

	if (hook->frame_flags & FRAME_PLAYSOUND1)
	{
		hook->frame_flags = hook->frame_flags - FRAME_PLAYSOUND1;
				
		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;
				
		ai_fire_curWeapon (self, Vector (self->s.origin), Vector (self->enemy->s.origin), 0, 0);
	}
	
	if (hook->frame_flags & FRAME_STATIC)
	{
		hook->frame_flags -= FRAME_STATIC;

		spider_set_attack_seq (self);

		if (self->enemy->deadflag != DEAD_NO)
		{
			//	pop off everything thru TASK_CHASE and begin wandering
			ai_killed_enemy (self);

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

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

			return;
		}
	}

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

///////////////////////////////////////////////////////////////////////////////
//	spider_begin_attack
//
///////////////////////////////////////////////////////////////////////////////

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

	com->ZeroVector (self->velocity);

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

	spider_set_attack_seq (self);
}

///////////////////////////////////////////////////////////////////////////////
//	monster_spider
//
//	spawns a skeleton during level load
///////////////////////////////////////////////////////////////////////////////

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

	spider_count++;

	hook = ai_init_monster (self, TYPE_SPIDER);

	self->className = "monster_spider";
	self->netname = "spider";

	///////////////////////////////////////////////////////////////////////////
	//	precache stuff
	///////////////////////////////////////////////////////////////////////////

	gstate->SoundIndex ("monsters/spider/spiderattack1.wav");
	gstate->SoundIndex ("monsters/spider/spiderattack2.wav");

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

	///////////////////////////////////////////////////////////////////////////
	// set up animation stuff
	///////////////////////////////////////////////////////////////////////////
	
	ai_get_sequences (self);
	spider_init_frametable (self);

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

	hook->dflags |= DFL_JUMPATTACK;

	hook->begin_attack = spider_begin_attack;

	hook->run_speed = 250;
	hook->walk_speed = 50;
	hook->attack_speed = 250;

	hook->jump_chance = 30;
	hook->attack_dist = 80;

	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;	// node links are set up 0.2 secs after map load

	self->translucent = 0;

	///////////////////////////////////////////////////////////////////////////
	//	give spider a weapon
	///////////////////////////////////////////////////////////////////////////

	self->curWeapon = ai_init_weapon (self, 10, 10, 0, 0, 0, hook->attack_dist, Vector (0, 0, 0), "punch", melee_punch, WEAPON_TRACE);
}

