]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/default/navigation.qc
Bot AI: fix bots sometimes going back and forth between a waypoint and a frozen teamm...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / default / navigation.qc
index cfaec7f2669957068c58c41b5116e6b08008a72a..cd21f7aa8767028a43e5e60f7c70954fef48b664 100644 (file)
@@ -625,7 +625,7 @@ void navigation_clearroute(entity this)
        this.goalcurrent_distance_2d = FLOAT_MAX;
        this.goalcurrent_distance_z = FLOAT_MAX;
        this.goalcurrent_distance_time = 0;
-       //print("bot ", etos(this), " clear\n");
+       this.goalentity_lock_timeout = 0;
        this.goalentity = NULL;
        this.goalcurrent = NULL;
        this.goalstack01 = NULL;
@@ -721,7 +721,10 @@ void navigation_poproute(entity this)
        this.goalcurrent_distance_time = 0;
        //print("bot ", etos(this), " pop\n");
        if(this.goalcurrent == this.goalentity)
+       {
                this.goalentity = NULL;
+               this.goalentity_lock_timeout = 0;
+       }
        this.goalcurrent = this.goalstack01;
        this.goalstack01 = this.goalstack02;
        this.goalstack02 = this.goalstack03;
@@ -849,6 +852,20 @@ entity navigation_findnearestwaypoint_withdist_except(entity ent, float walkfrom
                        best = it;
                }
        });
+       if(!best && !ent.navigation_dynamicgoal)
+       {
+               int solid_save = ent.solid;
+               ent.solid = SOLID_BSP;
+               IL_EACH(g_jumppads, true,
+               {
+                       if(trigger_push_test(it, ent))
+                       {
+                               best = it.nearestwaypoint;
+                               break;
+                       }
+               });
+               ent.solid = solid_save;
+       }
        return best;
 }
 entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
@@ -1223,7 +1240,10 @@ void navigation_routerating(entity this, entity e, float f, float rangebias)
                if ((!e.nearestwaypoint || e.navigation_dynamicgoal)
                        && e.nearestwaypointtimeout >= 0 && time > e.nearestwaypointtimeout)
                {
-                       e.nearestwaypoint = nwp = navigation_findnearestwaypoint(e, true);
+                       if(IS_BOT_CLIENT(e) && e.goalcurrent && e.goalcurrent.classname == "waypoint")
+                               e.nearestwaypoint = nwp = e.goalcurrent;
+                       else
+                               e.nearestwaypoint = nwp = navigation_findnearestwaypoint(e, true);
                        if(!nwp)
                        {
                                LOG_DEBUG("FAILED to find a nearest waypoint to '", e.classname, "' #", etos(e));
@@ -1247,11 +1267,15 @@ void navigation_routerating(entity this, entity e, float f, float rangebias)
        }
 
        LOG_DEBUG("-- checking ", e.classname, " (with cost ", ftos(nwp.wpcost), ")");
-       if (nwp)
-       if (nwp.wpcost < 10000000)
+       if (nwp && nwp.wpcost < 10000000)
        {
                //te_wizspike(nwp.wpnearestpoint);
-               float cost = nwp.wpcost + waypoint_gettravelcost(nwp.wpnearestpoint, goal_org, nwp, e);
+               float nwptoitem_cost = 0;
+               if(nwp.wpflags & WAYPOINTFLAG_TELEPORT)
+                       nwptoitem_cost = nwp.wp00mincost;
+               else
+                       nwptoitem_cost = waypoint_gettravelcost(nwp.wpnearestpoint, goal_org, nwp, e);
+               float cost = nwp.wpcost + nwptoitem_cost;
                LOG_DEBUG(e.classname, " ", ftos(f), "/(1+", ftos(cost), "/", ftos(rangebias), ") = ");
                f = f * rangebias / (rangebias + cost);
                LOG_DEBUG("considering ", e.classname, " (with rating ", ftos(f), ")");
@@ -1388,6 +1412,17 @@ int navigation_poptouchedgoals(entity this)
        if(vlen2(this.goalcurrent.origin - this.goalstack01.origin) > vlen2(this.goalstack01.origin - this.origin))
        if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
        {
+               // this can happen when a player stands still or is frozen
+               // NOTE: this is only needed because tracewalk always fail when destination
+               // point is on a player and bot_navigation_ignoreplayers is false
+               if (this.goalentity.navigation_dynamicgoal
+                       && boxesoverlap(this.absmin, this.absmax, this.goalentity.absmin, this.goalentity.absmax))
+               {
+                       navigation_poproute(this);
+                       ++removed_goals;
+                       return removed_goals;
+               }
+
                vector dest = '0 0 0';
                float dest_height = 0;
                SET_TRACEWALK_DESTCOORDS(this.goalstack01, this.origin, dest, dest_height);