]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/default/navigation.qc
Bot waypoints: fix waypoint link creation ignoring botclip surfaces. Apply the same...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / default / navigation.qc
index 3754897bda3fe5ff2554409d318933ad3e11e38a..9c3bae8e7992f37c5ce9157bfdd7d688808346a8 100644 (file)
@@ -13,7 +13,7 @@
 
 #include <common/constants.qh>
 #include <common/net_linked.qh>
-#include <common/triggers/trigger/jumppads.qh>
+#include <common/mapobjects/trigger/jumppads.qh>
 
 .float speed;
 
@@ -246,6 +246,7 @@ vector resurface_limited(vector org, float lim, vector m1)
 // rough simulation of walking from one point to another to test if a path
 // can be traveled, used for waypoint linking and havocbot
 // if end_height is > 0 destination is any point in the vertical segment [end, end + end_height * eZ]
+// INFO: the command sv_cmd trace walk is useful to test this function in game
 bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float end_height, float movemode)
 {
        if(autocvar_bot_debug_tracewalk)
@@ -1256,7 +1257,6 @@ void navigation_routerating(entity this, entity e, float f, float rangebias)
        //print("routerating ", etos(e), " = ", ftos(f), " - ", ftos(rangebias), "\n");
 
        // Evaluate path using jetpack
-       if(g_jetpack)
        if(this.items & IT_JETPACK)
        if(autocvar_bot_ai_navigation_jetpack)
        if(vdist(this.origin - goal_org, >, autocvar_bot_ai_navigation_jetpack_mindistance))
@@ -1318,7 +1318,7 @@ void navigation_routerating(entity this, entity e, float f, float rangebias)
                        LOG_DEBUG("jetpack ai: required fuel ", ftos(fuel), " this.ammo_fuel ", ftos(this.ammo_fuel));
 
                        // enough fuel ?
-                       if(this.ammo_fuel>fuel)
+                       if(this.ammo_fuel>fuel || (this.items & IT_UNLIMITED_WEAPON_AMMO))
                        {
                                // Estimate cost
                                // (as onground costs calculation is mostly based on distances, here we do the same establishing some relationship
@@ -1573,7 +1573,7 @@ void navigation_shortenpath(entity this)
                if (trace_ent == this || tracewalk(this, this.origin, this.mins, this.maxs,
                        tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
                {
-                       LOG_DEBUG("path optimized for ", this.netname, ", removed a goal from the queue"); 
+                       LOG_DEBUG("path optimized for ", this.netname, ", removed a goal from the queue");
                        navigation_poproute(this);
                }
        }
@@ -1592,15 +1592,8 @@ int navigation_poptouchedgoals(entity this)
        {
                // make sure jumppad is really hit, don't rely on distance based checks
                // as they may report a touch even if it didn't really happen
-               if(this.lastteleporttime > 0
-                       && time - this.lastteleporttime < ((this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL) ? 2 : 0.15))
+               if(this.lastteleporttime > 0 && TELEPORT_USED(this, this.goalcurrent))
                {
-                       if (this.jumppadcount && !boxesoverlap(this.goalcurrent.absmin, this.goalcurrent.absmax,
-                               this.lastteleport_origin + STAT(PL_MIN, this), this.lastteleport_origin + STAT(PL_MAX, this)))
-                       {
-                               return;
-                       }
-
                        if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
                        if(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL && this.goalcurrent.owner==this)
                        {
@@ -1614,6 +1607,37 @@ int navigation_poptouchedgoals(entity this)
                else
                        return removed_goals;
        }
+       else if (this.lastteleporttime > 0)
+       {
+               // sometimes bot is pushed so hard (by a jumppad or a shot) that ends up touching the next
+               // teleport / jumppad / warpzone present in its path skipping check of one or more goals
+               // if so immediately fix bot path by removing skipped goals
+               entity tele_ent = NULL;
+               if (this.goalstack01 && (this.goalstack01.wpflags & WAYPOINTFLAG_TELEPORT))
+                       tele_ent = this.goalstack01;
+               else if (this.goalstack02 && (this.goalstack02.wpflags & WAYPOINTFLAG_TELEPORT))
+                       tele_ent = this.goalstack02;
+               else if (this.goalstack03 && (this.goalstack03.wpflags & WAYPOINTFLAG_TELEPORT))
+                       tele_ent = this.goalstack03;
+               if (tele_ent && TELEPORT_USED(this, tele_ent))
+               {
+                       if (this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
+                       if (tele_ent.wpflags & WAYPOINTFLAG_PERSONAL && tele_ent.owner == this)
+                       {
+                               this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
+                               this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
+                       }
+                       while (this.goalcurrent != tele_ent)
+                       {
+                               navigation_poproute(this);
+                               ++removed_goals;
+                       }
+                       navigation_poproute(this);
+                       this.lastteleporttime = 0;
+                       ++removed_goals;
+                       return removed_goals;
+               }
+       }
 
        // Loose goal touching check when running
        if(this.aistatus & AI_STATUS_RUNNING)
@@ -1784,11 +1808,20 @@ void botframe_updatedangerousobjects(float maxupdate)
 
 void navigation_unstuck(entity this)
 {
-       float search_radius = 1000;
-
        if (!autocvar_bot_wander_enable)
                return;
 
+       bool has_user_waypoints = false;
+       IL_EACH(g_waypoints, !(it.wpflags & WAYPOINTFLAG_GENERATED),
+       {
+               has_user_waypoints = true;
+               break;
+       });
+       if (!has_user_waypoints)
+               return;
+
+       float search_radius = 1000;
+
        if (!bot_waypoint_queue_owner)
        {
                LOG_DEBUG(this.netname, " stuck, taking over the waypoints queue");
@@ -1806,7 +1839,7 @@ void navigation_unstuck(entity this)
                float d = vlen2(this.origin - bot_waypoint_queue_goal.origin);
                LOG_DEBUG(this.netname, " evaluating ", bot_waypoint_queue_goal.classname, " with distance ", ftos(d));
                set_tracewalk_dest(bot_waypoint_queue_goal, this.origin, false);
-               if (tracewalk(bot_waypoint_queue_goal, this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this),
+               if (tracewalk(this, this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this),
                        tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode))
                {
                        if( d > bot_waypoint_queue_bestgoalrating)