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

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

static	int	sludge_count	= 0;

///////////////////////////////////////////////////////////////////////////////////
// sludge specific funcitons
///////////////////////////////////////////////////////////////////////////////////

void	sludge_ranged_attack (userEntity_t *self);

///////////////////////////////////////////////////////////////////////////////////
//	sludge_init_frametable
//
///////////////////////////////////////////////////////////////////////////////////

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

	//	running/walking
	ai_set_sequence_data (self, hook->frames->walk [0], 1, "monsters/inmater/inmaterstep1.wav", 15, "monsters/inmater/inmaterstep1.wav", 0, -1, 0, -1, FRAME_ONCE);
	ai_set_sequence_data (self, hook->frames->run [0], 1, "monsters/inmater/inmaterstep1.wav", 15, "monsters/inmater/inmaterstep2.wav", 0, -1, 0, -1, FRAME_ONCE);

	ai_set_sequence_data (self, hook->frames->atak [0], 10, NULL, 23, NULL, 0, -1, 0, -1, FRAME_ONCE);
}

///////////////////////////////////////////////////////////////////////////////
//	sludge_set_attack_seq
//
///////////////////////////////////////////////////////////////////////////////

void	sludge_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);

	ai_init_sequence (self, hook->frames->atak [0], SEQUENCE_ATAK, 0);

	sludge_ranged_attack (self);
}

///////////////////////////////////////////////////////////////////////////////
//	sludge_ranged_attack
//
///////////////////////////////////////////////////////////////////////////////

void	sludge_ranged_attack (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	int				task_type, task_type2, clear_shot = TRUE;
	float			dist;
	taskData_t		*task_data, *task_data2;
	taskStack_t		*stack;

	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;

		self->curWeapon = gstate->InventoryFindItem (self->inventory, "sludge right");
		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;
		
		self->curWeapon = gstate->InventoryFindItem (self->inventory, "sludge left");
		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;

		task_current (hook->task_stack, &task_data, &task_type);
		if (task_data->goal_type != GOAL_ENEMY)
			com->Error ("sludge: TASK_ATTACK without GOAL_ENEMY.\n");

		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) || hook->ai_flags & AI_END_ATTACK)
		{
			hook->ai_flags -= (hook->ai_flags & AI_END_ATTACK);

			//	check the next task to make sure it's not screwed
			stack = hook->task_stack->next;
			task_current (stack, &task_data, &task_type);
			if (task_type == TASK_CHASE && task_data->goal_type != GOAL_ENEMY)
				com->Error ("sludge: TASK_CHASE on stack without GOAL_ENEMY.\n");
	
			//	leaving, so pop off TASK_ATTACK
			task_pop (&hook->task_stack);

			task_current (hook->task_stack, &task_data2, &task_type2);
			if (task_type2 == TASK_CHASE && task_data2->goal_type != GOAL_ENEMY)
				com->Error ("sludge: TASK_CHASE without GOAL_ENEMY.\n");

			ai_should_follow (self);

			return;
		}

		sludge_set_attack_seq (self);

		return;
	}

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

///////////////////////////////////////////////////////////////////////////////
//	sludge_begin_attack
//
///////////////////////////////////////////////////////////////////////////////

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

	com->ZeroVector (self->velocity);

	sludge_set_attack_seq (self);

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

///////////////////////////////////////////////////////////////////////////////
//	monster_sludgeminion
//
//	spawns a skeleton during level load
///////////////////////////////////////////////////////////////////////////////

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

	sludge_count++;

	hook = ai_init_monster (self, TYPE_SLUDGEMINION);

	self->className = "monster_sludgeminion";
	self->netname = "Roboco SludgeMinion";

	gstate->SoundIndex ("monsters/inmater/inmaterstep1.wav");
	gstate->SoundIndex ("monsters/inmater/inmaterstep2.wav");

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

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

	ai_get_sequences (self);
	sludge_init_frametable (self);

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

	hook->begin_attack = sludge_begin_attack;
	hook->dflags |= DFL_MECHANICAL;

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

	hook->attack_dist = 650;

	self->ang_speed [1] = 180;

	self->health = 300;
	hook->dflags |= DFL_RANGEDATTACK;
	hook->max_health = 300;
	hook->pain_chance = 20;
	self->mass = 4.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 sludgeminion a weapon
	///////////////////////////////////////////////////////////////////////////

	self->inventory = gstate->InventoryNew ();

	self->curWeapon = ai_init_weapon (self, 20, 40, 0.024, 0, 900.0, hook->attack_dist, Vector (40, 16, 40), "sludge right", sludge_attack, WEAPON_PROJECTILE);
	gstate->InventoryAddItem (self->inventory, self->curWeapon);

	self->curWeapon = ai_init_weapon (self, 20, 40, 0.024, 0, 900.0, hook->attack_dist, Vector (-24, 16, 40), "sludge left", sludge_attack, WEAPON_PROJECTILE);
	gstate->InventoryAddItem (self->inventory, self->curWeapon);
}