////////////////////////////////////////////////////////////////////////////////////
//	the current start and end path_corner_track's for the gun are stored in the
//	tgunHook_s that is pointed to by hook->trackHook
//
////////////////////////////////////////////////////////////////////////////////////

#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"
#include	"chasecam.h"
#include	"actorlist.h"

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

DllExport	void	monster_trackattack (userEntity_t *self);
DllExport	void	path_corner_track (userEntity_t *self);

///////////////////////////////////////////////////////////////////////////////////
// define
///////////////////////////////////////////////////////////////////////////////////

#define	MAX_TRACK_LINKS	8

///////////////////////////////////////////////////////////////////////////////////
// typedefs
///////////////////////////////////////////////////////////////////////////////////

typedef	struct	pctHook_s
{
	// can link up to 8 other destinations from any path_corner_track
	char			*target_names	[MAX_TRACK_LINKS];
	userEntity_t	*target [MAX_TRACK_LINKS];
} pctHook_t;

typedef	struct	tgunHook_s
{
	userEntity_t	*start;
	userEntity_t	*end;

	userEntity_t	*targ;
	vec3_t			dest;

	Vector			to_start;
	Vector			to_end;

	userEntity_t	*upper;
	userEntity_t	*mid;
} tgunHook_t;

///////////////////////////////////////////////////////////////////////////////////
// trackattack specific funcitons
///////////////////////////////////////////////////////////////////////////////////

///////////////////////////////
//	trackattack_init_frametable
//
//	ai for following/approaching an enemy
///////////////////////////////

void	trackattack_init_frametable (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	
	ai_set_sequence_data (self, hook->frames->atak [0], 0, "monsters/trak/trakattack1.wav", 5, "monsters/trak/trakattack1.wav", 0, -1, 0, -1, FRAME_ONCE);
}

/////////////////////////////
//	trackattack_find_target
//
//	searches the entity list for targets using client_bot_list
//	returns true if a targetable entity was found
/////////////////////////////

int		trackattack_find_target (userEntity_t *self)
{
	userEntity_t	*head;
	userEntity_t	*item, *enemy;
	int				dist, item_d, enemy_d;
	playerHook_t	*hook = (playerHook_t *) self->userHook;

	item = enemy = NULL;
	item_d = enemy_d = 32767;
	
	//	FIXME: searches throught entire list...
	//	perhaps stupider monsters could stop searching at first visible
	//	monster or item
	for (head = alist_FirstEntity (client_bot_list); head; head = alist_NextEntity (client_bot_list))
	{
		if (head == self)
			continue;

		// is this a client or a bot?
		if (head->health > 0 && !(head->flags & FL_NOTARGET))
		{
			if (head->deadflag == DEAD_NO)
			{
				dist = qv_dist (self->s.origin, head->s.origin);

				if (dist < enemy_d)
				{
					if (ai_visible (self, head))
					{
						enemy = head;
						enemy_d = dist;
					}
				}
			}
		}
	}

	if (enemy)
	{
		if (hook->sight_sound && enemy != self->enemy) 
			hook->sight_sound (self);		

		self->enemy = enemy;
		ai_set_goal (self, self->enemy, self->enemy->s.origin, GOAL_ENEMY);

#ifdef	DEBUGINFO
		ai_debug_print (self, "sighted enemy %s\n", enemy->className);
#endif
	
		hook->begin_follow (self);

		return	TRUE;
	}

	return	FALSE;
}

///////////////////////////////
//	trackattack_face_goal
//
//	ai for following/approaching an enemy
///////////////////////////////

void	trackattack_face_goal (userEntity_t *self)
{
	Vector			dir, ang;
	float			yaw;
	playerHook_t	*hook = (playerHook_t *) self->userHook;

	dir = Vector (self->goalentity->s.origin) - Vector (self->s.origin);
	dir.Normalize ();

	com->VecToAngles (ang, dir);
	self->ideal_ang [1] = ang.y;

	self->ideal_ang [0] = ang.x;

	com->ChangeYaw (self);

	com->ChangePitch (self);
//	self->s.angles [0] = ang.x;
}

///////////////////////////////
//	trackattack_set_targ
//
///////////////////////////////

void	trackattack_set_targ (userEntity_t *self, userEntity_t *targ)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	tgunHook_t		*ghook = (tgunHook_t *) hook->trackHook;

	ghook->targ = targ;
	com->CopyVector (ghook->dest, targ->s.origin);
	ghook->dest [2] -= 30;
}


///////////////////////////////
//	trackattack_movetogoal
//
//	ai for following/approaching an enemy
//	goal is enemy, but since tracked turrets
//	can't move directly towards enemy, this moves
//	it along the track in the best direction
//	towards its enemy
//
///////////////////////////////

void	trackattack_movetogoal (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	tgunHook_t		*ghook = (tgunHook_t *) hook->trackHook;
	Vector			temp;
	float			start_dist, end_dist;

	start_dist = qv_dist (ghook->start->s.origin, self->goalentity->s.origin);
	end_dist = qv_dist (ghook->end->s.origin, self->goalentity->s.origin);

	if (start_dist < end_dist)
	{
		temp = ghook->to_start * hook->run_speed;
		trackattack_set_targ (self, ghook->start);
	}
	else
	{
		temp = ghook->to_end * hook->run_speed;
		trackattack_set_targ (self, ghook->end);
	}

	if (qv_dist (ghook->dest, self->s.origin) > (hook->run_speed * THINK_TIME * 1.5))
		temp.set (self->velocity);
	else
		com->ZeroVector (self->velocity);

//	gstate->SetModel (ghook->targ, "models/debug/goal.mdl");
}

///////////////////////////////
//	trackattack_checknewrail
//
//	determines if the turret has reached
//	the end of a rail
//
//	if so, the start and end targets are
//	updated, according to which rail provides
//	the best path to the enemy
///////////////////////////////

void	trackattack_checknewrail (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	tgunHook_t		*ghook = (tgunHook_t *) hook->trackHook;
	pctHook_t		*phook;
	Vector			org;
	float			start_dist, end_dist, best_dist;
	int				best_track, i;

	end_dist = qv_dist (ghook->dest, self->s.origin);

	if (end_dist > (hook->run_speed * THINK_TIME * 1.5))
		return;

	if (ghook->targ == ghook->end)
		ghook->start = ghook->end;

//	gstate->SetModel (ghook->start, "models/debug/node.mdl");
//	gstate->SetModel (ghook->end, "models/debug/node.mdl");

	com->ZeroVector (self->velocity);

	//	place turret exactly on the path_corner_train
	gstate->SetOrigin (self, ghook->start->s.origin [0], ghook->start->s.origin [1], ghook->start->s.origin [2] - 30.0);

	///////////////////////////////////////////////////////////////////////
	//	find the best rail out of all the rails available at this junction
	//	make that the ghook->end
	///////////////////////////////////////////////////////////////////////

	best_track = MAX_TRACK_LINKS;
	best_dist = 32767;
	phook = (pctHook_t *) ghook->start->userHook;

	for (i = 0; i < MAX_TRACK_LINKS; i++)
	{
		if (phook->target [i])
		{
			end_dist = qv_dist (self->goalentity->s.origin, phook->target [i]->s.origin);
			if (end_dist < best_dist)
			{
				best_dist = end_dist;
				best_track = i;
			}
		}
	}

	if (best_track < MAX_TRACK_LINKS)
		ghook->end = phook->target [best_track];
	else
		ghook->end = phook->target [0];

	if (ghook->end == ghook->start)
	{
		com->Error ("trackattack_checknewrail: start track == end track!");
		return;
	}

//	gstate->SetModel (ghook->end, "models/debug/curnode.mdl");
	
	ghook->to_end = Vector (ghook->end->s.origin) - Vector (ghook->start->s.origin);
	ghook->to_end.Normalize ();

	ghook->to_start = ghook->to_end * -1;

	//	orient top piece of turret to direction of track
	ghook->upper->s.angles [1] = com->VecToYaw (ghook->to_end);
}

///////////////////////////////
//	trackattack_attack
//
//	ai for following/approaching an enemy
///////////////////////////////

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

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

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

	if (self->enemy->deadflag != DEAD_NO)
	{
		ai_set_think (self, hook->begin_stand, "trackattack_attack");

		return;
	}
	else if (dist > hook->attack_dist + 64.0 || !com->Visible (self, self->enemy))
	{
		ai_set_think (self, hook->begin_follow, "trackattack_attack");

		return;
	}

	if (hook->frame_flags & FRAME_PLAYSOUND1)
	{
		if (hook->sound1)
			gstate->sound (self, CHAN_AUTO, hook->sound1, 128, ATTN_NORM);
		
		hook->frame_flags = hook->frame_flags - FRAME_PLAYSOUND1;

		ai_fire_curWeapon (self, Vector (self->s.origin), Vector (self->enemy->s.origin) + Vector (self->enemy->view_ofs), 0, 0);
	}

	if (hook->frame_flags & FRAME_PLAYSOUND2)
	{
		if (hook->sound2)
			gstate->sound (self, CHAN_AUTO, hook->sound2, 128, ATTN_NORM);
		
		hook->frame_flags = hook->frame_flags - FRAME_PLAYSOUND2;

		ai_fire_curWeapon (self, Vector (self->s.origin), Vector (self->enemy->s.origin) + Vector (self->enemy->view_ofs), 0, 0);
//		ai_fire_projectile (self, self->enemy, Vector (0, 32, 14), 0, 0, 750, "models/ta_laser.mdl", trackattack_laser_touch, EF_FULLBRIGHT);
	}

	if (hook->frame_flags & FRAME_STATIC)
	{
		ai_set_think (self, hook->begin_follow, "trackattack_attack");

		hook->frame_flags -= FRAME_STATIC;	
		return;
	}

	trackattack_movetogoal (self);
	trackattack_checknewrail (self);

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

///////////////////////////////
//	trackattack_begin_attack
//	
//	ai for following/approaching an enemy
///////////////////////////////

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

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

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

	trackattack_attack (self);
}

///////////////////////////////
//	trackattack_follow
//
//	a track attack's movement is locked into
//	a straight line which is defined by the
//	rail it is currently connected to
///////////////////////////////

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

	ai_debug_info (self, "trackattack_follow", NULL);

	if (com->Visible (self, self->enemy))
	{
		com->CopyVector (self->goalentity->s.origin, self->enemy->s.origin);

		//trackattack_face_goal (self);

		if (hook->attack_finished <= gstate->time)
		{
			ai_set_think (self, hook->begin_attack, "trackattack_follow");
			return;
		}
	}

	trackattack_movetogoal (self);
	trackattack_checknewrail (self);

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

///////////////////////////////
//	trackattack_mid_drop_touch
//
///////////////////////////////

void	trackattack_drop_touch (userEntity_t *self, userEntity_t *other, cplane_t *plane, csurface_t *surf)
{
	if (qv_len (self->velocity) > 10.0)
	{
		self->avelocity [0] = rnd () * 400 - 200;
		self->avelocity [1] = rnd () * 400 - 200;
		self->avelocity [2] = rnd () * 400 - 200;
	}
	else
		self->touch = NULL;
}

///////////////////////////////
//	trackattack_pitchback
//
///////////////////////////////

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

#ifdef DEBUGINFO
	ai_debug_info (self, "ai_die", NULL);
#endif

	ai_frame_sounds (self);	

	com->ChangePitch (self);

	if (self->ideal_ang [0] == self->s.angles [0])
//	if (hook->frame_flags & FRAME_STATIC)
	{

		//	Q2FIXME:	FL_POSSESSED is being set for some reason...
/*
		if (self->flags & FL_POSSESSED)
		{
			// FIXME: put the possesser back in their own body
			// this does it right now, but it's just a hack
			camera_stop (hook->demon);
		}
*/
		self->deadflag = DEAD_DEAD;
		ai_remove_goal (self->goalentity);

		self->prethink = NULL;
		self->postthink = NULL;
		self->think = NULL;

		return;
	}

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

///////////////////////////////
//	trackattack_mid_drop
//
///////////////////////////////

void	trackattack_mid_drop (userEntity_t *self)
{
	self->movetype = MOVETYPE_BOUNCE;
	self->touch = trackattack_drop_touch;
}

///////////////////////////////
//	trackattack_begin_die
//
///////////////////////////////

void	trackattack_begin_die (userEntity_t *self, userEntity_t *inflictor, userEntity_t *attacker, int damage, vec3_t point)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	tgunHook_t		*ghook = (tgunHook_t *) hook->trackHook;

	com->SetVector (self->view_ofs, 0, 0, -8.0);
	self->deadflag = DEAD_DYING;
	self->takedamage = DAMAGE_NO;
	self->solid = SOLID_NOT;
	self->movetype = MOVETYPE_BOUNCE;

	gstate->hr_RemoveChild (self, ghook->upper, false);
	ghook->upper->movetype = MOVETYPE_NONE;

	gstate->hr_RemoveChild (self, ghook->mid, false);
	ghook->mid->movetype = MOVETYPE_NONE;
	ghook->mid->think = trackattack_mid_drop;
	ghook->mid->nextthink = gstate->time + 1.0 + rnd () * 3.0;
	ghook->mid->s.angles [0] = rnd () * 80 - 40;
	gstate->SetSize (ghook->mid, 0, 0, 0, 0, 0, 0);

//	self->flags -= FL_STICKYPARENT;
//	self->touch = trackattack_drop_touch;

	self->ideal_ang [0] = -15;
	ai_set_think (self, trackattack_pitchback, "trackattack_begin_die");

//	ai_die (self);
}

///////////////////////////////
//	trackattack_begin_follow
//
///////////////////////////////

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

	ai_debug_print (self, "trackattack_follow");

	hook->th_state = TH_FOLLOW;

	self->s.frame = hook->startFrame = hook->frames->stand [0]->first;
	hook->endFrame = hook->frames->stand [0]->last;
	hook->frame_flags = FRAME_LOOP;
	hook->frameInc = 1;	

	ai_set_sequence_sounds (self, -1, NULL, -1, NULL);

	trackattack_follow (self);
}

///////////////////////////////
//	trackattack_spawn
//
//	spawns the track attack at its targetted path corner
//	once all entities have been spawned
///////////////////////////////

void	trackattack_spawn (userEntity_t *self)
{
	playerHook_t		*hook = (playerHook_t *) self->userHook;
	pctHook_t			*phook;
	tgunHook_t			*ghook;
	userEntity_t		*upper, *mid, *path;
	Vector				org;

	////////////////////////////////////////////////////////////////
	//	find the targetted path_corner_track
	////////////////////////////////////////////////////////////////

	if (!(path = com->FindTarget (self->target)))
	{
		com->Error ("Track turret has no spawn target.");
		return;
	}

	phook = (pctHook_t *) path->userHook;
	
	////////////////////////////////////////////////////////////////
	//	spawn there
	////////////////////////////////////////////////////////////////

	gstate->SetModel (self, "models/tatakgun.mdl");
	gstate->SetSize (self, -16.0, -16.0, -24.0, 16.0, 16.0, 24.0);
	gstate->SetOrigin (self, path->s.origin [0], path->s.origin [1], path->s.origin [2] - 30.0);	

	////////////////////////////////////////////////////////////////
	//	set up hierarchy
	////////////////////////////////////////////////////////////////

	// upper clamping arm of gun
	upper = gstate->SpawnEntity ();
	upper->solid = self->solid;
	upper->className = "trackattack_upper";

	gstate->SetModel (upper, "models/tataktop.mdl");
	gstate->SetSize (upper, 0, 0, 0, 0, 0, 0);

	org = Vector (self->s.origin);
	org.z += 24.0;
	gstate->SetOrigin2 (upper, org.vec ());	

	gstate->hr_InitRelative (self, upper, HRF_NOPITCH + HRF_NOYAW + HRF_NOROLL);

	// middle swivel joint of gun
	mid = gstate->SpawnEntity ();
	mid->solid = self->solid;
	mid->className = "trackattack_mid";

	gstate->SetModel (mid, "models/tatakmid.mdl");
	gstate->SetSize (mid, 0, 0, 0, 0, 0, 0);

	org = Vector (self->s.origin);
	org.z += 24.0;
	gstate->SetOrigin2 (mid, org.vec ());

	gstate->hr_InitRelative (self, mid, HRF_NOPITCH + HRF_NOROLL);

	////////////////////////////////////////////////////////////////
	//	set up the start and end targets for this rail
	////////////////////////////////////////////////////////////////

	hook->trackHook = com->malloc (sizeof (tgunHook_t), MEM_MALLOC);
	ghook = (tgunHook_t *) hook->trackHook;

	ghook->upper = upper;
	ghook->mid = mid;

	ghook->start = path;
	trackattack_set_targ (self, path);

	if (!(ghook->end = phook->target [0]))
		ai_set_think (self, NULL, "trackattack_spawn");
	else
	{
		// find and save directions of travel
		ghook->to_start = Vector (ghook->start->s.origin) - Vector (ghook->end->s.origin);
		ghook->to_start.Normalize ();

		ghook->to_end = ghook->to_start * -1;

//		gstate->SetModel (ghook->start, "models/debug/node.mdl");
//		gstate->SetModel (ghook->end, "models/debug/curnode.mdl");

		ai_set_think (self, hook->begin_stand, "trackattack_spawn");
	}
}

///////////////////////////////
//  trackattack_stand
//
///////////////////////////////

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

#ifdef DEBUGINFO
	ai_debug_info (self, "ai_stand", NULL);
#endif

	if (trackattack_find_target (self))
		return;

	if (hook->wander_sound) 
		hook->wander_sound (self);

	ai_frame_sounds (self);	

	// do an ambient standing sequence
	// FIXME: won't search for targets while doing this...
	// may be a problem for long ambients, may need a special
	// transition think for this
	if (hook->frame_flags & FRAME_LAST)
	{
		hook->frame_flags -= FRAME_LAST;

		if (rnd () < 0.2)
		{
			if (hook->sequence_max [SEQUENCE_STAND] > 1)
			{
				i = (int) (rnd () * (hook->sequence_max [SEQUENCE_STAND] - 1)) + 1;
				
//				ai_set_sequence_sounds (self, hook->frames->stand [i]->soundframe1, hook->frames->stand [i]->sound1, 
//					  hook->frames->stand [i]->soundframe2, hook->frames->stand [i]->sound2);

//				ai_begin_transition (self, hook->frames->stand [i]->first, hook->frames->stand [i]->last, hook->begin_stand);
				ai_begin_transition (self, hook->frames->stand [i], SEQUENCE_STAND, i, hook->begin_stand);

				return;
			}
		}
	}

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

///////////////////////////////
//	trackattack_begin_stand
//
///////////////////////////////

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

	hook->th_state = TH_STAND;

	com->ZeroVector (self->velocity);
	
	self->enemy = self;
	ai_set_goal (self, self, self->s.origin, GOAL_ENEMY);

	ai_init_sequence (self, hook->frames->stand [0], SEQUENCE_STAND, 0);

	trackattack_stand (self);
}

////////////////////////////
//	trackattack_prethink
//
////////////////////////////

void	trackattack_prethink (userEntity_t *self)
{
	playerHook_t	*hook = (playerHook_t *) self->userHook;
	Vector			end;

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

//	if (self->goalentity)
//		trackattack_face_goal (self);
}

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

void	monster_trackattack (userEntity_t *self)
{
	playerHook_t		*hook;
	userEntity_t		*upper, *mid;
	Vector				org;

//	return;

	hook = ai_init_monster (self, TYPE_TRACKATTACK);

	self->className = "monster_trackattack";
	self->netname = "Roboco TrackAttack";
	self->movetype = MOVETYPE_FLY;

	gstate->Precache_Sound ("monsters/trak/trakattack1.wav");
	gstate->Precache_Sound ("monsters/trak/trakhit1.wav");

	gstate->Precache_Model ("models/tatakgun.mdl");
	gstate->Precache_Model ("models/tatakmid.mdl");
	gstate->Precache_Model ("models/tataktop.mdl");
	gstate->Precache_Model ("models/ta_laser.mdl");
	gstate->SetModel (self, "models/tatakgun.mdl");

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

	ai_get_sequences (self);

	trackattack_init_frametable (self);

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

	self->ang_speed [1] = 5.0;

	hook->begin_stand = trackattack_begin_stand;
	hook->begin_attack = trackattack_begin_attack;
	hook->begin_follow = trackattack_begin_follow;
	
	self->die = trackattack_begin_die;

	hook->run_speed = 160;
	hook->walk_speed = 80;
	hook->dflags |= (DFL_RANGEDATTACK + DFL_FACEPITCH);
	hook->attack_dist = 1024;

//	self->prethink = trackattack_prethink;

	hook->think_time = 0.05;
	self->think = trackattack_spawn;
	self->nextthink = gstate->time + 0.2;  // make sure it happens after path_corner_track_relinks

	self->curWeapon = ai_init_weapon (self, 15, 10, 0, 0, 950.0, hook->attack_dist, Vector (0, 32, 48), "laser", laser_fire, WEAPON_PROJECTILE);
}

//////////////////////////////////
//	path_corner_track_relink
//
//	relinks path_corner_track once all path_corner_tracks have been spawned
//////////////////////////////////

void	path_corner_track_relink (userEntity_t *self)
{
	pctHook_t	*hook = (pctHook_t *) self->userHook;
	char		msg	[128];
	int			i;

	for (i = 0; i < MAX_TRACK_LINKS; i++)
	{
		if (hook->target_names [i])
		{
			hook->target [i] = com->FindTarget (hook->target_names [i]);
			if (!hook->target [i])
			{
				com->Error ("Bad target%i on path_corner_track %s", i, self->targetname);
				return;
			}
		}
	}

	self->think = NULL;
	self->nextthink = 0;
}

//////////////////////////////////
//	path_corner_track
//
//////////////////////////////////

void	path_corner_track (userEntity_t *self)
{
	int			i, j;
	char		key [128];
	pctHook_t	*hook;

	self->userHook = com->malloc_hook (sizeof (pctHook_t), MEM_MALLOC);
	hook = (pctHook_t *) self->userHook;

	for (i = 0; self->epair [i].key; i++)
	{
		if (!stricmp (self->epair [i].key, "targetname"))
		{
			self->targetname = self->epair [i].value;
			gstate->Con_Dprintf ("path_corner_track %s\n", self->targetname);
		}
		else
		{
			// save up to MAX_TRACK_LINKS targets in the userhook
			for (j = 0; j < MAX_TRACK_LINKS;  j++)
			{
				if (j == 0)
					strcpy (key, "target");
				else
					sprintf (key, "target%i", j);
				
				if (!stricmp (self->epair [i].key, key))
				{
					hook->target_names [j] = self->epair [i].value;
					gstate->Con_Dprintf ("  %s\n", hook->target_names [j]);
				}
			}
		}
	}

//	gstate->SetModel (self, "models/debug/node.mdl");
	self->modelName = NULL;

	ai_set_think (self, path_corner_track_relink, "path_corner_track");
}