[nexuiz-commits] r7384 - in trunk/data: . qcsrc/server
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Fri Aug 7 12:51:39 EDT 2009
Author: mand1nga
Date: 2009-08-07 12:51:39 -0400 (Fri, 07 Aug 2009)
New Revision: 7384
Modified:
trunk/data/defaultNexuiz.cfg
trunk/data/qcsrc/server/bots.qc
trunk/data/qcsrc/server/havocbot.qc
Log:
Added jetpack support for bots
To use it add -DBOT_JETPACK_NAVIGATION to FTQECCFLAGS in data/Makefile (will be enabled by default after the next release)
Modified: trunk/data/defaultNexuiz.cfg
===================================================================
--- trunk/data/defaultNexuiz.cfg 2009-08-07 14:28:48 UTC (rev 7383)
+++ trunk/data/defaultNexuiz.cfg 2009-08-07 16:51:39 UTC (rev 7384)
@@ -396,6 +396,9 @@
set bot_ai_bunnyhop_startdistance 250 "Run to goals located further than this distance"
set bot_ai_bunnyhop_stopdistance 220 "Stop jumping after reaching this distance to the goal"
set bot_ai_bunnyhop_firstjumpdelay 0.5 "Start running to the goal only if it was seen for more than N seconds"
+set bot_god 0 "god mode for bots"
+set bot_ai_navigation_jetpack 1 "Enable bots to navigat maps using the jetpack"
+set bot_ai_navigation_jetpack_mindistance 2500 "Bots will try fly to objects located farther than this distance"
// Better don't touch these, there are hard to tweak!
set bot_ai_aimskill_order_mix_1st 0.01 "Amount of the 1st filter output to apply to the aiming angle"
set bot_ai_aimskill_order_mix_2nd 0.1 "Amount of the 1st filter output to apply to the aiming angle"
@@ -407,7 +410,6 @@
set bot_ai_aimskill_order_filter_3th 0.2 "Acceleration filter"
set bot_ai_aimskill_order_filter_4th 0.4 "Position prediction filter. Used rarely"
set bot_ai_aimskill_order_filter_5th 0.5 "Movement prediction filter. Used rarely"
-set bot_god 0 "god mode for bots"
// waypoint editor enable
set g_waypointeditor 0
Modified: trunk/data/qcsrc/server/bots.qc
===================================================================
--- trunk/data/qcsrc/server/bots.qc 2009-08-07 14:28:48 UTC (rev 7383)
+++ trunk/data/qcsrc/server/bots.qc 2009-08-07 16:51:39 UTC (rev 7384)
@@ -8,6 +8,10 @@
float AI_STATUS_WAYPOINT_PERSONAL_LINKING = 64; // Waiting for the personal waypoint to be linked
float AI_STATUS_WAYPOINT_PERSONAL_GOING = 128; // Going to a personal waypoint
float AI_STATUS_WAYPOINT_PERSONAL_REACHED = 256; // Personal waypoint reached
+#ifdef BOT_JETPACK_NAVIGATION
+float AI_STATUS_JETPACK_FLYING = 512;
+float AI_STATUS_JETPACK_LANDING = 1024;
+#endif
// utilities for path debugging
#ifdef DEBUG_TRACEWALK
@@ -1745,6 +1749,12 @@
return ent;
}
+#ifdef BOT_JETPACK_NAVIGATION
+// fields required for jetpack navigation
+.entity navigation_jetpack_goal;
+.vector navigation_jetpack_point;
+#endif
+
// updates the best goal according to a weighted calculation of travel cost and item value of a new proposed item
.void() havocbot_role;
void() havocbot_role_ctf_offense;
@@ -1752,6 +1762,98 @@
{
if (!e)
return;
+
+#ifdef BOT_JETPACK_NAVIGATION
+ // Evaluate path using jetpack
+ if(g_jetpack)
+ if(self.items & IT_JETPACK)
+ if(cvar("bot_ai_navigation_jetpack"))
+ if(vlen(self.origin - e.origin) > cvar("bot_ai_navigation_jetpack_mindistance"))
+ {
+ vector pointa, pointb;
+
+ // dprint("jetpack ai: evaluating path for ", e.classname,"\n");
+
+ // Point A
+ traceline(self.origin, self.origin + '0 0 65535', MOVE_NORMAL, self);
+ pointa = trace_endpos - '0 0 1';
+
+ // Point B
+ traceline(e.origin, e.origin + '0 0 65535', MOVE_NORMAL, e);
+ pointb = trace_endpos - '0 0 1';
+
+ // Can I see these two points from the sky?
+ traceline(pointa, pointb, MOVE_NORMAL, self);
+
+ if(trace_fraction==1)
+ {
+ // dprint("jetpack ai: can bridge these two points\n");
+
+ // Lower the altitude of these points as much as possible
+ local float zdistance, xydistance, cost, t, fuel;
+ local vector down, npa, npb;
+
+ down = '0 0 -1' * (PL_MAX_z - PL_MIN_z) * 10;
+
+ do{
+ npa = pointa + down;
+ npb = pointb + down;
+
+ if(npa_z<=self.absmax_z)
+ break;
+
+ if(npb_z<=e.absmax_z)
+ break;
+
+ traceline(npa, npb, MOVE_NORMAL, self);
+ if(trace_fraction==1)
+ {
+ pointa = npa;
+ pointb = npb;
+ }
+ }
+ while(trace_fraction == 1);
+
+
+ // Rough estimation of fuel consumption
+ // (ignores acceleration and current xyz velocity)
+ xydistance = vlen(pointa - pointb);
+ zdistance = fabs(pointa_z - self.origin_z);
+
+ t = zdistance / cvar("g_jetpack_maxspeed_up");
+ t += xydistance / cvar("g_jetpack_maxspeed_side");
+ fuel = t * cvar("g_jetpack_fuel") * 0.8;
+
+ // dprint("jetpack ai: required fuel ", ftos(fuel), " self.ammo_fuel ", ftos(self.ammo_fuel),"\n");
+
+ // enough fuel ?
+ if(self.ammo_fuel>fuel)
+ {
+ // Estimate cost
+ // (as onground costs calculation is mostly based on distances, here we do the same establishing some relationship
+ // - between air and ground speeds)
+
+ cost = xydistance / (cvar("g_jetpack_maxspeed_side")/cvar("sv_maxspeed"));
+ cost += zdistance / (cvar("g_jetpack_maxspeed_up")/cvar("sv_maxspeed"));
+ cost *= 1.5;
+
+ // Compare against other goals
+ f = f * rangebias / (rangebias + cost);
+
+ if (navigation_bestrating < f)
+ {
+ // dprint("jetpack path: added goal", e.classname, " (with rating ", ftos(f), ")\n");
+ navigation_bestrating = f;
+ navigation_add_bestgoal(e);
+ self.navigation_jetpack_goal = e;
+ self.navigation_jetpack_point = pointb;
+ }
+ return;
+ }
+ }
+ }
+ #endif
+
//te_wizspike(e.origin);
//bprint(etos(e));
//bprint("\n");
@@ -1772,13 +1874,14 @@
if (e.nearestwaypoint.wpcost < 10000000)
{
//te_wizspike(e.nearestwaypoint.wpnearestpoint);
- //dprint(e.classname, " ", ftos(f), "/(1+", ftos((e.nearestwaypoint.wpcost + vlen(e.origin - e.nearestwaypoint.wpnearestpoint))), "/", ftos(rangebias), ") = ");
+ // dprint(e.classname, " ", ftos(f), "/(1+", ftos((e.nearestwaypoint.wpcost + vlen(e.origin - e.nearestwaypoint.wpnearestpoint))), "/", ftos(rangebias), ") = ");
f = f * rangebias / (rangebias + (e.nearestwaypoint.wpcost + vlen(e.origin - e.nearestwaypoint.wpnearestpoint)));
//if (self.havocbot_role == havocbot_role_ctf_offense)
//dprint("considering ", e.classname, " (with rating ", ftos(f), ")\n");
//dprint(ftos(f));
if (navigation_bestrating < f)
{
+ // dprint("ground path: added goal ", e.classname, " (with rating ", ftos(f), ")\n");
navigation_bestrating = f;
navigation_add_bestgoal(e);
}
@@ -1800,6 +1903,12 @@
// put the entity on the goal stack
navigation_pushroute(e);
+#ifdef BOT_JETPACK_NAVIGATION
+ if(g_jetpack)
+ if(e==self.navigation_jetpack_goal)
+ return TRUE;
+#endif
+
// if it can reach the goal there is nothing more to do
if (tracewalk(self, startposition, PL_MIN, PL_MAX, e.origin, bot_navigation_movemode))
return TRUE;
@@ -1913,6 +2022,9 @@
// begin a goal selection session (queries spawnfunc_waypoint network)
void navigation_goalrating_start()
{
+#ifdef BOT_JETPACK_NAVIGATION
+ self.navigation_jetpack_goal = world;
+#endif
navigation_bestrating = -1;
self.navigation_hasgoals = FALSE;
navigation_bestgoals_reset();
@@ -1923,6 +2035,7 @@
void navigation_goalrating_end()
{
navigation_routetogoals();
+// dprint("best goal ", self.goalcurrent.classname , "\n");
// Hack: if it can't walk to any goal just move blindly to the first visible waypoint
if not (self.navigation_hasgoals)
Modified: trunk/data/qcsrc/server/havocbot.qc
===================================================================
--- trunk/data/qcsrc/server/havocbot.qc 2009-08-07 14:28:48 UTC (rev 7383)
+++ trunk/data/qcsrc/server/havocbot.qc 2009-08-07 16:51:39 UTC (rev 7384)
@@ -308,6 +308,70 @@
self.movement = '0 0 0';
maxspeed = cvar("sv_maxspeed");
+#ifdef BOT_JETPACK_NAVIGATION
+ // Jetpack navigation
+ if(self.navigation_jetpack_goal)
+ if(self.goalcurrent==self.navigation_jetpack_goal)
+ if(self.ammo_fuel)
+ {
+ #ifdef DEBUG_BOT_GOALSTACK
+ debuggoalstack();
+ te_wizspike(self.navigation_jetpack_point);
+ #endif
+
+ // Take off
+ if not(self.aistatus & AI_STATUS_JETPACK_FLYING)
+ {
+ // Brake almost completely so it can get a good direction
+ if(vlen(self.velocity)>10)
+ return;
+ self.aistatus |= AI_STATUS_JETPACK_FLYING;
+ }
+
+ makevectors(self.v_angle_y * '0 1 0');
+ dir = normalize(self.navigation_jetpack_point - self.origin);
+
+ // Landing
+ if(self.aistatus & AI_STATUS_JETPACK_LANDING)
+ {
+ // TODO: more accurate landing (with optimum fuel usage)
+ vector p = self.origin - self.goalcurrent.origin; p_z = 0;
+ if( vlen(p) < max(cvar("g_jetpack_maxspeed_side"), vlen(self.velocity)))
+ {
+ // Brake
+ if(fabs(self.velocity_x)>maxspeed)
+ {
+ self.BUTTON_HOOK = TRUE;
+ self.movement_x = dir * v_forward * -maxspeed;
+ return;
+ }
+ // Switch to normal mode
+ self.navigation_jetpack_goal = world;
+ self.aistatus &~= AI_STATUS_JETPACK_LANDING;
+ self.aistatus &~= AI_STATUS_JETPACK_FLYING;
+ return;
+ }
+ }
+ else if(checkpvs(self.origin,self.goalcurrent))
+ {
+ // If I can see the goal switch to landing code
+ self.aistatus &~= AI_STATUS_JETPACK_FLYING;
+ self.aistatus |= AI_STATUS_JETPACK_LANDING;
+ return;
+ }
+
+ // Flying
+ self.BUTTON_HOOK = TRUE;
+ if(self.navigation_jetpack_point_z - PL_MAX_z + PL_MIN_z < self.origin_z)
+ {
+ self.movement_x = dir * v_forward * maxspeed;
+ self.movement_y = dir * v_right * maxspeed;
+ }
+ return;
+ }
+#endif
+
+ // Handling of jump pads
if(self.jumppadcount)
{
if(self.flags & FL_ONGROUND)
More information about the nexuiz-commits
mailing list