r3426 - in trunk: data data/qcsrc/server pro
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Mon Feb 25 14:37:46 EST 2008
Author: lordhavoc
Date: 2008-02-25 14:37:46 -0500 (Mon, 25 Feb 2008)
New Revision: 3426
Modified:
trunk/data/default.cfg
trunk/data/qcsrc/server/bots.qc
trunk/data/qcsrc/server/ctf.qc
trunk/data/qcsrc/server/havocbot.qc
trunk/data/qcsrc/server/havocbot_roles.qc
trunk/data/qcsrc/server/keyhunt.qc
trunk/pro/default.cfg
Log:
fixed several bugs in bots to do with movement and aiming
optimized ctf and keyhunt by keeping flaglist and kh_keylist variables
(greatly accelerated some code that used find before)
added bot_ai_thinkinterval 0.05 which means that fast servers don't
croak from bot ai
added bot_ai_dodgeupdateinterval
added bot_ai_chooseweaponinterval
added bot_ai_dangerdetectioninterval
added bot_ai_dangerdetectionupdates (how many waypoints to update danger
ratings on per interval)
Modified: trunk/data/default.cfg
===================================================================
--- trunk/data/default.cfg 2008-02-25 19:37:08 UTC (rev 3425)
+++ trunk/data/default.cfg 2008-02-25 19:37:46 UTC (rev 3426)
@@ -160,8 +160,13 @@
seta bot_suffix ""
seta skill_auto 0 // when 1, "skill" gets adjusted to match the best player on the map
// general bot AI cvars
+set bot_ai_thinkinterval 0.05
set bot_ai_strategyinterval 2
set bot_ai_enemydetectioninterval 0.5
+set bot_ai_dodgeupdateinterval 0.1
+set bot_ai_chooseweaponinterval 0.3
+set bot_ai_dangerdetectioninterval 0.1
+set bot_ai_dangerdetectionupdates 64
set bot_ai_aimskill_blendrate 2
set bot_ai_aimskill_fixedrate 15
set bot_ai_aimskill_firetolerance_distdegrees 180
@@ -169,7 +174,7 @@
set bot_ai_aimskill_firetolerance_maxdegrees 45
set bot_ai_aimskill_mouse 1
set bot_ai_keyboard_distance 250
-set bot_ai_keyboard_treshold 0.94
+set bot_ai_keyboard_treshold 0.57
set bot_ai_aimskill_offset 1
set bot_ai_aimskill_think 1
// Better don't touch these, there are hard to tweak!
Modified: trunk/data/qcsrc/server/bots.qc
===================================================================
--- trunk/data/qcsrc/server/bots.qc 2008-02-25 19:37:08 UTC (rev 3425)
+++ trunk/data/qcsrc/server/bots.qc 2008-02-25 19:37:46 UTC (rev 3426)
@@ -4,7 +4,7 @@
vector stepheightvec;
float navigation_testtracewalk;
-float(entity e, vector start, vector m1, vector m2, vector end) tracewalk =
+float(entity e, vector start, vector m1, vector m2, vector end, float movemode) tracewalk =
{
local vector org;
local vector move;
@@ -30,10 +30,10 @@
stepdist = 32;
ignorehazards = FALSE;
//self.angles = vectoangles(dir);
- traceline(start, start, FALSE, e);
+ traceline(start, start, MOVE_NORMAL, e);
if (trace_dpstartcontents & (DPCONTENTS_SLIME | DPCONTENTS_LAVA))
ignorehazards = TRUE;
- tracebox(start, m1, m2, start, TRUE, e);
+ tracebox(start, m1, m2, start, MOVE_NOMONSTERS, e);
if (trace_startsolid)
{
// failed - bad start
@@ -71,7 +71,7 @@
if (stepdist > dist)
stepdist = dist;
dist = dist - stepdist;
- traceline(org, org, FALSE, e);
+ traceline(org, org, MOVE_NORMAL, e);
if (!ignorehazards)
{
if (trace_dpstartcontents & (DPCONTENTS_SLIME | DPCONTENTS_LAVA))
@@ -89,7 +89,7 @@
if (trace_dpstartcontents & DPCONTENTS_LIQUIDSMASK)
{
move = normalize(end - org);
- tracebox(org, m1, m2, org + move * stepdist, MOVE_WORLDONLY, e);
+ tracebox(org, m1, m2, org + move * stepdist, movemode, e);
if (trace_fraction < 1)
{
if (navigation_testtracewalk)
@@ -107,10 +107,10 @@
else
{
move = dir * stepdist + org;
- tracebox(org, m1, m2, move, MOVE_WORLDONLY, e);
+ tracebox(org, m1, m2, move, movemode, e);
if (trace_fraction < 1)
{
- tracebox(org + stepheightvec, m1, m2, move + stepheightvec, MOVE_WORLDONLY, e);
+ tracebox(org + stepheightvec, m1, m2, move + stepheightvec, movemode, e);
if (trace_fraction < 1 || trace_startsolid)
{
if (navigation_testtracewalk)
@@ -126,13 +126,12 @@
}
}
move = trace_endpos;
- tracebox(move, m1, m2, move + '0 0 -65536', FALSE, e);
- /*
// trace down from stepheight as far as possible and move there,
// if this starts in solid we try again without the stepup, and
// if that also fails we assume it is a wall
// (this is the same logic as the Quake walkmove function used)
- tracebox(move + '0 0 18', m1, m2, move + '0 0 -65536', FALSE, e);
+ tracebox(move, m1, m2, move + '0 0 -65536', movemode, e);
+ /*
if (trace_startsolid)
{
tracebox(move, m1, m2, move + '0 0 -65536', FALSE, e);
@@ -344,7 +343,7 @@
.float wp00mincost, wp01mincost, wp02mincost, wp03mincost, wp04mincost, wp05mincost, wp06mincost, wp07mincost;
.float wp08mincost, wp09mincost, wp10mincost, wp11mincost, wp12mincost, wp13mincost, wp14mincost, wp15mincost;
.float wp16mincost, wp17mincost, wp18mincost, wp19mincost, wp20mincost, wp21mincost, wp22mincost, wp23mincost, wp24mincost, wp25mincost, wp26mincost, wp27mincost, wp28mincost, wp29mincost, wp30mincost, wp31mincost;
-.float wpfire, wpcost;
+.float wpfire, wpcost, wpconsidered;
.float wpisbox;
.float wpflags;
.vector wpnearestpoint;
@@ -516,10 +515,10 @@
//traceline(self.origin, e.origin, FALSE, world);
//if (trace_fraction == 1)
if (!self.wpisbox)
- if (tracewalk(self, sv, PL_MIN, PL_MAX, ev))
+ if (tracewalk(self, sv, PL_MIN, PL_MAX, ev, MOVE_NOMONSTERS))
waypoint_addlink(self, e);
if (!e.wpisbox)
- if (tracewalk(e, ev, PL_MIN, PL_MAX, sv))
+ if (tracewalk(e, ev, PL_MIN, PL_MAX, sv, MOVE_NOMONSTERS))
waypoint_addlink(e, self);
}
}
@@ -1039,7 +1038,7 @@
{
traceline(v, org, TRUE, player);
if (trace_fraction == 1)
- if (tracewalk(player, v, PL_MIN, PL_MAX, org))
+ if (tracewalk(player, v, PL_MIN, PL_MAX, org, MOVE_NORMAL))
{
bestdist = dist;
best = w;
@@ -1049,7 +1048,7 @@
{
traceline(v, org, TRUE, player);
if (trace_fraction == 1)
- if (tracewalk(player, org, PL_MIN, PL_MAX, v))
+ if (tracewalk(player, org, PL_MIN, PL_MAX, v, MOVE_NORMAL))
{
bestdist = dist;
best = w;
@@ -1062,50 +1061,48 @@
}
// finds the waypoints near the bot initiating a navigation query
-void() navigation_markroutes_nearestwaypoints =
+float(entity waylist, float maxdist) navigation_markroutes_nearestwaypoints =
{
local entity head;
- local float dist;
- local vector v, m1, m2;
+ local vector v, m1, m2, diff;
+ local float c;
//navigation_testtracewalk = TRUE;
- head = findchain(classname, "waypoint");
+ c = 0;
+ head = waylist;
while (head)
{
- m1 = head.origin + head.mins;
- m2 = head.origin + head.maxs;
- v = self.origin;
- v_x = bound(m1_x, v_x, m2_x);
- v_y = bound(m1_y, v_y, m2_y);
- v_z = bound(m1_z, v_z, m2_z);
- dist = vlen(v - self.origin);
- if (dist < 1000)
+ if (!head.wpconsidered)
{
- if (dist < 4)
+ if (head.wpisbox)
{
- // if bot is very near a waypoint don't bother doing a trace
- head.wpnearestpoint = v;
- head.wpcost = dist + head.dmg;
- head.wpfire = 1;
- head.enemy = world;
+ m1 = head.origin + head.mins;
+ m2 = head.origin + head.maxs;
+ v = self.origin;
+ v_x = bound(m1_x, v_x, m2_x);
+ v_y = bound(m1_y, v_y, m2_y);
+ v_z = bound(m1_z, v_z, m2_z);
}
else
+ v = head.origin;
+ diff = v - self.origin;
+ diff_z = max(0, diff_z);
+ if (vlen(diff) < maxdist)
{
- tracebox(self.origin, '-16 -16 0', '16 16 0', v, TRUE, self);
- if (trace_fraction == 1)
+ head.wpconsidered = TRUE;
+ if (tracewalk(self, self.origin, self.mins, self.maxs, v, MOVE_NORMAL))
{
- if (tracewalk(self, self.origin, self.mins, self.maxs, v))
- {
- head.wpnearestpoint = v;
- head.wpcost = dist + head.dmg;
- head.wpfire = 1;
- head.enemy = world;
- }
+ head.wpnearestpoint = v;
+ head.wpcost = vlen(v - self.origin) + head.dmg;
+ head.wpfire = 1;
+ head.enemy = world;
+ c = c + 1;
}
}
}
head = head.chain;
}
//navigation_testtracewalk = FALSE;
+ return c;
}
// updates a path link if a waypoint link is better than the current one
@@ -1143,13 +1140,18 @@
w = waylist = findchain(classname, "waypoint");
while (w)
{
+ w.wpconsidered = FALSE;
w.wpnearestpoint = '0 0 0';
w.wpcost = 10000000;
w.wpfire = 0;
w.enemy = world;
w = w.chain;
}
- navigation_markroutes_nearestwaypoints();
+ // try a short range search for the nearest waypoints, and expand the
+ // search repeatedly if none are found
+ if (!navigation_markroutes_nearestwaypoints(waylist, 250))
+ if (!navigation_markroutes_nearestwaypoints(waylist, 1000))
+ navigation_markroutes_nearestwaypoints(waylist, 1000000);
searching = TRUE;
while (searching)
{
@@ -1252,9 +1254,9 @@
//bprint(etos(e));
//bprint(") : ");
//bprint(etos(e));
- tracebox(self.origin, '-16 -16 0', '16 16 0', e.origin, TRUE, self);
- if (trace_fraction == 1)
- if (tracewalk(self, self.origin, PL_MIN, PL_MAX, e.origin))
+ //tracebox(self.origin, '-16 -16 0', '16 16 0', e.origin, TRUE, self);
+ //if (trace_fraction == 1)
+ if (tracewalk(self, self.origin, PL_MIN, PL_MAX, e.origin, MOVE_NORMAL))
return;
// see if there are waypoints describing a path to the item
e = e.nearestwaypoint;
@@ -1265,7 +1267,7 @@
//te_smallflash((e.absmin + e.absmax) * 0.5);
//tracebox(self.origin, '-16 -16 0', '16 16 0', e.origin, TRUE, self);
//if (trace_fraction == 1)
- //if (tracewalk(self, self.origin, PL_MIN, PL_MAX, e.origin))
+ //if (tracewalk(self, self.origin, PL_MIN, PL_MAX, e.origin, MOVE_NORMAL))
// break;
// add the waypoint to the path
navigation_pushroute(e);
@@ -1527,6 +1529,7 @@
self.bot_canfire = 1;
};
+.float bot_nextthink;
.float bot_badaimtime;
.float bot_aimthinktime;
.vector bot_mouseaim;
@@ -1575,13 +1578,7 @@
//dprint("aim ", self.netname, ": old:", vtos(self.v_angle));
// make sure v_angle is sane first
- //self.v_angle_x = bound(-180, self.v_angle_x, 180);
- //while (self.v_angle_x < -180) self.v_angle_x = self.v_angle_x + 360;
- //while (self.v_angle_x >= 180) self.v_angle_x = self.v_angle_x - 360;
- while (self.v_angle_y < -180) self.v_angle_y = self.v_angle_y + 360;
- while (self.v_angle_y >= 180) self.v_angle_y = self.v_angle_y - 360;
- //while (self.v_angle_z < -180) self.v_angle_z = self.v_angle_z + 360;
- //while (self.v_angle_z >= 180) self.v_angle_z = self.v_angle_z - 360;
+ self.v_angle_y = self.v_angle_y - floor(self.v_angle_y / 360) * 360;
self.v_angle_z = 0;
// get the desired angles to aim at
@@ -1591,15 +1588,14 @@
if (time >= self.bot_badaimtime)
{
self.bot_badaimtime = max(self.bot_badaimtime + 0.3, time);
- self.bot_badaimoffset = randomvec() * bound(0, 5 - 0.5 * (skill+self.bot_offsetskill), 5);
+ self.bot_badaimoffset = randomvec() * bound(0, 5 - 0.5 * (skill+self.bot_offsetskill), 5) * cvar("bot_ai_aimskill_offset");
}
- desiredang = vectoangles(v) + self.bot_badaimoffset*cvar("bot_ai_aimskill_offset");
+ desiredang = vectoangles(v) + self.bot_badaimoffset;
//dprint(" desired:", vtos(desiredang));
if (desiredang_x >= 180)
desiredang_x = desiredang_x - 360;
- desiredang_x = 0 - desiredang_x;
+ desiredang_x = bound(-90, 0 - desiredang_x, 90);
desiredang_z = self.v_angle_z;
- desiredang_x = bound(-90, desiredang_x, 90);
//dprint(" / ", vtos(desiredang));
//// pain throws off aim
@@ -1610,19 +1606,17 @@
//}
// calculate turn angles
- diffang = (desiredang - self.bot_olddesiredang)*(1/frametime);
+ diffang = (desiredang - self.bot_olddesiredang);
+ // wrap yaw turn
+ diffang_y = diffang_y - floor(diffang_y / 360) * 360;
+ if (diffang_y >= 180)
+ diffang_y = diffang_y - 360;
self.bot_olddesiredang = desiredang;
//dprint(" diff:", vtos(diffang));
- // wrap yaw turn
- while (diffang_y < -180)
- diffang_y = diffang_y + 360;
- while (diffang_y > 180)
- diffang_y = diffang_y - 360;
-
// Here we will try to anticipate the comming aiming direction
self.bot_1st_order_aimfilter= self.bot_1st_order_aimfilter
- + (diffang - self.bot_1st_order_aimfilter) * bound(0, cvar("bot_ai_aimskill_order_filter_1st"),1);
+ + (diffang * (1 / frametime) - self.bot_1st_order_aimfilter) * bound(0, cvar("bot_ai_aimskill_order_filter_1st"),1);
self.bot_2nd_order_aimfilter= self.bot_2nd_order_aimfilter
+ (self.bot_1st_order_aimfilter - self.bot_2nd_order_aimfilter) * bound(0, cvar("bot_ai_aimskill_order_filter_2nd"),1);
self.bot_3th_order_aimfilter= self.bot_3th_order_aimfilter
@@ -1643,19 +1637,14 @@
+ self.bot_4th_order_aimfilter * cvar("bot_ai_aimskill_order_mix_4th")
+ self.bot_5th_order_aimfilter * cvar("bot_ai_aimskill_order_mix_5th")
);
- while (desiredang_z < -180)
- desiredang_z = desiredang_z + 360;
- while (desiredang_z > 180)
- desiredang_z = desiredang_z - 360;
+
// calculate turn angles
diffang = desiredang - self.bot_mouseaim;
- //dprint(" diff:", vtos(diffang));
-
// wrap yaw turn
- while (diffang_y < -180)
- diffang_y = diffang_y + 360;
- while (diffang_y > 180)
+ diffang_y = diffang_y - floor(diffang_y / 360) * 360;
+ if (diffang_y >= 180)
diffang_y = diffang_y - 360;
+ //dprint(" diff:", vtos(diffang));
if (time >= self.bot_aimthinktime)
{
@@ -1665,27 +1654,21 @@
//self.v_angle = self.v_angle + diffang * bound(0, r * frametime * (skill * 0.5 + 2), 1);
- desiredang = self.bot_mouseaim*bound(0,cvar("bot_ai_aimskill_think"),1) + desiredang * bound(0,(1-cvar("bot_ai_aimskill_think")),1);
+ diffang = self.bot_mouseaim - desiredang;
+ // wrap yaw turn
+ diffang_y = diffang_y - floor(diffang_y / 360) * 360;
+ if (diffang_y >= 180)
+ diffang_y = diffang_y - 360;
+ desiredang = desiredang + diffang * bound(0,cvar("bot_ai_aimskill_think"),1);
// calculate turn angles
diffang = desiredang - self.v_angle;
- //dprint(" diff:", vtos(diffang));
-
// wrap yaw turn
- while (diffang_y < -180)
- diffang_y = diffang_y + 360;
- while (diffang_y > 180)
+ diffang_y = diffang_y - floor(diffang_y / 360) * 360;
+ if (diffang_y >= 180)
diffang_y = diffang_y - 360;
- // calculate turn angles
- diffang = desiredang - self.v_angle;
//dprint(" diff:", vtos(diffang));
- // wrap yaw turn
- while (diffang_y < -180)
- diffang_y = diffang_y + 360;
- while (diffang_y > 180)
- diffang_y = diffang_y - 360;
-
// jitter tracking
dist = vlen(diffang);
//diffang = diffang + randomvec() * (dist * 0.05 * (3.5 - bound(0, skill, 3)));
@@ -1701,10 +1684,7 @@
//self.v_angle = self.v_angle + diffang * bound(0, r * frametime * (skill * 0.5 + 2), 1);
//self.v_angle = self.v_angle + diffang * (1/ blendrate);
self.v_angle_z = 0;
- while (self.v_angle_y < -180)
- self.v_angle_y = self.v_angle_y + 360;
- while (self.v_angle_y >= 180)
- self.v_angle_y = self.v_angle_y - 360;
+ self.v_angle_y = self.v_angle_y - floor(self.v_angle_y / 360) * 360;
//dprint(" turn:", vtos(self.v_angle));
makevectors(self.v_angle);
@@ -1715,13 +1695,12 @@
//te_lightning2(world, shotorg, shotorg + shotdir * 100);
// calculate turn angles again
- diffang = desiredang - self.v_angle;
- while (diffang_y < -180)
- diffang_y = diffang_y + 360;
- while (diffang_y > 180)
- diffang_y = diffang_y - 360;
+ //diffang = desiredang - self.v_angle;
+ //diffang_y = diffang_y - floor(diffang_y / 360) * 360;
+ //if (diffang_y >= 180)
+ // diffang_y = diffang_y - 360;
- //bprint("e ");bprintvector(diffang);bprint(" < ");bprintfloat(maxfiredeviation);bprint("\n");
+ //dprint("e ", vtos(diffang), " < ", ftos(maxfiredeviation), "\n");
// decide whether to fire this time
// note the maxfiredeviation is in degrees so this has to convert to radians first
@@ -1729,7 +1708,7 @@
if ((normalize(v) * shotdir) >= cos(maxfiredeviation * (3.14159265358979323846 / 180)))
if (vlen(trace_endpos-shotorg) < 500+500*bound(0, skill, 10) || random()*random()>bound(0,skill*0.05,1))
self.bot_firetimer = time + bound(0.1, 0.5-skill*0.05, 0.5);
- traceline(shotorg,shotorg+shotdir*1000,FALSE,world);
+ //traceline(shotorg,shotorg+shotdir*1000,FALSE,world);
//dprint(ftos(maxfiredeviation),"\n");
//dprint(" diff:", vtos(diffang), "\n");
@@ -1802,6 +1781,9 @@
// TODO: move this painintensity code to the player damage code
void() bot_think =
{
+ if (self.bot_nextthink > time)
+ return;
+ self.bot_nextthink = self.bot_nextthink + cvar("bot_ai_thinkinterval");
//if (self.bot_painintensity > 0)
// self.bot_painintensity = self.bot_painintensity - (skill + 1) * 40 * frametime;
@@ -1859,6 +1841,7 @@
};
entity bot_strategytoken;
+float bot_strategytoken_taken;
entity player_list;
.entity nextplayer;
void() bot_relinkplayerlist =
@@ -1887,6 +1870,7 @@
}
dprint(strcat("relink: ", ftos(currentbots), " bots seen.\n"));
bot_strategytoken = bot_list;
+ bot_strategytoken_taken = TRUE;
};
void() havocbot_setupbot;
@@ -1896,6 +1880,7 @@
{
if (clienttype(self) != CLIENTTYPE_BOT)
return;
+ self.bot_nextthink = time - random();
self.lag_func = bot_lagfunc;
self.isbot = TRUE;
self.createdtime = self.nextthink;
@@ -2053,7 +2038,7 @@
};
entity botframe_dangerwaypoint;
-void() botframe_updatedangerousobjects =
+void(float maxupdate) botframe_updatedangerousobjects =
{
local entity head, bot_dodgelist;
local vector m1, m2, v;
@@ -2084,7 +2069,7 @@
}
botframe_dangerwaypoint.dmg = danger;
c = c + 1;
- if (c >= 256)
+ if (c >= maxupdate)
break;
botframe_dangerwaypoint = find(botframe_dangerwaypoint, classname, "waypoint");
}
@@ -2093,6 +2078,7 @@
float botframe_spawnedwaypoints;
float botframe_nextthink;
+float botframe_nextdangertime;
float autoskill_nextthink;
.float totalfrags_lastcheck;
@@ -2245,12 +2231,24 @@
// cycle the goal token from one bot to the next each frame
// (this prevents them from all doing waypoint searches on the same
// frame, which causes choppy framerates)
- if (bot_strategytoken)
- bot_strategytoken = bot_strategytoken.nextbot;
- if (!bot_strategytoken)
- bot_strategytoken = bot_list;
+ if (bot_strategytoken_taken)
+ {
+ bot_strategytoken_taken = FALSE;
+ if (bot_strategytoken)
+ bot_strategytoken = bot_strategytoken.nextbot;
+ if (!bot_strategytoken)
+ bot_strategytoken = bot_list;
+ }
- botframe_updatedangerousobjects();
+ if (botframe_nextdangertime < time)
+ {
+ local float interval;
+ interval = cvar("bot_ai_dangerdetectioninterval");
+ if (botframe_nextdangertime < time - interval * 1.5)
+ botframe_nextdangertime = time;
+ botframe_nextdangertime = botframe_nextdangertime + interval;
+ botframe_updatedangerousobjects(cvar("bot_ai_dangerdetectionupdates"));
+ }
}
if (cvar("g_waypointeditor"))
Modified: trunk/data/qcsrc/server/ctf.qc
===================================================================
--- trunk/data/qcsrc/server/ctf.qc 2008-02-25 19:37:08 UTC (rev 3425)
+++ trunk/data/qcsrc/server/ctf.qc 2008-02-25 19:37:46 UTC (rev 3426)
@@ -1,4 +1,6 @@
+entity flaglist; // CTF flags in the map
+
.float next_take_time; // the next time a player can pick up a flag (time + blah)
/// I used this, in part, to fix the looping score bug. - avirox
@@ -458,10 +460,15 @@
{
if (!g_ctf)
return;
+
//if(!cvar("teamplay"))
// cvar_set("teamplay", "3");
- self.classname = "item_flag_team1";
+ // link flag into flaglist
+ self.enemy = flaglist;
+ flaglist = self;
+
+ self.classname = "item_flag_team";
self.team = COLOR_TEAM1; // color 4 team (red)
self.items = IT_KEY2; // gold key (redish enough)
self.netname = "^1RED^7 flag";
@@ -520,7 +527,11 @@
//if(!cvar("teamplay"))
// cvar_set("teamplay", "3");
- self.classname = "item_flag_team2";
+ // link flag into flaglist
+ self.enemy = flaglist;
+ flaglist = self;
+
+ self.classname = "item_flag_team";
self.team = COLOR_TEAM2; // color 13 team (blue)
self.items = IT_KEY1; // silver key (bluish enough)
self.netname = "^4BLUE^7 flag";
@@ -655,9 +666,11 @@
if (g_ctf) {
local entity flag;
- flag = find(world, classname, "item_flag_team1");
- ctf_setstatus2(flag);
- flag = find(world, classname, "item_flag_team2");
- ctf_setstatus2(flag);
+ flag = flaglist;
+ while (flag)
+ {
+ ctf_setstatus2(flag);
+ flag = flag.enemy;
+ }
}
};
Modified: trunk/data/qcsrc/server/havocbot.qc
===================================================================
--- trunk/data/qcsrc/server/havocbot.qc 2008-02-25 19:37:08 UTC (rev 3425)
+++ trunk/data/qcsrc/server/havocbot.qc 2008-02-25 19:37:46 UTC (rev 3426)
@@ -5,6 +5,9 @@
vector() havocbot_dodge =
{
+ // LordHavoc: disabled because this is too expensive
+ return '0 0 0';
+ /*
local entity head;
local vector dodge, v, n;
local float danger, bestdanger, vl, d;
@@ -49,12 +52,16 @@
head = head.chain;
}
return dodge;
+ */
};
//.float havocbotignoretime;
.float havocbot_keyboardtime;
.float havocbot_ducktime;
.vector havocbot_keyboard;
+//.vector bot_dodgevector;
+//.float bot_dodgevector_time;
+//.float bot_dodgevector_jumpbutton;
void() havocbot_movetogoal =
{
local vector destorg;
@@ -66,11 +73,13 @@
local vector evadeobstacle;
local vector evadelava;
local float s;
+ local float maxspeed;
//local float dist;
local vector dodge;
//if (self.goalentity)
// te_lightning2(self, self.origin, (self.goalentity.absmin + self.goalentity.absmax) * 0.5);
self.movement = '0 0 0';
+ maxspeed = cvar("sv_maxspeed");
if(self.jumppadcount)
{
@@ -89,8 +98,6 @@
self.bot_strategytime = 0;
return;
}
- evadeobstacle = '0 0 0';
- evadelava = '0 0 0';
m1 = self.goalcurrent.origin + self.goalcurrent.mins;
m2 = self.goalcurrent.origin + self.goalcurrent.maxs;
destorg = self.origin;
@@ -102,113 +109,146 @@
dir = normalize(diff);
flatdir = diff;flatdir_z = 0;
flatdir = normalize(flatdir);
- if (!self.waterlevel)
+ //if (self.bot_dodgevector_time < time)
{
- // Since new update in air contol, we can move in air
- //if (!(self.flags & FL_ONGROUND))
- //{
- // // prevent goal checks when we can't walk
- // if (self.bot_strategytime < time + 0.1)
- // self.bot_strategytime = time + 0.1;
- // return;
- //}
+ // self.bot_dodgevector_time = time + cvar("bot_ai_dodgeupdateinterval");
+ // self.bot_dodgevector_jumpbutton = 1;
+ evadeobstacle = '0 0 0';
+ evadelava = '0 0 0';
+ if (!self.waterlevel)
+ {
+ // Since new update in air contol, we can move in air
+ //if (!(self.flags & FL_ONGROUND))
+ //{
+ // // prevent goal checks when we can't walk
+ // if (self.bot_strategytime < time + 0.1)
+ // self.bot_strategytime = time + 0.1;
+ // return;
+ //}
- // jump if going toward an obstacle that doesn't look like stairs we
- // can walk up directly
- tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.2, FALSE, self);
- if (trace_fraction < 1)
- if (trace_plane_normal_z < 0.7)
- {
- s = trace_fraction;
- tracebox(self.origin + '0 0 16', self.mins, self.maxs, self.origin + self.velocity * 0.2 + '0 0 16', FALSE, self);
- if (trace_fraction < s + 0.01)
+ // jump if going toward an obstacle that doesn't look like stairs we
+ // can walk up directly
+ tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.2, FALSE, self);
+ if (trace_fraction < 1)
if (trace_plane_normal_z < 0.7)
{
s = trace_fraction;
- tracebox(self.origin + '0 0 48', self.mins, self.maxs, self.origin + self.velocity * 0.2 + '0 0 48', FALSE, self);
- if (trace_fraction > s)
- self.button2 = 1;
+ tracebox(self.origin + '0 0 16', self.mins, self.maxs, self.origin + self.velocity * 0.2 + '0 0 16', FALSE, self);
+ if (trace_fraction < s + 0.01)
+ if (trace_plane_normal_z < 0.7)
+ {
+ s = trace_fraction;
+ tracebox(self.origin + '0 0 48', self.mins, self.maxs, self.origin + self.velocity * 0.2 + '0 0 48', FALSE, self);
+ if (trace_fraction > s)
+ self.button2 = 1;
+ }
}
+
+ traceline(self.origin + self.velocity * 0.3, self.origin + self.velocity * 0.3 + '0 0 -1000', TRUE, world);
+ s = pointcontents(trace_endpos + '0 0 1');
+ if (s == CONTENT_LAVA || s == CONTENT_SLIME)
+ evadelava = normalize(self.velocity) * -1;
+
+ dir = flatdir;
+ evadeobstacle_z = 0;
+ evadelava_z = 0;
+ makevectors(self.v_angle_y * '0 1 0');
}
+ else
+ makevectors(self.v_angle);
+ dodge = havocbot_dodge();
+ dodge = dodge * bound(0,3+skill*0.1,1);
+ evadelava = evadelava * bound(1,3-skill,3); //Noobs fear lava a lot and take more distance from it
+ traceline(self.origin, self.enemy.origin, TRUE, world);
+ if(trace_ent.classname == "player")
+ dir = dir * bound(0,skill/7,1);
- traceline(self.origin + self.velocity * 0.3, self.origin + self.velocity * 0.3 + '0 0 -1000', TRUE, world);
- s = pointcontents(trace_endpos + '0 0 1');
- if (s == CONTENT_LAVA || s == CONTENT_SLIME)
- evadelava = normalize(self.velocity) * -1;
-
- dir = flatdir;
+ dir = normalize(dir + dodge + evadeobstacle + evadelava);
+ // self.bot_dodgevector = dir;
+ // self.bot_dodgevector_jumpbutton = self.button2;
}
- dodge = havocbot_dodge();
- dodge = dodge * bound(0,3+skill*0.1,1);
- evadelava = evadelava * bound(1,3-skill,3); //Noobs fear lava a lot and take more distance from it
- traceline(self.origin, self.enemy.origin, TRUE, world);
- if(trace_ent.classname == "player")
- dir = dir * bound(0,skill/7,1);
- dir = normalize(dir + dodge + evadeobstacle + evadelava);
+ //dir = self.bot_dodgevector;
+ //if (self.bot_dodgevector_jumpbutton)
+ // self.button2 = 1;
+ self.movement_x = dir * v_forward * maxspeed;
+ self.movement_y = dir * v_right * maxspeed;
+ self.movement_z = dir * v_up * maxspeed;
-
- // Emulate keyboard interface;
- local vector keyboard,flatangle;
- local float blend;
- keyboard = self.havocbot_keyboard;
- if (time >= self.havocbot_keyboardtime)
+ if (skill < 10)
{
- flatdir=dir; flatdir_z = 0;
- self.havocbot_keyboardtime =
- max(
- self.havocbot_keyboardtime
- + bound(0,0.05/(skill+self.havocbot_keyboardskill),0.05)
- +random()*bound(0,0.025/(skill+self.havocbot_keyboardskill),100)
- , time);
- keyboard = '0 0 0';
-
- flatangle = self.v_angle; flatangle_z=0;
- makevectors(flatangle);
-
- local float trigger;
- local vector v_forward_right;
- local vector v_forward_left;
- blend = bound(0,skill*0.1,1);
- trigger = cvar("bot_ai_keyboard_treshold");
- v_forward_right = normalize(v_forward + v_right);
- v_forward_left = normalize(v_forward - v_right);
- // Place in reverse order !! least important direction FIRST
-
- if (skill > 4.5)
+ // Emulate keyboard interface;
+ local vector keyboard;
+ local float blend;
+ if (time >= self.havocbot_keyboardtime)
{
- if (flatdir * v_forward_right * -1 > trigger) keyboard = v_forward_right * -1;
- if (flatdir * v_forward_left * -1 > trigger) keyboard = v_forward_left * -1;
+ self.havocbot_keyboardtime =
+ max(
+ self.havocbot_keyboardtime
+ + bound(0,0.05/(skill+self.havocbot_keyboardskill),0.05)
+ +random()*bound(0,0.025/(skill+self.havocbot_keyboardskill),100)
+ , time);
+ keyboard = self.movement * (1.0 / maxspeed);
+
+ local float trigger, trigger1;
+ blend = bound(0,skill*0.1,1);
+ trigger = cvar("bot_ai_keyboard_treshold");
+ trigger1 = 0 - trigger;
+
+ // categorize forward movement
+ // at skill < 1.5 only forward
+ // at skill < 2.5 only individual directions
+ // at skill < 4.5 only individual directions, and forward diagonals
+ // at skill >= 4.5, all cases allowed
+ if (keyboard_x > trigger)
+ {
+ keyboard_x = 1;
+ if (skill < 2.5)
+ keyboard_y = 0;
+ }
+ else if (keyboard_x < trigger1 && skill > 1.5)
+ {
+ keyboard_x = -1;
+ if (skill < 4.5)
+ keyboard_y = 0;
+ }
+ else
+ {
+ keyboard_x = 0;
+ if (skill < 1.5)
+ keyboard_y = 0;
+ }
+ if (skill < 4.5)
+ keyboard_z = 0;
+
+ if (keyboard_y > trigger)
+ keyboard_y = 1;
+ else if (keyboard_y < trigger1)
+ keyboard_y = -1;
+ else
+ keyboard_y = 0;
+
+ if (keyboard_z >= trigger)
+ keyboard_z = 1;
+ else if (keyboard_z <= trigger1)
+ keyboard_z = -1;
+ else
+ keyboard_z = 0;
+
+ self.havocbot_keyboard = keyboard * maxspeed;
+ if (self.havocbot_ducktime>time) self.button5=TRUE;
}
- if (skill > 2.5)
- {
- if (flatdir * v_forward_right > trigger) keyboard = v_forward_right;
- if (flatdir * v_forward_left > trigger) keyboard = v_forward_left;
- if (flatdir * v_forward * 1 > trigger) keyboard = v_forward * -1;
- }
- if (skill > 1.5)
- {
- if (flatdir * v_right > trigger) keyboard = v_right;
- if (flatdir * v_right * -1 > trigger) keyboard = v_right * -1;
- }
- if (flatdir * v_forward > trigger) keyboard = v_forward;
- //dprint(ftos(flatdir * v_forward),"\n");
- keyboard = normalize(keyboard);
- self.havocbot_keyboard = keyboard;
- if (self.havocbot_ducktime>time) self.button5=TRUE;
+ keyboard = self.havocbot_keyboard;
+ blend = bound(0,vlen(destorg-self.origin)/cvar("bot_ai_keyboard_distance"),1); // When getting close move with 360 degree
+ //dprint("movement ", vtos(self.movement), " keyboard ", vtos(keyboard), " blend ", ftos(blend), "\n");
+ self.movement = self.movement + (keyboard - self.movement) * blend;
}
- blend = bound(0,vlen(self.goalcurrent.origin-self.origin)/cvar("bot_ai_keyboard_distance"),1); // When getting close move with 360 degree
- dir = (keyboard * blend + dir * (1-blend))*cvar("sv_maxspeed");
- self.movement_x = dir * v_forward;
- self.movement_y = dir * v_right;
- if (self.flags & FL_INWATER) self.movement_z = dir * v_up; else self.movement_z = 0;
-
if ((dir * v_up) >= cvar("sv_jumpvelocity")*0.5 && (self.flags & FL_ONGROUND)) self.button2=1;
if (((dodge * v_up) > 0) && random()*frametime >= 0.2*bound(0,(10-skill)*0.1,1)) self.button2=TRUE;
if (((dodge * v_up) < 0) && random()*frametime >= 0.5*bound(0,(10-skill)*0.1,1)) self.havocbot_ducktime=time+0.3/bound(0.1,skill,10);
-
+
};
.float havocbot_chooseenemy_finished;
@@ -223,30 +263,39 @@
self.enemy = world;
return;
}
- traceline(self.origin+self.view_ofs, self.enemy.origin+self.enemy.view_ofs*0.5,FALSE,world);
- if (trace_ent.classname != "player")
- self.havocbot_stickenemy =0;
- else if ( (trace_ent != self.enemy) || (vlen(self.enemy.origin - self.origin) > 1000) )
+ if (self.enemy)
+ {
+ if (!bot_shouldattack(self.enemy))
{
- self.havocbot_stickenemy =0;
- if( (self.health < 30) || (self.enemy.health < 0))
+ // enemy died or something, find a new target
+ self.enemy = world;
self.havocbot_chooseenemy_finished = time;
}
- //dprint(ftos(self.havocbot_stickenemy));dprint(etos(self.enemy),"\n");
- //dprint(ftos(time),"-");dprint(ftos(self.havocbot_chooseenemy_finished),"\n");
- if (self.havocbot_stickenemy == 1)
- {
- // remain tracking him for a shot while (case he went after a small corner or pilar
- self.havocbot_chooseenemy_finished = time + bound(0,skill*0.1,1)*1.8;
- return;
+ else if (self.havocbot_stickenemy)
+ {
+ // tracking last chosen enemy
+ // if enemy is visible
+ // and not really really far away
+ // and we're not severely injured
+ // then keep tracking for a half second into the future
+ traceline(self.origin+self.view_ofs, self.enemy.origin+self.enemy.view_ofs*0.5,FALSE,world);
+ if (trace_ent == self.enemy || trace_fraction == 1)
+ if (vlen(self.enemy.origin - self.origin) < 1000)
+ if (self.health > 30)
+ {
+ // remain tracking him for a shot while (case he went after a small corner or pilar
+ self.havocbot_chooseenemy_finished = time + cvar("bot_ai_enemydetectioninterval");
+ return;
+ }
+ // enemy isn't visible, or is far away, or we're injured severely
+ // so stop preferring this enemy
+ // (it will still take a half second until a new one is chosen)
+ self.havocbot_stickenemy = 0;
+ }
}
if (time < self.havocbot_chooseenemy_finished)
- {
- self.havocbot_stickenemy = 1;
return;
- }
- self.havocbot_chooseenemy_finished = time + cvar("bot_ai_enemydetectioninterval")*bound(0,(11-skill)*0.1,1);
- self.havocbot_chooseenemy_finished = time + 0.01;
+ self.havocbot_chooseenemy_finished = time + cvar("bot_ai_enemydetectioninterval");
eye = (self.origin + self.view_ofs);
best = world;
bestrating = 100000000;
@@ -387,12 +436,22 @@
lag_additem(time + self.ping, 0, 0, world, self.origin, selfvel, self.goalcurrent.origin, '0 0 0');
};
+.float bot_chooseweapontime;
void() havocbot_ai =
{
if (bot_strategytoken == self)
+ if (!bot_strategytoken_taken)
+ {
self.havocbot_role();
+ // token has been used this frame
+ bot_strategytoken_taken = TRUE;
+ }
havocbot_chooseenemy();
- havocbot_chooseweapon();
+ if (self.bot_chooseweapontime < time)
+ {
+ self.bot_chooseweapontime = time + cvar("bot_ai_chooseweaponinterval");
+ havocbot_chooseweapon();
+ }
havocbot_aim();
lag_update();
if (self.bot_aimtarg)
@@ -400,18 +459,22 @@
else if (self.goalcurrent)
{
local vector now,v,next;//,heading;
- local float distance,skillblend,distanceblend;
- now = self.goalcurrent.origin - self.origin;
+ local float distance,skillblend,distanceblend,blend;
+ next = now = self.goalcurrent.origin - (self.origin + self.view_ofs);
distance = vlen(now);
//heading = self.velocity;
//dprint(self.goalstack01.classname,etos(self.goalstack01),"\n");
if(self.goalstack01 != self && self.goalstack01 != world)
- next = self.goalstack01.origin - self.origin;
- else
- next = now;
+ next = self.goalstack01.origin - (self.origin + self.view_ofs);
skillblend=bound(0,(skill-2.5)*0.5,1); //lower skill player can't preturn
- distanceblend=bound(0,distance/cvar("bot_ai_keyboard_distance"),1);
- v = (now * (distanceblend) + next * (1-distanceblend)) * (skillblend) + now * (1-skillblend);
+ distanceblend=bound(0,distance/cvar("bot_ai_keyboard_distance"),1);
+ blend = skillblend * (1-distanceblend);
+ //v = (now * (distanceblend) + next * (1-distanceblend)) * (skillblend) + now * (1-skillblend);
+ //v = now * (distanceblend) * (skillblend) + next * (1-distanceblend) * (skillblend) + now * (1-skillblend);
+ //v = now * ((1-skillblend) + (distanceblend) * (skillblend)) + next * (1-distanceblend) * (skillblend);
+ v = now + blend * (next - now);
+ //dprint(etos(self), " ");
+ //dprint(vtos(now), ":", vtos(next), "=", vtos(v), " (blend ", ftos(blend), ")\n");
//v = now * (distanceblend) + next * (1-distanceblend);
if (self.waterlevel < 2)
v_z = 0;
Modified: trunk/data/qcsrc/server/havocbot_roles.qc
===================================================================
--- trunk/data/qcsrc/server/havocbot_roles.qc 2008-02-25 19:37:08 UTC (rev 3425)
+++ trunk/data/qcsrc/server/havocbot_roles.qc 2008-02-25 19:37:46 UTC (rev 3426)
@@ -125,24 +125,33 @@
}
};
+entity flaglist;
void(float ratingscale) havocbot_goalrating_ctf_ourflag =
{
local entity head;
- if (self.team == COLOR_TEAM1) // red
- head = find(world, classname, "item_flag_team1"); // red flag
- else // blue
- head = find(world, classname, "item_flag_team2"); // blue flag
- navigation_routerating(head, ratingscale);
+ head = flaglist;
+ while (head)
+ {
+ if (self.team == head.team)
+ break;
+ head = head.enemy;
+ }
+ if (head)
+ navigation_routerating(head, ratingscale);
};
void(float ratingscale) havocbot_goalrating_ctf_enemyflag =
{
local entity head;
- if (self.team == COLOR_TEAM1) // red
- head = find(world, classname, "item_flag_team2"); // blue flag
- else // blue
- head = find(world, classname, "item_flag_team1"); // red flag
- navigation_routerating(head, ratingscale);
+ head = flaglist;
+ while (head)
+ {
+ if (self.team != head.team)
+ break;
+ head = head.enemy;
+ }
+ if (head)
+ navigation_routerating(head, ratingscale);
};
void(float ratingscale) havocbot_goalrating_ctf_enemybase =
@@ -153,30 +162,28 @@
void(float ratingscale) havocbot_goalrating_ctf_ourstolenflag =
{
local entity head;
- if (self.team == COLOR_TEAM1) // red
- head = find(world, classname, "item_flag_team1"); // red flag
- else // blue
- head = find(world, classname, "item_flag_team2"); // blue flag
+ head = flaglist;
+ while (head)
+ {
+ if (self.team == head.team)
+ break;
+ head = head.enemy;
+ }
+ if (head)
if (head.cnt != FLAG_BASE)
navigation_routerating(head, ratingscale);
};
void(float ratingscale) havocbot_goalrating_ctf_droppedflags =
{
- local entity redflag, blueflag;
-
- redflag = find(world, classname, "item_flag_team1");
- blueflag = find(world, classname, "item_flag_team2");
-
- if (redflag == world)
- error("havocbot: item_flag_team1 missing\n");
- if (blueflag == world)
- error("havocbot: item_flag_team2 missing\n");
-
- if (redflag.cnt != FLAG_BASE) // red flag is carried or out in the field
- navigation_routerating(redflag, ratingscale);
- if (blueflag.cnt != FLAG_BASE) // blue flag is carried or out in the field
- navigation_routerating(blueflag, ratingscale);
+ local entity head;
+ head = flaglist;
+ while (head)
+ {
+ if (head.cnt != FLAG_BASE) // flag is carried or out in the field
+ navigation_routerating(head, ratingscale);
+ head = head.enemy;
+ }
};
// CTF: (always teamplay)
@@ -236,10 +243,13 @@
return;
}
// check our flag
- if (self.team == COLOR_TEAM1) // red
- f = find(world, classname, "item_flag_team1");
- else // blue
- f = find(world, classname, "item_flag_team2");
+ f = flaglist;
+ while (f)
+ {
+ if (self.team == f.team)
+ break;
+ f = f.enemy;
+ }
if (f.cnt != FLAG_BASE && canreach(f))
{
dprint("changing role to interceptor\n");
@@ -286,10 +296,13 @@
return;
}
// check our flag
- if (self.team == COLOR_TEAM1) // red
- f = find(world, classname, "item_flag_team1");
- else // blue
- f = find(world, classname, "item_flag_team2");
+ f = flaglist;
+ while (f)
+ {
+ if (self.team == f.team)
+ break;
+ f = f.enemy;
+ }
if (f.cnt == FLAG_BASE)
{
dprint("changing role back\n");
@@ -327,10 +340,13 @@
return;
}
// check our flag
- if (self.team == COLOR_TEAM1) // red
- f = find(world, classname, "item_flag_team1");
- else // blue
- f = find(world, classname, "item_flag_team2");
+ f = flaglist;
+ while (f)
+ {
+ if (self.team == f.team)
+ break;
+ f = f.enemy;
+ }
if (f.cnt != FLAG_BASE && canreach(f))
{
dprint("changing role to interceptor\n");
@@ -387,10 +403,13 @@
return;
}
// check our flag
- if (self.team == COLOR_TEAM1) // red
- f = find(world, classname, "item_flag_team1");
- else // blue
- f = find(world, classname, "item_flag_team2");
+ f = flaglist;
+ while (f)
+ {
+ if (self.team == f.team)
+ break;
+ f = f.enemy;
+ }
if (f.cnt != FLAG_BASE && canreach(f))
{
dprint("changing role to interceptor\n");
@@ -451,6 +470,7 @@
// CTF:
// choose a role according to the situation
+void() havocbot_role_dm;
void() havocbot_chooserole_ctf =
{
local float r;
@@ -515,10 +535,12 @@
+entity kh_keylist;
void(float ratingscale_team, float ratingscale_dropped, float ratingscale_enemy) havocbot_goalrating_kh =
{
local entity head;
- for(head = world; (head = find(head, classname, "item_kh_key")); )
+ head = kh_keylist;
+ while (head)
{
if(head.owner == self)
continue;
@@ -531,6 +553,7 @@
navigation_routerating(head, ratingscale_team);
else
navigation_routerating(head, ratingscale_enemy);
+ head = head.enemy;
}
};
Modified: trunk/data/qcsrc/server/keyhunt.qc
===================================================================
--- trunk/data/qcsrc/server/keyhunt.qc 2008-02-25 19:37:08 UTC (rev 3425)
+++ trunk/data/qcsrc/server/keyhunt.qc 2008-02-25 19:37:46 UTC (rev 3426)
@@ -1,4 +1,4 @@
-#define FOR_EACH_KH_KEY(v) for(v = world; (v = find(v, classname, STR_ITEM_KH_KEY)); )
+#define FOR_EACH_KH_KEY(v) for(v = kh_keylist; v; v = v.enemy )
// #define KH_PLAYER_USE_ATTACHMENT
// #define KH_PLAYER_USE_CARRIEDMODEL
@@ -32,6 +32,7 @@
return 0;
}
+entity kh_keylist;
entity kh_controller;
float kh_tracking_enabled;
float kh_teams;
@@ -320,6 +321,10 @@
break;
}
+ // link into key list
+ key.enemy = kh_keylist;
+ kh_keylist = key;
+
sprint(initial_owner, strcat("You got the ^2", key.netname, "\n"));
WaypointSprite_Spawn("", 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, FALSE);
@@ -338,6 +343,23 @@
else // it was dropped
WaypointSprite_DetachCarrier(key);
+ // remove key from key list
+ if (kh_keylist == key)
+ kh_keylist = kh_keylist.enemy;
+ else
+ {
+ o = kh_keylist;
+ while (o)
+ {
+ if (o.enemy == key)
+ {
+ o.enemy = o.enemy.enemy;
+ break;
+ }
+ o = o.enemy;
+ }
+ }
+
remove(key);
}
@@ -467,7 +489,7 @@
if(!self.owner)
if(time > self.pain_finished)
kh_LoserTeam(self.team, self);
-
+
if(self.owner)
if(kh_Key_AllOwnedByWhichTeam() != -1)
{
@@ -583,7 +605,7 @@
FOR_EACH_PLAYER(player)
if(player.team != teem)
++players;
-
+
FOR_EACH_KH_KEY(key)
if(key.owner && key.team != teem)
++keys;
@@ -649,7 +671,7 @@
entity player;
string result;
result = "";
-
+
// find a random player per team
for(i = 0; i < kh_teams; ++i)
{
@@ -764,11 +786,11 @@
// e is spectator? That's no team mate...
if(e.classname != "player")
return kh_GetCarrierSprite(self.team, -1);
-
+
// e is no key carrier: simple case...
if(!e.kh_next)
return kh_GetCarrierSprite(self.team, e.team);
-
+
// e is a key carrier: if any key is dropped or owned by another team, show
// the carrier sprite; otherwise show run here
if(kh_Key_AllOwnedByWhichTeam() == e.team)
@@ -835,8 +857,8 @@
setmodel(kh_controller, "models/keyhunt/key.md3");
kh_key_dropped = kh_controller.modelindex;
/*
- dprint(vtos(kh_controller.mins));
- dprint(vtos(kh_controller.maxs));
+ dprint(vtos(kh_controller.mins));
+ dprint(vtos(kh_controller.maxs));
dprint("\n");
*/
#ifdef KH_PLAYER_USE_CARRIEDMODEL
Modified: trunk/pro/default.cfg
===================================================================
--- trunk/pro/default.cfg 2008-02-25 19:37:08 UTC (rev 3425)
+++ trunk/pro/default.cfg 2008-02-25 19:37:46 UTC (rev 3426)
@@ -160,8 +160,13 @@
seta bot_suffix ""
seta skill_auto 0 // when 1, "skill" gets adjusted to match the best player on the map
// general bot AI cvars
+set bot_ai_thinkinterval 0.05
set bot_ai_strategyinterval 2
set bot_ai_enemydetectioninterval 0.5
+set bot_ai_dodgeupdateinterval 0.1
+set bot_ai_chooseweaponinterval 0.3
+set bot_ai_dangerdetectioninterval 0.1
+set bot_ai_dangerdetectionupdates 64
set bot_ai_aimskill_blendrate 2
set bot_ai_aimskill_fixedrate 15
set bot_ai_aimskill_firetolerance_distdegrees 180
@@ -169,7 +174,7 @@
set bot_ai_aimskill_firetolerance_maxdegrees 45
set bot_ai_aimskill_mouse 1
set bot_ai_keyboard_distance 250
-set bot_ai_keyboard_treshold 0.94
+set bot_ai_keyboard_treshold 0.57
set bot_ai_aimskill_offset 1
set bot_ai_aimskill_think 1
// Better don't touch these, there are hard to tweak!
More information about the nexuiz-commits
mailing list