580 lines
13 KiB
C++
580 lines
13 KiB
C++
/*
|
|
=============================
|
|
xifight.qc
|
|
coded by
|
|
Michael Rogers a.k.a Xsniper
|
|
ssj_xsniper@yahoo.com
|
|
http://www.xsniper.net/
|
|
|
|
Description:
|
|
This file contains fighting code for Xsniper Bot.
|
|
=============================
|
|
*/
|
|
|
|
void() xsn_attack;
|
|
//========================================================================================================
|
|
//Fighting Styles Code Below
|
|
|
|
void() fs_standstill =
|
|
{
|
|
//very simple, stand still and fire
|
|
self.think = self.th_missile;
|
|
self.nextthink = time + 0.01;
|
|
};
|
|
|
|
void() fs_sidestep =
|
|
{
|
|
local float ofs;
|
|
|
|
// this is a cool strafing routine
|
|
if (self.lefty)
|
|
ofs = 90;
|
|
else
|
|
ofs = -90;
|
|
|
|
if (walkmove (self.angles_y + ofs, 20))
|
|
{
|
|
if (ofs == -90)
|
|
{
|
|
makevectors(self.angles);
|
|
self.flags = self.flags - (self.flags & FL_ONGROUND);
|
|
self.velocity = v_right * self.speed;
|
|
}
|
|
else
|
|
{
|
|
makevectors(self.angles);
|
|
self.flags = self.flags - (self.flags & FL_ONGROUND);
|
|
self.velocity = v_right * self.speed * -1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
self.lefty = 1 - self.lefty;
|
|
|
|
walkmove (self.angles_y - ofs, 20);
|
|
|
|
if (ofs == -90)
|
|
{
|
|
makevectors(self.angles);
|
|
self.flags = self.flags - (self.flags & FL_ONGROUND);
|
|
self.velocity = v_right * self.speed;
|
|
}
|
|
else
|
|
{
|
|
makevectors(self.angles);
|
|
self.flags = self.flags - (self.flags & FL_ONGROUND);
|
|
self.velocity = v_right * self.speed * -1;
|
|
}
|
|
|
|
//lets fire our weapon now
|
|
self.think = self.th_missile;
|
|
self.nextthink = time + 0.01;
|
|
};
|
|
|
|
void() fs_charge =
|
|
{
|
|
//lets get as close to our enemy as possible
|
|
movetogoal(20);
|
|
makevectors(self.angles);
|
|
self.flags = self.flags - (self.flags & FL_ONGROUND);
|
|
self.velocity = v_forward * self.speed;
|
|
|
|
//shoot him up close and personal
|
|
self.think = self.th_missile;
|
|
self.nextthink = time + 0.01;
|
|
};
|
|
|
|
void() fs_back =
|
|
{
|
|
//if the enemy gets too close then back up
|
|
if (range(self.enemy) == RANGE_MELEE || range(self.enemy) == RANGE_NEAR)
|
|
ai_back(23);
|
|
|
|
//shoot from a distance
|
|
self.think = self.th_missile;
|
|
self.nextthink = time + 0.01;
|
|
};
|
|
|
|
void() fs_circle =
|
|
{
|
|
//circle around the enemy
|
|
if (vlen(self.enemy.origin - self.origin) < 80)
|
|
walkmove(self.angles_y - 180, 20);
|
|
if (vlen(self.enemy.origin - self.origin) > 110)
|
|
movetogoal(20);
|
|
else fs_sidestep();
|
|
|
|
//lets fire our weapon now
|
|
self.think = self.th_missile;
|
|
self.nextthink = time + 0.01;
|
|
};
|
|
|
|
/*
|
|
=============================
|
|
pick_fighting_style
|
|
|
|
Picks a fighting style based on
|
|
certain criteria.
|
|
|
|
Fighting Styles:
|
|
0: stand still
|
|
1: sidestep
|
|
2: charge towards opponent
|
|
3: keep your distance
|
|
4: circle around opponent
|
|
=============================
|
|
*/
|
|
void() pick_fighting_style =
|
|
{
|
|
local float r;
|
|
|
|
//set up random variable
|
|
r = random();
|
|
|
|
//for now lets pick a fighting style at random
|
|
if (r <= 0.2)
|
|
self.fstyle = 0;
|
|
else if (r <= 0.4)
|
|
self.fstyle = 1;
|
|
else if (r <= 0.6)
|
|
self.fstyle = 2;
|
|
else if (r <= 0.8)
|
|
self.fstyle = 3;
|
|
else
|
|
self.fstyle = 4;
|
|
|
|
//set up fstime
|
|
self.fstime = time + 5 + random();
|
|
};
|
|
|
|
/*
|
|
===============================
|
|
execute_fighting_style
|
|
|
|
Lets activate our fighting style.
|
|
|
|
Fighting Styles:
|
|
0: stand still
|
|
1: sidestep
|
|
2: charge towards opponent
|
|
3: keep your distance
|
|
4: circle around opponent
|
|
===============================
|
|
*/
|
|
void() execute_fighting_style =
|
|
{
|
|
//see if we need to get a new fighting style or not
|
|
if (time > self.fstime)
|
|
pick_fighting_style();
|
|
|
|
//when using melee weapons we need to charge forward for best results
|
|
if (self.weapon == IT_DAGGER)
|
|
self.fstyle = 2;
|
|
else if (self.weapon == IT_SWORD && self.wmode == 1)
|
|
self.fstyle = 2;
|
|
|
|
//execute our fighting style
|
|
if (self.fstyle == 0)
|
|
fs_standstill();
|
|
else if (self.fstyle == 1)
|
|
fs_sidestep();
|
|
else if (self.fstyle == 2)
|
|
fs_charge();
|
|
else if (self.fstyle == 3)
|
|
fs_back();
|
|
else
|
|
fs_circle();
|
|
};
|
|
|
|
//========================================================================================================
|
|
//Weapon Selection Code Below
|
|
|
|
/*
|
|
============================
|
|
have_weapon
|
|
|
|
Returns true or false if self has the weapon
|
|
referenced by wcode.
|
|
============================
|
|
*/
|
|
float(float wcode) have_weapon =
|
|
{
|
|
local float it;
|
|
|
|
//set up items
|
|
it = self.items;
|
|
|
|
//see if we have the weapon
|
|
if (it & wcode)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
};
|
|
|
|
float() CheckPrimaryAmmo =
|
|
{
|
|
//check ammo for primary attacks
|
|
if(self.weapon == IT_CROSSBOW && self.currentammo >= 1)
|
|
return TRUE;
|
|
if(self.weapon == IT_TRINITY_BLAST && self.currentammo >= 1)
|
|
return TRUE;
|
|
if(self.weapon == IT_ICE_SHARDS && self.currentammo >= 2)
|
|
return TRUE;
|
|
if(self.weapon == IT_LIGHTNING_ARC && self.currentammo >= 1)
|
|
return TRUE;
|
|
if(self.weapon == IT_SMITE && self.currentammo >= 1)
|
|
return TRUE;
|
|
if(self.weapon == IT_SOUL_DISC && self.currentammo >= 2)
|
|
return TRUE;
|
|
if(self.weapon == IT_SWORD)
|
|
return TRUE;
|
|
|
|
if (self.weapon == IT_DAGGER)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
};
|
|
|
|
float() CheckSecondaryAmmo =
|
|
{
|
|
//check ammo for secondary attacks
|
|
if(self.weapon == IT_CROSSBOW && self.currentammo >= 3)
|
|
return TRUE;
|
|
if(self.weapon == IT_TRINITY_BLAST && self.currentammo >= 3)
|
|
return TRUE;
|
|
if(self.weapon == IT_ICE_SHARDS && self.currentammo >= 4)
|
|
return TRUE;
|
|
if(self.weapon == IT_LIGHTNING_ARC && self.currentammo >= 10)
|
|
return TRUE;
|
|
if(self.weapon == IT_SMITE && self.currentammo >= 2)
|
|
return TRUE;
|
|
if(self.weapon == IT_SOUL_DISC && self.currentammo >= 2)
|
|
return TRUE;
|
|
if(self.weapon == IT_SWORD)
|
|
return TRUE;
|
|
|
|
if (self.weapon == IT_DAGGER)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
};
|
|
|
|
/*
|
|
=================
|
|
have_ammo
|
|
|
|
Returns a 1 if they have enough ammo for primary attack only.
|
|
Returns a 2 if they have enough ammo for primary and secondary attack.
|
|
Returns a 0 if they don't have enough ammo for either attack.
|
|
=================
|
|
*/
|
|
float() have_ammo =
|
|
{
|
|
local float rvalue;
|
|
|
|
//initialize rvalue
|
|
rvalue = 0;
|
|
|
|
if (CheckPrimaryAmmo() == TRUE)
|
|
rvalue = rvalue + 1;
|
|
if (CheckSecondaryAmmo() == TRUE)
|
|
rvalue = rvalue + 1;
|
|
|
|
return rvalue;
|
|
};
|
|
|
|
void() print_ammo =
|
|
{
|
|
//debug msg
|
|
bprint("self.currentammo == ");
|
|
bprint(ftos(self.currentammo));
|
|
bprint("\n");
|
|
|
|
};
|
|
|
|
/*
|
|
=============================
|
|
enemies_nearby
|
|
|
|
Returns true or false if there are other
|
|
enemies near targ.
|
|
=============================
|
|
*/
|
|
float(entity targ) enemies_nearby =
|
|
{
|
|
local entity etemp;
|
|
local float ecount;
|
|
|
|
//initialize ecount
|
|
ecount = 0;
|
|
|
|
//check a radius around targ for other enemies
|
|
etemp = findradius(targ.origin, 300);
|
|
|
|
while(etemp)
|
|
{
|
|
//we don't want to count ourself
|
|
if (etemp != targ)
|
|
{
|
|
//only want to count monsters
|
|
if (etemp.monflag == "TRUE")
|
|
ecount = ecount + 1;
|
|
}
|
|
|
|
etemp = etemp.chain;
|
|
}
|
|
|
|
//return true or false based on ecount
|
|
if (ecount > 0)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
};
|
|
|
|
string() get_weapon =
|
|
{
|
|
if (self.weapon == 4096) //IT_DAGGER
|
|
return "IT_DAGGER";
|
|
if (self.weapon == 1) //IT_CROSSBOW
|
|
return "IT_CROSSBOW";
|
|
if (self.weapon == 2) //IT_TRINITY_BLAST
|
|
return "IT_TRINITY_BLAST";
|
|
if (self.weapon == 4) //IT_ICE_SHARDS
|
|
return "IT_ICE_SHARDS";
|
|
if (self.weapon == 8) //IT_LIGHTNING_ARC
|
|
return "IT_LIGHTNING_ARC";
|
|
if (self.weapon == 16) //IT_SMITE
|
|
return "IT_SMITE";
|
|
if (self.weapon == 32) //IT_SOUL_DISC
|
|
return "IT_SOUL_DISC";
|
|
if (self.weapon == 64) //IT_SWORD
|
|
return "IT_SWORD";
|
|
if (self.weapon == 128) //IT_EXTRA_WEAPON
|
|
return "IT_EXTRA_WEAPON";
|
|
|
|
};
|
|
|
|
/*
|
|
=====================
|
|
set_weapon
|
|
|
|
Gives the best weapon possible with
|
|
w1 being the best and w8 being the worst.
|
|
If bot doesnt have any of these weapons then
|
|
it just returns.
|
|
=====================
|
|
*/
|
|
void(float w1, float w2,float w3,float w4,float w5,float w6,float w7,float w8) set_weapon =
|
|
{
|
|
if (have_weapon(w1))
|
|
{
|
|
self.weapon = w1;
|
|
//DebugMsg(3,"self.weapon == ",get_weapon(),"\n","");
|
|
//make sure we have enough ammo to do primary attack atleast
|
|
if (have_ammo() >= 1)
|
|
return;
|
|
}
|
|
if (have_weapon(w2))
|
|
{
|
|
self.weapon = w2;
|
|
//DebugMsg(3,"self.weapon == ",get_weapon(),"\n","");
|
|
//make sure we have enough ammo to do primary attack atleast
|
|
if (have_ammo() >= 1)
|
|
return;
|
|
}
|
|
if (have_weapon(w3))
|
|
{
|
|
self.weapon = w3;
|
|
//DebugMsg(3,"self.weapon == ",get_weapon(),"\n","");
|
|
//make sure we have enough ammo to do primary attack atleast
|
|
if (have_ammo() >= 1)
|
|
return;
|
|
}
|
|
if (have_weapon(w4))
|
|
{
|
|
self.weapon = w4;
|
|
//DebugMsg(3,"self.weapon == ",get_weapon(),"\n","");
|
|
//make sure we have enough ammo to do primary attack atleast
|
|
if (have_ammo() >= 1)
|
|
return;
|
|
}
|
|
if (have_weapon(w5))
|
|
{
|
|
self.weapon = w5;
|
|
//DebugMsg(3,"self.weapon == ",get_weapon(),"\n","");
|
|
//make sure we have enough ammo to do primary attack atleast
|
|
if (have_ammo() >= 1)
|
|
return;
|
|
}
|
|
if (have_weapon(w6))
|
|
{
|
|
self.weapon = w6;
|
|
//DebugMsg(3,"self.weapon == ",get_weapon(),"\n","");
|
|
//make sure we have enough ammo to do primary attack atleast
|
|
if (have_ammo() >= 1)
|
|
return;
|
|
}
|
|
if (have_weapon(w7))
|
|
{
|
|
self.weapon = w7;
|
|
//DebugMsg(3,"self.weapon == ",get_weapon(),"\n","");
|
|
//make sure we have enough ammo to do primary attack atleast
|
|
if (have_ammo() >= 1)
|
|
return;
|
|
}
|
|
if (have_weapon(w8))
|
|
{
|
|
self.weapon = w8;
|
|
//DebugMsg(3,"self.weapon == ",get_weapon(),"\n","");
|
|
//make sure we have enough ammo to do primary attack atleast
|
|
if (have_ammo() >= 1)
|
|
return;
|
|
}
|
|
};
|
|
|
|
/*
|
|
=====================
|
|
set_mode
|
|
|
|
Will put us into secondary attack mode
|
|
if possible and if our current weapon is
|
|
any of the weapons from w1 through w8
|
|
=====================
|
|
*/
|
|
void(float w1,float w2,float w3,float w4,float w5,float w6,float w7,float w8) set_mode =
|
|
{
|
|
if (self.weapon == w1 && have_ammo() == 2)
|
|
self.wmode = 2;
|
|
else if (self.weapon == w2 && have_ammo() == 2)
|
|
self.wmode = 2;
|
|
else if (self.weapon == w3 && have_ammo() == 2)
|
|
self.wmode = 2;
|
|
else if (self.weapon == w4 && have_ammo() == 2)
|
|
self.wmode = 2;
|
|
else if (self.weapon == w5 && have_ammo() == 2)
|
|
self.wmode = 2;
|
|
else if (self.weapon == w6 && have_ammo() == 2)
|
|
self.wmode = 2;
|
|
else if (self.weapon == w7 && have_ammo() == 2)
|
|
self.wmode = 2;
|
|
else if (self.weapon == w8 && have_ammo() == 2)
|
|
self.wmode = 2;
|
|
else
|
|
self.wmode = 1;
|
|
};
|
|
|
|
/*
|
|
=====================
|
|
choose_weapon
|
|
|
|
This function is called by the bot during combat
|
|
allowing him to choose the best weapon for
|
|
the situation based on range of enemy and number
|
|
of enemies around him.
|
|
=====================
|
|
*/
|
|
void() choose_weapon =
|
|
{
|
|
//get our current ammo set up
|
|
W_SetCurrentAmmo ();
|
|
|
|
//first check the range
|
|
if (range(self.enemy) == RANGE_MID) //Medium Range
|
|
{
|
|
//DebugMsg(2,"range == RANGE_MID", "\n", "", "");
|
|
|
|
//now check if more enemies are around self.enemy
|
|
if (enemies_nearby(self.enemy))
|
|
{
|
|
//DebugMsg(2,"enemies_nearby == TRUE", "\n", "", "");
|
|
|
|
//set our weapon appropriately
|
|
set_weapon(IT_SMITE,IT_ICE_SHARDS,IT_SOUL_DISC,IT_TRINITY_BLAST,IT_CROSSBOW,IT_SWORD,0,0);
|
|
|
|
//set weapon attack mode
|
|
set_mode(IT_ICE_SHARDS,IT_CROSSBOW,IT_SWORD,0,0,0,0,0);
|
|
|
|
//lets fire our weapon now
|
|
xsn_attack();
|
|
}
|
|
else //just one enemy
|
|
{
|
|
//DebugMsg(2,"enemies_nearby == FALSE", "\n", "", "");
|
|
|
|
//set our weapon appropriately
|
|
set_weapon(IT_SMITE,IT_ICE_SHARDS,IT_CROSSBOW,IT_TRINITY_BLAST,IT_SWORD,0,0,0);
|
|
|
|
//set weapon attack mode
|
|
set_mode(IT_CROSSBOW,IT_SWORD,0,0,0,0,0,0);
|
|
|
|
//lets fire our weapon now
|
|
xsn_attack();
|
|
}
|
|
}
|
|
else if (range(self.enemy) == RANGE_NEAR) //Closer but not melee yet
|
|
{
|
|
//DebugMsg(2,"range == RANGE_NEAR", "\n", "", "");
|
|
|
|
//now check if more enemies are around self.enemy
|
|
if (enemies_nearby(self.enemy))
|
|
{
|
|
//DebugMsg(2,"enemies_nearby == TRUE", "\n", "", "");
|
|
|
|
//set our weapon appropriately
|
|
set_weapon(IT_LIGHTNING_ARC,IT_SMITE,IT_ICE_SHARDS,IT_SOUL_DISC,IT_TRINITY_BLAST,IT_CROSSBOW,IT_SWORD,0);
|
|
|
|
//set weapon attack mode
|
|
set_mode(IT_LIGHTNING_ARC,IT_ICE_SHARDS,IT_TRINITY_BLAST,IT_CROSSBOW,IT_SWORD,0,0,0);
|
|
|
|
//lets fire our weapon now
|
|
xsn_attack();
|
|
}
|
|
else //just one enemy
|
|
{
|
|
//DebugMsg(2,"enemies_nearby == FALSE", "\n", "", "");
|
|
|
|
//set our weapon appropriately
|
|
set_weapon(IT_LIGHTNING_ARC,IT_SMITE,IT_SOUL_DISC,IT_CROSSBOW,IT_ICE_SHARDS,IT_TRINITY_BLAST,IT_SWORD,0);
|
|
|
|
//set weapon attack mode
|
|
set_mode(IT_CROSSBOW,IT_TRINITY_BLAST,IT_SWORD,0,0,0,0,0);
|
|
|
|
//lets fire our weapon now
|
|
xsn_attack();
|
|
}
|
|
}
|
|
else if (range(self.enemy) == RANGE_MELEE) //Hand to hand combat
|
|
{
|
|
//DebugMsg(2,"range == RANGE_MELEE", "\n", "", "");
|
|
|
|
//now check if more enemies are around self.enemy
|
|
if (enemies_nearby(self.enemy))
|
|
{
|
|
//DebugMsg(2,"enemies_nearby == TRUE", "\n", "", "");
|
|
|
|
//set our weapon appropriately
|
|
set_weapon(IT_LIGHTNING_ARC,IT_SMITE,IT_SOUL_DISC,IT_ICE_SHARDS,IT_CROSSBOW,IT_SWORD,IT_DAGGER,0);
|
|
|
|
//set weapon attack mode
|
|
set_mode(IT_LIGHTNING_ARC,IT_SMITE,IT_ICE_SHARDS,IT_CROSSBOW,0,0,0,0);
|
|
|
|
//lets fire our weapon now
|
|
xsn_attack();
|
|
}
|
|
else //just one enemy
|
|
{
|
|
//DebugMsg(2,"enemies_nearby == FALSE", "\n", "", "");
|
|
|
|
//set our weapon appropriately
|
|
set_weapon(IT_SWORD,IT_ICE_SHARDS,IT_DAGGER,0,0,0,0,0);
|
|
|
|
//set weapon attack mode
|
|
set_mode(0,0,0,0,0,0,0,0);
|
|
|
|
//lets fire our weapon now
|
|
xsn_attack();
|
|
}
|
|
}
|
|
};
|
|
|
|
|