r5813 - trunk/data/qcsrc/server
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Mon Feb 9 09:58:59 EST 2009
Author: mand1nga
Date: 2009-02-09 09:58:59 -0500 (Mon, 09 Feb 2009)
New Revision: 5813
Modified:
trunk/data/qcsrc/server/bots.qc
trunk/data/qcsrc/server/havocbot.qc
trunk/data/qcsrc/server/havocbot_roles.qc
Log:
Bot improvements:
Use the 2nd best rated goal if something happened to the primary goal (ie: someone picked it up before). This is cheaper than forcing a whole strategy re-think.
Anti lemming behavior workaround
Force strategy re-think upon respawn
Moved keyboard emulation out of movetogoal()
Made them "try" to jump out of lava
Modified: trunk/data/qcsrc/server/bots.qc
===================================================================
--- trunk/data/qcsrc/server/bots.qc 2009-02-09 14:43:03 UTC (rev 5812)
+++ trunk/data/qcsrc/server/bots.qc 2009-02-09 14:58:59 UTC (rev 5813)
@@ -366,11 +366,12 @@
// used during navigation_goalrating_begin/end sessions
float navigation_bestrating;
entity navigation_bestgoal;
+entity navigation_alternativegoal;
+.entity alternativegoal;
-
/////////////////////////////////////////////////////////////////////////////
// spawnfunc_waypoint management
/////////////////////////////////////////////////////////////////////////////
@@ -1252,6 +1253,7 @@
//dprint(ftos(f));
if (navigation_bestrating < f)
{
+ navigation_alternativegoal = navigation_bestgoal;
navigation_bestrating = f;
navigation_bestgoal = e;
}
@@ -1325,6 +1327,7 @@
{
if (self.havocbot_role == havocbot_role_ctf_offense)
dprint(navigation_bestgoal.classname, " (with rating ", ftos(navigation_bestrating), ")\n");
+ self.alternativegoal = navigation_alternativegoal;
navigation_routetogoal(navigation_bestgoal);
};
@@ -1367,6 +1370,7 @@
.float(entity player, entity item) bot_pickupevalfunc;
.float bot_pickupbasevalue;
.float bot_canfire;
+.float bot_strategytime;
// used for aiming currently
// FIXME: make the weapon code use these and then replace the calculations here with a call to the weapon code
@@ -1940,10 +1944,13 @@
if (self.deadflag)
{
if (self.deadflag == DEAD_DEAD)
+ {
self.BUTTON_JUMP = 1; // press jump to respawn
- return;
+ self.bot_strategytime = 0;
+ return;
+ }
}
-
+
// now call the current bot AI (havocbot for example)
self.bot_ai();
};
Modified: trunk/data/qcsrc/server/havocbot.qc
===================================================================
--- trunk/data/qcsrc/server/havocbot.qc 2009-02-09 14:43:03 UTC (rev 5812)
+++ trunk/data/qcsrc/server/havocbot.qc 2009-02-09 14:58:59 UTC (rev 5813)
@@ -55,10 +55,82 @@
*/
};
-//.float havocbotignoretime;
.float havocbot_keyboardtime;
.float havocbot_ducktime;
.vector havocbot_keyboard;
+void havocbot_keyboard_movement(vector destorg)
+{
+ local vector keyboard;
+ local float blend, maxspeed;
+
+ maxspeed = cvar("sv_maxspeed");
+
+ if (time < self.havocbot_keyboardtime)
+ return;
+
+ 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.BUTTON_CROUCH=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;
+};
+
+//.float havocbotignoretime;
//.vector bot_dodgevector;
//.float bot_dodgevector_time;
//.float bot_dodgevector_jumpbutton;
@@ -91,13 +163,26 @@
if (self.goalcurrent == world)
return;
+
navigation_poptouchedgoals();
if (self.goalcurrent == world)
{
- // ran out of goals, rethink strategy as soon as possible
- self.bot_strategytime = 0;
+ if(self.alternativegoal==world)
+ {
+ // ran out of goals, rethink strategy as soon as possible
+ self.bot_strategytime = 0;
+ return;
+ }
+ // try to use the alternative goal
+ navigation_findnearestwaypoint(self.alternativegoal, TRUE);
+ navigation_routetogoal(self.alternativegoal);
+ self.alternativegoal = world;
return;
}
+
+// te_wizspike(self.goalcurrent.origin);
+// te_lightning2(world, self.origin, self.goalcurrent.origin);
+
m1 = self.goalcurrent.origin + self.goalcurrent.mins;
m2 = self.goalcurrent.origin + self.goalcurrent.maxs;
destorg = self.origin;
@@ -109,23 +194,21 @@
dir = normalize(diff);
flatdir = diff;flatdir_z = 0;
flatdir = normalize(flatdir);
+
//if (self.bot_dodgevector_time < time)
{
// 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)
+ 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;
- //}
-
+ makevectors(self.v_angle);
+ self.BUTTON_JUMP = 1;
+ // TODO: Make them swim up
+ }
+ else
+ {
// 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);
@@ -144,18 +227,42 @@
}
}
- 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;
+ // avoiding dangers and obstacles
+ // TODO: don't make this check every frame
+ if(self.flags & FL_ONGROUND)
+ {
+ local vector dst_ahead, dst_down;
+ dst_ahead = self.origin + self.view_ofs + (self.velocity * 0.3);
+ dst_down = dst_ahead + '0 0 -1500';
+
+ traceline(self.origin + self.view_ofs , dst_ahead, TRUE, world);
+
+ if(trace_fraction == 1){
+ traceline(dst_ahead , dst_down, TRUE, world);
+ // te_lightning2(world, self.origin, dst_ahead); // Draw "ahead" look
+ if(trace_fraction == 1)
+ {
+ s = pointcontents(trace_endpos + '0 0 1');
+ if (s == CONTENT_LAVA || s == CONTENT_SLIME)
+ evadelava = normalize(self.velocity) * -1;
+ else if (s == CONTENT_SKY)
+ evadeobstacle = normalize(self.velocity) * -1;
+ else if (tracebox_hits_trigger_hurt(dst_ahead, self.mins, self.maxs, trace_endpos))
+ {
+ // te_lightning2(world, dst_ahead, dst_down); // Draw "downards" look
+ // TODO: this could be better, but actually it stops lemming behavior
+ evadeobstacle = flatdir * -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
@@ -176,79 +283,13 @@
self.movement_y = dir * v_right * maxspeed;
self.movement_z = dir * v_up * maxspeed;
+ // Emulate keyboard interface
if (skill < 10)
- {
- // Emulate keyboard interface;
- local vector keyboard;
- local float blend;
- if (time >= self.havocbot_keyboardtime)
- {
- 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);
+ havocbot_keyboard_movement(destorg);
- 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.BUTTON_CROUCH=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;
- }
-
if ((dir * v_up) >= cvar("sv_jumpvelocity")*0.5 && (self.flags & FL_ONGROUND)) self.BUTTON_JUMP=1;
if (((dodge * v_up) > 0) && random()*frametime >= 0.2*bound(0,(10-skill)*0.1,1)) self.BUTTON_JUMP=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;
@@ -559,6 +600,9 @@
// token has been used this frame
bot_strategytoken_taken = TRUE;
}
+ if(self.deadflag)
+ return;
+
havocbot_chooseenemy();
if (self.bot_chooseweapontime < time )
{
Modified: trunk/data/qcsrc/server/havocbot_roles.qc
===================================================================
--- trunk/data/qcsrc/server/havocbot_roles.qc 2009-02-09 14:43:03 UTC (rev 5812)
+++ trunk/data/qcsrc/server/havocbot_roles.qc 2009-02-09 14:58:59 UTC (rev 5813)
@@ -1,7 +1,6 @@
.float havocbot_role_timeout;
.void() havocbot_previous_role;
-.float bot_strategytime;
.void() havocbot_role;
float bot_ignore_bots;
@@ -236,10 +235,28 @@
if (self != head)
if (head.health > 0)
if ((noteam && (!bot_ignore_bots || clienttype(head) == CLIENTTYPE_REAL)) || head.team != self.team)
- if (vlen(head.origin - org) < sradius)
{
+ if (vlen(head.origin - org) > sradius)
+ continue;
+
+ // rate only visible enemies
+ /*
+ traceline(self.origin + self.view_ofs, head.origin, MOVE_NOMONSTERS, self);
+ if (trace_fraction < 1 || trace_ent != head)
+ continue;
+ */
+
+ // not falling
+ if(head.flags & FL_ONGROUND == 0)
+ {
+ traceline(head.origin, head.origin + '0 0 -1500', TRUE, world);
+ t = pointcontents(trace_endpos + '0 0 1');
+ if (t != CONTENT_SOLID)
+ continue;
+ // TODO: check for trigger_hurt here
+ }
+
t = (self.health + self.armorvalue ) / (head.health + head.armorvalue );
- // clientcommand(self, strcat("say rating ", ftos(t*ratingscale)));
navigation_routerating(head, t * ratingscale, 2000);
}
}
More information about the nexuiz-commits
mailing list