]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Improve linking of normal waypoints to ladders by autogenerating waypoints for ladders
authorterencehill <piuntn@gmail.com>
Sun, 16 Apr 2017 18:50:08 +0000 (20:50 +0200)
committerterencehill <piuntn@gmail.com>
Sun, 16 Apr 2017 18:50:08 +0000 (20:50 +0200)
qcsrc/common/triggers/func/ladder.qc
qcsrc/server/bot/api.qh
qcsrc/server/bot/default/navigation.qc
qcsrc/server/bot/default/waypoints.qc

index 5ff2bdcc247133ac99b9c7a95f1ae4da3fe38a82..58c726360fcac469dc640f8962be1d5ac6ef5272 100644 (file)
@@ -45,6 +45,10 @@ void func_ladder_init(entity this)
 
        trigger_init(this);
        func_ladder_link(this);
+       vector top = (this.absmin + this.absmax) / 2;
+       top.z = this.absmax.z + 1 - PL_MIN_CONST.z;
+       float height = this.absmax.z - this.absmin.z;
+       waypoint_spawnforteleporter_boxes(this, WAYPOINTFLAG_LADDER, this.absmin, this.absmax, top, top, height);
 }
 
 spawnfunc(func_ladder)
index 3cbf2d9d2333edc85c7d7a844a83b194b48562b9..330e61961d4eb7941e809a568dc0d86f828e231b 100644 (file)
@@ -10,6 +10,7 @@ const int WAYPOINTFLAG_PERSONAL = BIT(19);
 const int WAYPOINTFLAG_PROTECTED = BIT(18);  // Useless WP detection never kills these.
 const int WAYPOINTFLAG_USEFUL = BIT(17);  // Useless WP detection temporary flag.
 const int WAYPOINTFLAG_DEAD_END = BIT(16);  // Useless WP detection temporary flag.
+const int WAYPOINTFLAG_LADDER = BIT(15);
 
 entity kh_worldkeylist;
 .entity kh_worldkeynext;
index b4503fa148a61e14164dc832d878fd40371ca615..6fafa9d473cdd3b2aeab617c188e11868372a260 100644 (file)
@@ -50,7 +50,6 @@ bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float m
        float stepdist;
        float ignorehazards;
        float swimming;
-       entity tw_ladder = NULL;
 
        if(autocvar_bot_debug_tracewalk)
        {
@@ -178,17 +177,26 @@ bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float m
                                        tracebox(org + jumpstepheightvec, m1, m2, move + jumpstepheightvec, movemode, e);
                                        if (trace_fraction < 1 || trace_startsolid)
                                        {
+                                               bool ladder_found = false;
+                                               FOREACH_ENTITY_CLASS("func_ladder", boxesoverlap(trace_endpos + m1 + '-1 -1 -1', trace_endpos + 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')))
+                                                               ladder_found = true; // can't return here ("Loop mutex held by tracewalk" error)
+                                               });
+                                               if(ladder_found)
+                                               {
+                                                       if(autocvar_bot_debug_tracewalk)
+                                                               debugnodestatus(org, DEBUG_NODE_SUCCESS);
+
+                                                       //print("tracewalk: ", vtos(start), " can reach ", vtos(end), "\n");
+                                                       return true;
+                                               }
+
                                                if(autocvar_bot_debug_tracewalk)
                                                        debugnodestatus(trace_endpos, DEBUG_NODE_WARNING);
 
-                                               FOREACH_ENTITY_CLASS("func_ladder", true,
-                                                       { it.solid = SOLID_BSP; });
-
                                                traceline( org, move, movemode, e);
 
-                                               FOREACH_ENTITY_CLASS("func_ladder", true,
-                                                       { it.solid = SOLID_TRIGGER; });
-
                                                if ( trace_ent.classname == "door_rotating" || trace_ent.classname == "door")
                                                {
                                                        vector nextmove;
@@ -200,24 +208,6 @@ bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float m
                                                                move = nextmove;
                                                        }
                                                }
-                                               else if (trace_ent.classname == "func_ladder")
-                                               {
-                                                       tw_ladder = trace_ent;
-                                                       vector ladder_bottom = trace_endpos - dir * m2.x;
-                                                       vector ladder_top = ladder_bottom;
-                                                       ladder_top.z = trace_ent.absmax.z + (-m1.z + 1);
-                                                       tracebox(ladder_bottom, m1, m2, ladder_top, movemode, e);
-                                                       if (trace_fraction < 1 || trace_startsolid)
-                                                       {
-                                                               if(autocvar_bot_debug_tracewalk)
-                                                                       debugnodestatus(trace_endpos, DEBUG_NODE_FAIL);
-
-                                                               return false; // failed
-                                                       }
-                                                       org = ladder_top + dir * m2.x;
-                                                       move = org + dir * stepdist;
-                                                       continue;
-                                               }
                                                else
                                                {
                                                        if(autocvar_bot_debug_tracewalk)
@@ -257,16 +247,6 @@ bool tracewalk(entity e, vector start, vector m1, vector m2, vector end, float m
 
                        org = trace_endpos;
                }
-
-               if(tw_ladder && org.z < tw_ladder.absmax.z)
-               {
-                       // stop tracewalk if destination height is lower than the top of the ladder
-                       // otherwise bot can't easily figure out climbing direction
-                       if(autocvar_bot_debug_tracewalk)
-                               debugnodestatus(org, DEBUG_NODE_FAIL);
-
-                       return false;
-               }
        }
 
        //print("tracewalk: ", vtos(start), " did not arrive at ", vtos(end), " but at ", vtos(org), "\n");
index a98a04a376a77385f5df2acb5109f125d0e95fbb..865cd2160672ff3fb3714d3add64e0595fef62f8 100644 (file)
@@ -968,11 +968,11 @@ void waypoint_spawnforitem(entity e)
        waypoint_spawnforitem_force(e, e.origin);
 }
 
-void waypoint_spawnforteleporter_boxes(entity e, vector org1, vector org2, vector destination1, vector destination2, float timetaken)
+void waypoint_spawnforteleporter_boxes(entity e, int teleport_flag, vector org1, vector org2, vector destination1, vector destination2, float timetaken)
 {
        entity w;
        entity dw;
-       w = waypoint_spawn(org1, org2, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_NORELINK);
+       w = waypoint_spawn(org1, org2, WAYPOINTFLAG_GENERATED | teleport_flag | WAYPOINTFLAG_NORELINK);
        dw = waypoint_spawn(destination1, destination2, WAYPOINTFLAG_GENERATED);
        // one way link to the destination
        w.wp00 = dw;
@@ -987,13 +987,13 @@ void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, flo
 {
        org = waypoint_fixorigin(org);
        destination = waypoint_fixorigin(destination);
-       waypoint_spawnforteleporter_boxes(e, org, org, destination, destination, timetaken);
+       waypoint_spawnforteleporter_boxes(e, WAYPOINTFLAG_TELEPORT, org, org, destination, destination, timetaken);
 }
 
 void waypoint_spawnforteleporter(entity e, vector destination, float timetaken)
 {
        destination = waypoint_fixorigin(destination);
-       waypoint_spawnforteleporter_boxes(e, e.absmin, e.absmax, destination, destination, timetaken);
+       waypoint_spawnforteleporter_boxes(e, WAYPOINTFLAG_TELEPORT, e.absmin, e.absmax, destination, destination, timetaken);
 }
 
 entity waypoint_spawnpersonal(entity this, vector position)
@@ -1275,6 +1275,8 @@ void botframe_deleteuselesswaypoints()
                        it.wpflags |= WAYPOINTFLAG_USEFUL;
                if (it.wpflags & WAYPOINTFLAG_TELEPORT)
                        it.wpflags |= WAYPOINTFLAG_USEFUL;
+               if (it.wpflags & WAYPOINTFLAG_LADDER)
+                       it.wpflags |= WAYPOINTFLAG_USEFUL;
                if (it.wpflags & WAYPOINTFLAG_PROTECTED)
                        it.wpflags |= WAYPOINTFLAG_USEFUL;
                // b) WP is closest WP for an item/spawnpoint/other entity