]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Fix linking to teleports and jumppads waypoints not working from a lower point of...
authorterencehill <piuntn@gmail.com>
Thu, 18 May 2017 22:14:22 +0000 (00:14 +0200)
committerterencehill <piuntn@gmail.com>
Thu, 18 May 2017 22:14:22 +0000 (00:14 +0200)
qcsrc/server/bot/api.qh
qcsrc/server/bot/default/navigation.qc
qcsrc/server/bot/default/navigation.qh
qcsrc/server/bot/default/waypoints.qc
qcsrc/server/bot/null/bot_null.qc
qcsrc/server/command/sv_cmd.qc

index 330e61961d4eb7941e809a568dc0d86f828e231b..695763fe5606b124684352c992b860a881defb8b 100644 (file)
@@ -86,7 +86,7 @@ void navigation_markroutes(entity this, entity fixed_source_waypoint);
 void navigation_markroutes_inverted(entity fixed_source_waypoint);
 void navigation_routerating(entity this, entity e, float f, float rangebias);
 
-bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode);
+bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float end_height, float movemode);
 
 void waypoint_remove_fromeditor(entity pl);
 void waypoint_remove(entity wp);
index 76ac3389cdac1e72961e48b23c64bc3ebb27d63b..bdcab001b5ad756246336e9f935a893c1602efea 100644 (file)
@@ -39,8 +39,8 @@ void navigation_dynamicgoal_unset(entity this)
 
 // rough simulation of walking from one point to another to test if a path
 // can be traveled, used for waypoint linking and havocbot
-
-bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode)
+// if end_height is > 0 destination is any point in the vertical segment [end, end + end_height * eZ]
+bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float end_height, float movemode)
 {
        vector org;
        vector move;
@@ -90,11 +90,13 @@ bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float m
                return false;
        }
 
+       vector end2 = end;
+       if(end_height)
+               end2.z += end_height;
        // Movement loop
-       move = end - org;
        for (;;)
        {
-               if (boxesoverlap(end, end, org + m1 + '-1 -1 -1', org + m2 + '1 1 1'))
+               if (boxesoverlap(end, end2, org + m1 + '-1 -1 -1', org + m2 + '1 1 1'))
                {
                        // Succeeded
                        if(autocvar_bot_debug_tracewalk)
@@ -181,7 +183,7 @@ bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float m
                                                FOREACH_ENTITY_CLASS("func_ladder", true,
                                                {
                                                        if(boxesoverlap(org + jumpheight_vec + m1 + '-1 -1 -1', org + jumpheight_vec + m2 + '1 1 1', it.absmin, it.absmax))
-                                                       if(boxesoverlap(end, end, it.absmin + (m1 - eZ * m1.z - '1 1 0'), it.absmax + (m2 - eZ * m2.z + '1 1 0')))
+                                                       if(boxesoverlap(end, end2, it.absmin + (m1 - eZ * m1.z - '1 1 0'), it.absmax + (m2 - eZ * m2.z + '1 1 0')))
                                                                ladder_found = true; // can't return here ("Loop mutex held by tracewalk" error)
                                                });
                                                if(ladder_found)
@@ -409,12 +411,12 @@ float navigation_waypoint_will_link(vector v, vector org, entity ent, float walk
                {
                        if (walkfromwp)
                        {
-                               if (tracewalk(ent, v, PL_MIN_CONST, PL_MAX_CONST, org, bot_navigation_movemode))
+                               if (tracewalk(ent, v, PL_MIN_CONST, PL_MAX_CONST, org, 0, bot_navigation_movemode))
                                        return true;
                        }
                        else
                        {
-                               if (tracewalk(ent, org, PL_MIN_CONST, PL_MAX_CONST, v, bot_navigation_movemode))
+                               if (tracewalk(ent, org, PL_MIN_CONST, PL_MAX_CONST, v, 0, bot_navigation_movemode))
                                        return true;
                        }
                }
@@ -503,8 +505,9 @@ entity navigation_findnearestwaypoint(entity ent, float walkfromwp)
 float navigation_markroutes_nearestwaypoints(entity this, float maxdist)
 {
        vector v, m1, m2;
-//     navigation_testtracewalk = true;
+       //navigation_testtracewalk = true;
        int c = 0;
+       float v_height;
        IL_EACH(g_waypoints, !it.wpconsidered,
        {
                if (it.wpisbox)
@@ -514,16 +517,20 @@ float navigation_markroutes_nearestwaypoints(entity this, float maxdist)
                        v = this.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);
+                       v.z = m1.z;
+                       v_height = m2.z - m1.z;
                }
                else
+               {
                        v = it.origin;
+                       v_height = 0;
+               }
                vector diff = v - this.origin;
                diff.z = max(0, diff.z);
                if(vdist(diff, <, maxdist))
                {
                        it.wpconsidered = true;
-                       if (tracewalk(this, this.origin, this.mins, this.maxs, v, bot_navigation_movemode))
+                       if (tracewalk(this, this.origin, this.mins, this.maxs, v, v_height, bot_navigation_movemode))
                        {
                                it.wpnearestpoint = v;
                                it.wpcost = waypoint_getdistancecost(this.origin, v) + it.dmg;
@@ -961,7 +968,10 @@ bool navigation_routetogoal(entity this, entity e, vector startposition)
                return true;
 
        // if it can reach the goal there is nothing more to do
-       if (tracewalk(this, startposition, STAT(PL_MIN, this), STAT(PL_MAX, this), (e.absmin + e.absmax) * 0.5, bot_navigation_movemode))
+       vector dest = (e.absmin + e.absmax) * 0.5;
+       dest.z = e.absmin.z;
+       float dest_height = e.absmax.z - e.absmin.z;
+       if (tracewalk(this, startposition, STAT(PL_MIN, this), STAT(PL_MAX, this), dest, dest_height, bot_navigation_movemode))
                return true;
 
        entity nearest_wp = NULL;
@@ -980,10 +990,21 @@ bool navigation_routetogoal(entity this, entity e, vector startposition)
        if(nearest_wp && nearest_wp.enemy)
        {
                // often path can be optimized by not adding the nearest waypoint
-               if (this.goalentity.nearestwaypoint_dist < 8
-                       || (!this.goalentity.navigation_dynamicgoal && navigation_item_islinked(nearest_wp.enemy, this.goalentity))
-                       || (this.goalentity.navigation_dynamicgoal && tracewalk(this, nearest_wp.enemy.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), (this.goalentity.absmin + this.goalentity.absmax) * 0.5, bot_navigation_movemode)))
+               if (this.goalentity.nearestwaypoint_dist < 8)
                        e = nearest_wp.enemy;
+               else
+               {
+                       if (this.goalentity.navigation_dynamicgoal)
+                       {
+                               vector dest = (this.goalentity.absmin + this.goalentity.absmax) * 0.5;
+                               dest.z = this.goalentity.absmin.z;
+                               float dest_height = this.goalentity.absmax.z - this.goalentity.absmin.z;
+                               if(tracewalk(this, nearest_wp.enemy.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), dest, dest_height, bot_navigation_movemode))
+                                       e = nearest_wp.enemy;
+                       }
+                       else if(navigation_item_islinked(nearest_wp.enemy, this.goalentity))
+                               e = nearest_wp.enemy;
+               }
        }
 
        for (;;)
@@ -1026,16 +1047,21 @@ void navigation_poptouchedgoals(entity this)
        if(this.goalstack01 && !wasfreed(this.goalstack01))
        if(vlen2(this.goalcurrent.origin - this.origin) > vlen2(this.goalstack01.origin - this.origin))
        if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
-       if(tracewalk(this, this.origin, this.mins, this.maxs, (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5, bot_navigation_movemode))
        {
-               LOG_DEBUG("path optimized for ", this.netname, ", removed a goal from the queue");
-               navigation_poproute(this);
-               // TODO this may also be a nice idea to do "early" (e.g. by
-               // manipulating the vlen() comparisons) to shorten paths in
-               // general - this would make bots walk more "on rails" than
-               // "zigzagging" which they currently do with sufficiently
-               // random-like waypoints, and thus can make a nice bot
-               // personality property
+               vector dest = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
+               dest.z = this.goalstack01.absmin.z;
+               float dest_height = this.goalstack01.absmax.z - this.goalstack01.absmin.z;
+               if(tracewalk(this, this.origin, this.mins, this.maxs, dest, dest_height, bot_navigation_movemode))
+               {
+                       LOG_DEBUG("path optimized for ", this.netname, ", removed a goal from the queue");
+                       navigation_poproute(this);
+                       // TODO this may also be a nice idea to do "early" (e.g. by
+                       // manipulating the vlen() comparisons) to shorten paths in
+                       // general - this would make bots walk more "on rails" than
+                       // "zigzagging" which they currently do with sufficiently
+                       // random-like waypoints, and thus can make a nice bot
+                       // personality property
+               }
        }
 
        // Loose goal touching check when running
@@ -1173,7 +1199,10 @@ void navigation_unstuck(entity this)
                // evaluate the next goal on the queue
                float d = vlen2(this.origin - bot_waypoint_queue_goal.origin);
                LOG_DEBUG(this.netname, " evaluating ", bot_waypoint_queue_goal.classname, " with distance ", ftos(d));
-               if(tracewalk(bot_waypoint_queue_goal, this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), bot_waypoint_queue_goal.origin, bot_navigation_movemode))
+               vector dest = (bot_waypoint_queue_goal.absmin + bot_waypoint_queue_goal.absmax) * 0.5;
+               dest.z = bot_waypoint_queue_goal.absmin.z;
+               float dest_height = bot_waypoint_queue_goal.absmax.z - bot_waypoint_queue_goal.absmin.z;
+               if(tracewalk(bot_waypoint_queue_goal, this.origin, STAT(PL_MIN, this), STAT(PL_MAX, this), dest, dest_height, bot_navigation_movemode))
                {
                        if( d > bot_waypoint_queue_bestgoalrating)
                        {
index ddb4bd3ef8995ba9908ad0fbb7e6d8cb2c6db9dd..e94c32a82fac9232b0def98574b6ecbc2e6fd3fd 100644 (file)
@@ -87,7 +87,7 @@ void debugnodestatus(vector position, float status);
 
 void debuggoalstack(entity this);
 
-float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode);
+float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float end_height, float movemode);
 
 float navigation_markroutes_nearestwaypoints(entity this, float maxdist);
 float navigation_routetogoal(entity this, entity e, vector startposition);
index 73c901be642f2c3288cba7ae7bc618e21edae06c..7a5728ac843118026e3587bd04d8bba7c14573ab 100644 (file)
@@ -571,6 +571,8 @@ void waypoint_think(entity this)
                                ++relink_lengthculled;
                                continue;
                        }
+                       float sv_deviation = 0;
+                       float ev_deviation = 0;
                        navigation_testtracewalk = 0;
                        if (!this.wpisbox)
                        {
@@ -578,6 +580,7 @@ void waypoint_think(entity this)
                                if (!trace_startsolid)
                                {
                                        //dprint("sv deviation", vtos(trace_endpos - sv), "\n");
+                                       sv_deviation = trace_endpos.z + 1 - sv.z;
                                        sv = trace_endpos + '0 0 1';
                                }
                        }
@@ -587,19 +590,37 @@ void waypoint_think(entity this)
                                if (!trace_startsolid)
                                {
                                        //dprint("ev deviation", vtos(trace_endpos - ev), "\n");
+                                       ev_deviation = trace_endpos.z + 1 - ev.z;
                                        ev = trace_endpos + '0 0 1';
                                }
                        }
                        //traceline(this.origin, it.origin, false, NULL);
                        //if (trace_fraction == 1)
-                       if (!this.wpisbox && tracewalk(this, sv, PL_MIN_CONST, PL_MAX_CONST, ev, MOVE_NOMONSTERS))
-                               waypoint_addlink(this, it);
-                       else
+                       if (this.wpisbox)
                                relink_walkculled += 0.5;
-                       if (!it.wpisbox && tracewalk(it, ev, PL_MIN_CONST, PL_MAX_CONST, sv, MOVE_NOMONSTERS))
-                               waypoint_addlink(it, this);
                        else
+                       {
+                               vector dest = ev;
+                               dest.z = em1.z + ev_deviation;
+                               float dest_height = em2.z - em1.z;
+                               if(tracewalk(this, sv, PL_MIN_CONST, PL_MAX_CONST, dest, dest_height, MOVE_NOMONSTERS))
+                                       waypoint_addlink(this, it);
+                               else
+                                       relink_walkculled += 0.5;
+                       }
+
+                       if (it.wpisbox)
                                relink_walkculled += 0.5;
+                       else
+                       {
+                               vector dest = sv;
+                               dest.z = sm1.z + sv_deviation;
+                               float dest_height = sm2.z - sm1.z;
+                               if(tracewalk(it, ev, PL_MIN_CONST, PL_MAX_CONST, dest, dest_height, MOVE_NOMONSTERS))
+                                       waypoint_addlink(it, this);
+                               else
+                                       relink_walkculled += 0.5;
+                       }
                }
        });
        navigation_testtracewalk = 0;
index 46a0ffbba00dfc41f22cb6df24b244be937981a3..6c60a70e35977545dd74b11242deed9da6aefd13 100644 (file)
@@ -28,7 +28,7 @@ void navigation_markroutes(entity this, entity fixed_source_waypoint) { }
 void navigation_markroutes_inverted(entity fixed_source_waypoint) { }
 void navigation_routerating(entity this, entity e, float f, float rangebias) { }
 
-bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode) { return false; }
+bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float end_height, float movemode) { return false; }
 
 void waypoint_remove_fromeditor(entity pl) { }
 void waypoint_remove(entity wp) { }
index 145e75952a81f9fd9e555292f26f666ee43473f8..7b33033de2b4e39fb2544e09df16ad1d6faadf78 100644 (file)
@@ -1567,8 +1567,10 @@ void GameCommand_trace(float request, float argc)
                                        if (argc == 4)
                                        {
                                                e = nextent(NULL);
-                                               if (tracewalk(e, stov(argv(2)), e.mins, e.maxs, stov(argv(3)), MOVE_NORMAL)) LOG_INFO("can walk\n");
-                                               else LOG_INFO("cannot walk\n");
+                                               if (tracewalk(e, stov(argv(2)), e.mins, e.maxs, stov(argv(3)), 0, MOVE_NORMAL))
+                                                       LOG_INFO("can walk\n");
+                                               else
+                                                       LOG_INFO("cannot walk\n");
                                                return;
                                        }
                                }