/*
==============================================================================

BOT AI

==============================================================================
*/

// Prototypes

float   ()                                             BotFindTarget;
void    ()                                             bot_ai_stand;
void    (entity attacker, float damage)                bot_pain;
void    ()                                             bot_die;
void    ()                                             BotSightSound;
void    ()                                             BotFoundTarget;
void    ()                                             BotHuntTarget;
void    (float dist)                                   bot_ai_walk;
void    (float dist)                                   man_bot_ai_walk;
void    ()                                             bot_ai_turn;
void    (float dist)                                   bot_ai_run;
void    (float dist)                                   man_bot_ai_run;
void    (float dist)                                   bot_ai_follow;
void    (void () thinkst)                              BotCheckRefire;
void    ()                                             BotSelfDeActivate;
void    ()                                             bot_fire;
void    ()                                             bot_fire2;
void    ()                                             enforcer_fire;
void    (vector offset)                                benforcer_fire;
void    (vector org, vector dir)                       launch_spike;
void    (vector org, vector dir)                       glaunch_spike;
void    ()                                             spike_touch; 
// Frame macros

$cd /raid/quake/id1/models/enforcer
$origin 0 -6 24
$base base		
$skin skin

$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7

$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9 walk10
$frame walk11 walk12 walk13 walk14 walk15 walk16

$frame run1 run2 run3 run4 run5 run6 run7 run8

$frame attack1 attack2 attack3 attack4 attack5 attack6
$frame attack7 attack8 attack9 attack10

$frame death1 death2 death3 death4 death5 death6 death7 death8
$frame death9 death10 death11 death12 death13 death14

$frame fdeath1 fdeath2 fdeath3 fdeath4 fdeath5 fdeath6 fdeath7 fdeath8
$frame fdeath9 fdeath10 fdeath11

$frame paina1 paina2 paina3 paina4

$frame painb1 painb2 painb3 painb4 painb5

$frame painc1 painc2 painc3 painc4 painc5 painc6 painc7 painc8

$frame paind1 paind2 paind3 paind4 paind5 paind6 paind7 paind8
$frame paind9 paind10 paind11 paind12 paind13 paind14 paind15 paind16
$frame paind17 paind18 paind19

void()	bot_stand1	=[	$stand1,	bot_stand2	] {bot_ai_stand();};
void()	bot_stand2	=[	$stand2,	bot_stand3	] {bot_ai_stand();};
void()	bot_stand3	=[	$stand3,	bot_stand4	] {bot_ai_stand();};
void()	bot_stand4	=[	$stand4,	bot_stand5	] {bot_ai_stand();};
void()	bot_stand5	=[	$stand5,	bot_stand6	] {bot_ai_stand();};
void()	bot_stand6	=[	$stand6,	bot_stand7	] {bot_ai_stand();};
void()	bot_stand7	=[	$stand7,	bot_stand1	] {bot_ai_stand();};

void()	man_bot_stand1	=[	$stand1,	man_bot_stand2	] {ChangeYaw();};
void()	man_bot_stand2	=[	$stand2,	man_bot_stand3	] {ChangeYaw();};
void()	man_bot_stand3	=[	$stand3,	man_bot_stand4	] {ChangeYaw();};
void()	man_bot_stand4	=[	$stand4,	man_bot_stand5	] {ChangeYaw();};
void()	man_bot_stand5	=[	$stand5,	man_bot_stand6	] {ChangeYaw();};
void()	man_bot_stand6	=[	$stand6,	man_bot_stand7	] {ChangeYaw();};
void()	man_bot_stand7	=[	$stand7,	man_bot_stand1	] {ChangeYaw();};

void()	man_bot_walk1	=[	$walk1 ,	man_bot_walk2	]
{
	if (random() < 0.2)
		sound (self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE);
	man_bot_ai_walk(3);
};
void()	man_bot_walk2	=[	$walk2 ,	man_bot_walk3	] {man_bot_ai_walk(5);};
void()	man_bot_walk3	=[	$walk3 ,	man_bot_walk4	] {man_bot_ai_walk(5);};
void()	man_bot_walk4	=[	$walk4 ,	man_bot_walk5	] {man_bot_ai_walk(4);};
void()	man_bot_walk5	=[	$walk5 ,	man_bot_walk6	] {man_bot_ai_walk(2);};
void()	man_bot_walk6	=[	$walk6 ,	man_bot_walk7	] {man_bot_ai_walk(3);};
void()	man_bot_walk7	=[	$walk7 ,	man_bot_walk8	] {man_bot_ai_walk(3);};
void()	man_bot_walk8	=[	$walk8 ,	man_bot_walk9	] {man_bot_ai_walk(2);};
void()	man_bot_walk9	=[	$walk9 ,	man_bot_walk10	] {man_bot_ai_walk(3);};
void()	man_bot_walk10	=[	$walk10,	man_bot_walk11	] {man_bot_ai_walk(5);};
void()	man_bot_walk11	=[	$walk11,	man_bot_walk12	] {man_bot_ai_walk(5);};
void()	man_bot_walk12	=[	$walk12,	man_bot_walk13	] {man_bot_ai_walk(2);};
void()	man_bot_walk13	=[	$walk13,	man_bot_walk14	] {man_bot_ai_walk(3);};
void()	man_bot_walk14	=[	$walk14,	man_bot_walk15	] {man_bot_ai_walk(4);};
void()	man_bot_walk15	=[	$walk15,	man_bot_walk16	] {man_bot_ai_walk(5);};
void()	man_bot_walk16	=[	$walk16,	man_bot_walk1	] {man_bot_ai_walk(3);};

void()	bot_walk1	=[	$walk1 ,	bot_walk2	]
{
	if (random() < 0.2)
		sound (self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE);
	bot_ai_walk(4);
};
void()	bot_walk2	=[	$walk2 ,	bot_walk3	] {bot_ai_walk(8);};
void()	bot_walk3	=[	$walk3 ,	bot_walk4	] {bot_ai_walk(8);};
void()	bot_walk4	=[	$walk4 ,	bot_walk5	] {bot_ai_walk(6);};
void()	bot_walk5	=[	$walk5 ,	bot_walk6	] {bot_ai_walk(2);};
void()	bot_walk6	=[	$walk6 ,	bot_walk7	] {bot_ai_walk(4);};
void()	bot_walk7	=[	$walk7 ,	bot_walk8	] {bot_ai_walk(4);};
void()	bot_walk8	=[	$walk8 ,	bot_walk9	] {bot_ai_walk(2);};
void()	bot_walk9	=[	$walk9 ,	bot_walk10	] {bot_ai_walk(4);};
void()	bot_walk10	=[	$walk10,	bot_walk11	] {bot_ai_walk(8);};
void()	bot_walk11	=[	$walk11,	bot_walk12	] {bot_ai_walk(8);};
void()	bot_walk12	=[	$walk12,	bot_walk13	] {bot_ai_walk(2);};
void()	bot_walk13	=[	$walk13,	bot_walk14	] {bot_ai_walk(4);};
void()	bot_walk14	=[	$walk14,	bot_walk15	] {bot_ai_walk(6);};
void()	bot_walk15	=[	$walk15,	bot_walk16	] {bot_ai_walk(8);};
void()	bot_walk16	=[	$walk16,	bot_walk1	] {bot_ai_walk(4);};

void()	bot_run1	=[	$run1  ,	bot_run2	]
{
	if (random() < 0.2)
		sound (self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE);
	bot_ai_run(18);
};
void()	bot_run2	=[	$run2  ,	bot_run3	] {bot_ai_run(14);};
void()	bot_run3	=[	$run3  ,	bot_run4	] {bot_ai_run(7);};
void()	bot_run4	=[	$run4  ,	bot_run5	] {bot_ai_run(12);};
void()	bot_run5	=[	$run5  ,	bot_run6	] {bot_ai_run(14);};
void()	bot_run6	=[	$run6  ,	bot_run7	] {bot_ai_run(14);};
void()	bot_run7	=[	$run7  ,	bot_run8	] {bot_ai_run(7);};
void()	bot_run8	=[	$run8  ,	bot_run1	] {bot_ai_run(11);};

void()	man_bot_run1	=[	$run1  ,	man_bot_run2	]
{
	if (random() < 0.2)
		sound (self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE);
	man_bot_ai_run(18);
};
void()	man_bot_run2	=[	$run2  ,	man_bot_run3	] {man_bot_ai_run(14);};
void()	man_bot_run3	=[	$run3  ,	man_bot_run4	] {man_bot_ai_run(7);};
void()	man_bot_run4	=[	$run4  ,	man_bot_run5	] {man_bot_ai_run(12);};
void()	man_bot_run5	=[	$run5  ,	man_bot_run6	] {man_bot_ai_run(14);};
void()	man_bot_run6	=[	$run6  ,	man_bot_run7	] {man_bot_ai_run(14);};
void()	man_bot_run7	=[	$run7  ,	man_bot_run8	] {man_bot_ai_run(7);};
void()	man_bot_run8	=[	$run8  ,	man_bot_run1	] {man_bot_ai_run(11);};

void()	bot_follow1	=[	$run1  ,	bot_follow2	]
{
	if (random() < 0.2)
		sound (self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE);
	self.goalentity = self.movetarget = self.owner;
	bot_ai_follow(18);
};
void()	bot_follow2	=[	$run2  ,	bot_follow3	] {bot_ai_follow(14);};
void()	bot_follow3	=[	$run3  ,	bot_follow4	] {bot_ai_follow(7);};
void()	bot_follow4	=[	$run4  ,	bot_follow5	] {bot_ai_follow(12);};
void()	bot_follow5	=[	$run5  ,	bot_follow6	] {bot_ai_follow(14);};
void()	bot_follow6	=[	$run6  ,	bot_follow7	] {bot_ai_follow(14);};
void()	bot_follow7	=[	$run7  ,	bot_follow8	] {bot_ai_follow(7);};
void()	bot_follow8	=[	$run8  ,	bot_follow1	] {bot_ai_follow(11);};

void()	bot_atk1	=[	$attack1,	bot_atk2	] {ai_face();};
void()	bot_atk2	=[	$attack2,	bot_atk3	] {ai_face();};
void()	bot_atk3	=[	$attack3,	bot_atk4	] {ai_face();};
void()	bot_atk4	=[	$attack4,	bot_atk5	] {ai_face();};
void()	bot_atk5	=[	$attack5,	bot_atk6	] {ai_face();};
void()  bot_atk6        =[      $attack6,       bot_atk7        ] {bot_fire2();};
void()  bot_atk7        =[      $attack6,       bot_atk8        ] {bot_fire();};
void()  bot_atk8        =[      $attack5,       bot_atk9        ] {bot_fire2();};
void()  bot_atk9        =[      $attack6,       bot_atk10       ] {bot_fire();};
void()  bot_atk10       =[      $attack5,       bot_atk11       ] {bot_fire2();};
void()  bot_atk11       =[      $attack6,       bot_atk12       ] {bot_fire();};
void()  bot_atk12       =[      $attack5,       bot_atk13       ] {bot_fire2();};
void()  bot_atk13       =[      $attack6,       bot_atk14       ] {bot_fire();};
void()  bot_atk14       =[      $attack5,       bot_atk15       ] {bot_fire2();};
void()  bot_atk15       =[      $attack6,       bot_atk16       ] {bot_fire2();};
void()  bot_atk16       =[      $attack5,       bot_atk17       ] {bot_fire();};
void()  bot_atk17       =[      $attack6,       bot_atk18       ] {bot_fire2();};
void()  bot_atk18       =[      $attack7,       bot_atk19       ] {ai_face();};
void()  bot_atk19       =[      $attack8,       bot_atk20       ] {ai_face();};
void()  bot_atk20       =[      $attack9,       bot_atk21       ] {ai_face();};
void()  bot_atk21       =[      $attack10,      bot_run1        ]

{
	ai_face();
	BotCheckRefire (bot_atk1);
};

void()	bot_paina1	=[	$paina1,	bot_paina2	] {};
void()	bot_paina2	=[	$paina2,	bot_paina3	] {};
void()	bot_paina3	=[	$paina3,	bot_paina4	] {};
void()	bot_paina4	=[	$paina4,	bot_run1	] {};

void()	bot_painb1	=[	$painb1,	bot_painb2	] {};
void()	bot_painb2	=[	$painb2,	bot_painb3	] {};
void()	bot_painb3	=[	$painb3,	bot_painb4	] {};
void()	bot_painb4	=[	$painb4,	bot_painb5	] {};
void()	bot_painb5	=[	$painb5,	bot_run1	] {};

void()	bot_painc1	=[	$painc1,	bot_painc2	] {};
void()	bot_painc2	=[	$painc2,	bot_painc3	] {};
void()	bot_painc3	=[	$painc3,	bot_painc4	] {};
void()	bot_painc4	=[	$painc4,	bot_painc5	] {};
void()	bot_painc5	=[	$painc5,	bot_painc6	] {};
void()	bot_painc6	=[	$painc6,	bot_painc7	] {};
void()	bot_painc7	=[	$painc7,	bot_painc8	] {};
void()	bot_painc8	=[	$painc8,	bot_run1	] {};

void()	bot_paind1	=[	$paind1,	bot_paind2	] {};
void()	bot_paind2	=[	$paind2,	bot_paind3	] {};
void()	bot_paind3	=[	$paind3,	bot_paind4	] {};
void()	bot_paind4	=[	$paind4,	bot_paind5	] {ai_painforward(2);};
void()	bot_paind5	=[	$paind5,	bot_paind6	] {ai_painforward(1);};
void()	bot_paind6	=[	$paind6,	bot_paind7	] {};
void()	bot_paind7	=[	$paind7,	bot_paind8	] {};
void()	bot_paind8	=[	$paind8,	bot_paind9	] {};
void()	bot_paind9	=[	$paind9,	bot_paind10	] {};
void()	bot_paind10	=[	$paind10,	bot_paind11	] {};
void()	bot_paind11	=[	$paind11,	bot_paind12	] {ai_painforward(1);};
void()	bot_paind12	=[	$paind12,	bot_paind13	] {ai_painforward(1);};
void()	bot_paind13	=[	$paind13,	bot_paind14	] {ai_painforward(1);};
void()	bot_paind14	=[	$paind14,	bot_paind15	] {};
void()	bot_paind15	=[	$paind15,	bot_paind16	] {};
void()	bot_paind16	=[	$paind16,	bot_paind17	] {ai_pain(1);};
void()	bot_paind17	=[	$paind17,	bot_paind18	] {ai_pain(1);};
void()	bot_paind18	=[	$paind18,	bot_paind19	] {};
void()	bot_paind19	=[	$paind19,	bot_run1	] {};

void()	bot_die1	=[	$death1,	bot_die2	] {};
void()	bot_die2	=[	$death2,	bot_die3	] {};
void()	bot_die3	=[	$death3,	bot_die4	]
{
	self.solid = SOLID_NOT;
	self.ammo_cells = 5;
	DropBackpack();
};
void()	bot_die4	=[	$death4,	bot_die5	] {ai_forward(14);};
void()	bot_die5	=[	$death5,	bot_die6	] {ai_forward(2);};
void()	bot_die6	=[	$death6,	bot_die7	] {};
void()	bot_die7	=[	$death7,	bot_die8	] {};
void()	bot_die8	=[	$death8,	bot_die9	] {};
void()	bot_die9	=[	$death9,	bot_die10	] {ai_forward(3);};
void()	bot_die10	=[	$death10,	bot_die11	] {ai_forward(5);};
void()	bot_die11	=[	$death11,	bot_die12	] {ai_forward(5);};
void()	bot_die12	=[	$death12,	bot_die13	] {ai_forward(5);};
void()	bot_die13	=[	$death13,	bot_die14	] {};
void()	bot_die14	=[	$death14,	bot_die14	] {BotSelfDeActivate();};

void()	bot_fdie1	=[	$fdeath1,	bot_fdie2	] {};
void()	bot_fdie2	=[	$fdeath2,	bot_fdie3	] {};
void()	bot_fdie3	=[	$fdeath3,	bot_fdie4	] 
{
	self.solid = SOLID_NOT;
	self.ammo_cells = 5;
	DropBackpack();
};
void()	bot_fdie4	=[	$fdeath4,	bot_fdie5	] {};
void()	bot_fdie5	=[	$fdeath5,	bot_fdie6	] {};
void()	bot_fdie6	=[	$fdeath6,	bot_fdie7	] {};
void()	bot_fdie7	=[	$fdeath7,	bot_fdie8	] {};
void()	bot_fdie8	=[	$fdeath8,	bot_fdie9	] {};
void()	bot_fdie9	=[	$fdeath9,	bot_fdie10	] {};
void()	bot_fdie10	=[	$fdeath10,	bot_fdie11	] {};
void()	bot_fdie11	=[	$fdeath11,	bot_fdie11	] {BotSelfDeActivate();};



//=============================================================
// BotFindTarget
// Self is currently not attacking anything, so try to find a target
// Will not currently target other players
// Sets self.enemy and returns TRUE if an enemy was sighted
// Sets self.enemy to world and returns FALSE if no enemy sighted
//=============================================================
/*
        Old Code

float() BotFindTarget =
{
        local entity head, selected;
	local float dist;
	dist = 1500;	// awareness radius of bot, increasing it slows down game
	selected = world;

	head = findradius(self.origin, 1500);
	while(head)
	{
//           if(!(head.flags & FL_NOTARGET) && (head.flags & FL_MONSTER)) Original Code
                if(!(head.flags & FL_NOTARGET) && ((head.flags & FL_CLIENT) || (head.flags & FL_MONSTER)))
                if (((teamplay) &&  (head.team != self.owner.team)) || (!teamplay))
                if ((head.health > 1) && (head != self) && (head.bot != self))
                if (visible(head))
                if (trace_plane_dist < dist)
                if ((head.health > 0) && (head !=self))
                   {
                        selected = head;
                        dist = trace_plane_dist;
                   }
		head = head.chain;
	}
	self.enemy = selected;
		
	if (self.enemy == world)
        {
                centerprint(self.owner, "World\n");
		return FALSE;
        }
        else
                if (selected.bot == self)
                        {
                                centerprint(self.owner, "Doh, thats ");
                                centerprint(self.owner, selected.owner.netname);
                                centerprint(self.owner, "\n");
                                return FALSE;
                        }
                else
                        if (teamplay == 1)
                     {
                          if (selected.team == self.team)
                                       {
                                              centerprint(self.owner, "Doh, thats my friend ");
                                              centerprint(self.owner, selected.owner.netname);
                                              centerprint(self.owner, "\n");
                                              return FALSE;
                                        }
                          else
                          centerprint(self.owner, "Die interloper!\n");
                          BotFoundTarget();
                          return TRUE;
                      }
        else
        {
                centerprint(self.owner, "Die interloper!\n");
		BotFoundTarget();
		return TRUE;
	}
};
*/
// New Code
float() BotFindTarget =
{
        local entity head, selected;
	local float dist;
	dist = 1500;	// awareness radius of bot, increasing it slows down game
	selected = world;

	head = findradius(self.origin, 1500);
	while(head)
	{
//           if(!(head.flags & FL_NOTARGET) && (head.flags & FL_MONSTER)) Original Code
// Old Code if(!(head.flags & FL_NOTARGET) && ((head.flags & FL_CLIENT) || (head.flags & FL_MONSTER)))
                if(!(head.flags & FL_NOTARGET) && ((head.flags & FL_CLIENT) || (head.flags & FL_MONSTER)))
                if (((teamplay) &&  (head.team != self.owner.team)) || (!teamplay))
                if ((head.health > 1) && (head != self) && (head.bot != self))
                if (visible(head))
                if (trace_plane_dist < dist)
                if ((head.health > 0) && (head !=self))
                   {
                        selected = head;
                        dist = trace_plane_dist;
                   }
		head = head.chain;
	}
	self.enemy = selected;
		
	if (self.enemy == world)
		return FALSE;
        else
/*      if (self.enemy.bot == self)
//              return FALSE;
//      else
//      if (teamplay == 1)
//              {
//                if (self.enemy.team == self.team)
//                   {
//  No Longer         self.enemy = world;
//  Needed I Hope    return FALSE;
//                   }
//                else
// Modified by Silvar
//                   {
//                    BotFoundTarget();
//                    return TRUE;
//                   }
//             }
//      else
*/
        {
		BotFoundTarget();
		return TRUE;
	}
};
// end new code
//=============================================================
// bot_ai_stand - bot stands in place until target acquired,
// and starts to walk if pausetime has expired
//=============================================================
void() bot_ai_stand =
{
	if (BotFindTarget ())
		return;
	
	if (vlen (self.origin - self.owner.origin) > 500)
	{
		bot_follow1	();
		return;
	}

	if (time > self.pausetime)
	{
		self.th_walk ();
		return;
	}
};


//=============================================================
// bot_pain
//=============================================================
void(entity attacker, float damage)	bot_pain =
{
	local float r;
	local entity oldself;

	r = random ();
	if (self.pain_finished > time)
		return;

	
	if (r < 0.5)
		sound (self, CHAN_VOICE, "enforcer/pain1.wav", 1, ATTN_NORM);
	else
		sound (self, CHAN_VOICE, "enforcer/pain2.wav", 1, ATTN_NORM);


// Been hit, so go into automatic mode
	if (!(self.owner.bot_auto))
	{
		oldself = self;
		self = self.owner;
		BotAutoToggle();
		self = oldself;
//                self.enemy = attacker.owner;
//                BotFoundTarget();
	}

	if (r < 0.2)
	{
		self.pain_finished = time + 1;
		bot_paina1 ();
	}
	else if (r < 0.4)
	{
		self.pain_finished = time + 1;
		bot_painb1 ();
	}
	else if (r < 0.7)
	{
		self.pain_finished = time + 1;
		bot_painc1 ();
	}
	else
	{
		self.pain_finished = time + 2;
		bot_paind1 ();
	}

};

//=============================================================
// bot_die
//=============================================================
void() bot_die =
{
	sound (self, CHAN_VOICE, "enforcer/death1.wav", 1, ATTN_NORM);
	if (random() > 0.5)
		bot_die1 ();
	else
		bot_fdie1 ();

// death frame sequence includes bot deactivation	
};


//=============================================================
// BotSightSound
//=============================================================
void() BotSightSound =
{
	local float	rsnd;

	rsnd = rint(random() * 3);			
	if (rsnd == 1)
		sound (self, CHAN_VOICE, "enforcer/sight1.wav", 1, ATTN_NORM);
	else if (rsnd == 2)
		sound (self, CHAN_VOICE, "enforcer/sight2.wav", 1, ATTN_NORM);
	else if (rsnd == 0)
		sound (self, CHAN_VOICE, "enforcer/sight3.wav", 1, ATTN_NORM);
	else
		sound (self, CHAN_VOICE, "enforcer/sight4.wav", 1, ATTN_NORM);
};


//=============================================================
// BotHuntTarget
//=============================================================
void() BotHuntTarget =
{
	self.goalentity = self.enemy;
	self.think = self.th_run;
	self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
	self.nextthink = time + 0.1;
        SUB_AttackFinished (0.1);       // wait a while before first attack
};


//=============================================================
// BotFoundTarget
//=============================================================
void() BotFoundTarget =
{
	local float f_dist;
	local string s_dist;
	f_dist = vlen (self.enemy.origin - self.origin);
	s_dist = ftos (f_dist);

	self.show_hostile = time + 1;		// wake up other monsters
	
	sprint (self.owner, "targetting: ");
        if (self.enemy.classname == "player")
            {
              sprint (self.owner, self.enemy.netname);
            }    
        else
	sprint (self.owner, self.enemy.classname);
	sprint (self.owner, "\n");
	sprint (self.owner, "  distance: ");
	sprint (self.owner, s_dist);
	sprint (self.owner, "\n");
	BotSightSound ();
	BotHuntTarget ();
};


//=============================================================
// bot_ai_walk - bot is walking, looking for enemies
//=============================================================
void(float dist) bot_ai_walk =
{
	if (BotFindTarget ())
		return;

	if (vlen (self.origin - self.owner.origin) > 500)
	{
		bot_follow1();
		return;
	}

	movetogoal (dist);
};


//=============================================================
// bot_ai_follow - bot is following player, looking for enemies
//=============================================================
void(float dist) bot_ai_follow =
{
	if (BotFindTarget ())
		return;

	if (vlen (self.origin - self.owner.origin) <= 50)
	{
		self.pausetime = time + 2;
		self.th_stand ();
		return;
	}

	movetogoal (dist);
};


//=============================================================
// man_bot_ai_walk - bot is walking
//=============================================================
void(float dist) man_bot_ai_walk =
{
	local vector	temp_vec;

	ChangeYaw();
	makevectors (self.angles);
	temp_vec = vectoangles (v_forward);
	walkmove (temp_vec_y, dist);
};


//=============================================================
// man_bot_ai_run - bot is running
//=============================================================
void(float dist) man_bot_ai_run =
{
	local entity temp_ent;
	local vector temp_vec;

	ChangeYaw();
	makevectors (self.angles);

	temp_ent = spawn();
	temp_ent.classname = "navpoint";
	temp_ent.owner = self;
	temp_ent.angles = self.angles;
	temp_ent.nextthink = time + 0.1;
	temp_ent.think = SUB_Remove;
	temp_ent.takedamage = DAMAGE_NO;
	temp_ent.solid = SOLID_NOT;
	temp_ent.movetype = MOVETYPE_NONE;

	self.enemy = self.goalentity = self.movetarget = temp_ent;

	makevectors (self.angles);
	temp_vec = self.origin + (v_forward * 100);
	setorigin (temp_ent, temp_vec);

	movetogoal (dist);
};


//=============================================================
// bot_ai_turn - turn towards ideal_yaw if no enemy sighted
//=============================================================
void() bot_ai_turn =
{
	if (BotFindTarget ())
		return;
	
	ChangeYaw ();
};


//=============================================================
// bot_ai_run - still needs a little work
//=============================================================
void(float dist) bot_ai_run =
{
	local	vector	delta;
	local	float	axis;
	local	float	direct, ang_rint, ang_floor, ang_ceil;
	
	movedist = dist;

	if (self.enemy.health <= 0)
	{
		self.enemy = world;
		if (self.oldenemy.health > 0)
		{
			self.enemy = self.oldenemy;
			BotHuntTarget ();
		}
		else
		{
			if (BotFindTarget())
				return;
			else
			{
				self.movetarget = self.owner;
				self.th_walk ();
				return;
			}
		}
	}

	self.show_hostile = time + 1;		// wake up other monsters

	enemy_vis = visible(self.enemy);
	if (enemy_vis)
		self.search_time = time + 5;

	enemy_infront = infront(self.enemy);
	enemy_range = range(self.enemy);
	enemy_yaw = vectoyaw(self.enemy.origin - self.origin);
	
	if (self.attack_state == AS_MISSILE)
	{
		ai_run_missile ();
		return;
	}
	if (self.attack_state == AS_MELEE)
	{
		ai_run_melee ();
		return;
	}

	if (CheckAnyAttack ())
		return;					// beginning an attack
		
	if (self.attack_state == AS_SLIDING)
	{
		ai_run_slide ();
		return;
	}
		
	movetogoal (dist);		// done in C code...
};


//=============================================================
// BotCheckRefire
//=============================================================
void (void () thinkst) BotCheckRefire =
{
	if (!visible (self.enemy) || (self.enemy.health <= 0))
		return;
	self.think = thinkst;
};


//=============================================================
// BotSelfDeActivate - Bot deactivates itself
//=============================================================
void () BotSelfDeActivate =
{
	local entity bot_owner;
	bot_owner = self.owner;

	WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
	WriteByte (MSG_BROADCAST, TE_TELEPORT);
	WriteCoord (MSG_BROADCAST, self.origin_x);
	WriteCoord (MSG_BROADCAST, self.origin_y);
	WriteCoord (MSG_BROADCAST, self.origin_z);
	sound (self, CHAN_BODY, "misc/r_tele1.wav", 1, ATTN_NORM);
	remove (self);
	bot_owner.bot_flag = FALSE;
	sprint(bot_owner, "bot deactivated\n");
};

//=============================================================
// bot_fire
//=============================================================
void () bot_fire =
{
// in future, adjust frame sequence to not show firing if auto_fire off

	if (self.auto_fire)
	{
               if (!visible (self.enemy) || (self.enemy.health <= 0))
                return;
               benforcer_fire();
		sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM);
               benforcer_fire();
	}
	else
		return;
};
void () bot_fire2 =
{
// in future, adjust frame sequence to not show firing if auto_fire off

	if (self.auto_fire)
	{
               self.oldenemy = self.enemy;
               if (!visible (self.enemy) || (self.enemy.health <= 0))
               {
                        if (BotFindTarget ())
                                return;
	
                                ChangeYaw ();
                  self.enemy = self.oldenemy;
               }
               benforcer_fire('0.01 0.01 0');
		sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM);
               benforcer_fire('0.01 0 0.01');
	}
	else
		return;
};

void(vector offset) benforcer_fire =
{
	local vector org;
        local vector dir;
        local float ox;
        
        ox = 4;

	self.effects = self.effects | EF_MUZZLEFLASH;
	makevectors (self.angles);
	sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
	
        org = self.origin + v_forward * 30 + v_right*ox + '0 0 16';
        dir = self.enemy.origin - self.origin;
        dir = normalize(dir);
        launch_spike(org, dir);
        org = org + offset;
        launch_spike(org, dir);
//      glaunch_spike(org, dir);
};
void(vector org, vector dir) glaunch_spike =
{
        local   vector  vec, move;
        local   float   fly, mspeed, accuracy;

	newmis = spawn ();
	newmis.owner = self;
	newmis.movetype = MOVETYPE_FLYMISSILE;
	newmis.solid = SOLID_BBOX;
        mspeed = 1000;
        accuracy = 0.0;
	makevectors (self.angles);
                                // set missile speed
        vec = self.enemy.origin + self.enemy.mins + self.enemy.size * 0.7 - newmis.origin;
                                // calc aproximate time for missile to reach vec
	fly = vlen (vec) / mspeed;
                                // get the entities xy velocity
	move = self.enemy.velocity;
	move_z = 0;
                                // project the target forward in time
	vec = vec + move * fly;
	vec = normalize(vec);
        vec = vec + accuracy*v_up*(random()- 0.1) + accuracy*v_right*(random()- 0.1);
        newmis.velocity = vec * mspeed;
        newmis.angles = '0 0 0';
        newmis.angles_y = vectoyaw(newmis.velocity);
                                // set missile duration
	newmis.touch = spike_touch;
	newmis.classname = "spike";
	newmis.think = SUB_Remove;
	newmis.nextthink = time + 6;
	setmodel (newmis, "progs/spike.mdl");
	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);		
	setorigin (newmis, org);

};

