]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/default/waypoints.qc
Merge branch 'master' into terencehill/bot_waypoints
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / default / waypoints.qc
index e545c6c85f8a450855ead5f5675aba6066390237..f08c32691683d03c8c8f4696153001683c8d6475 100644 (file)
@@ -24,7 +24,14 @@ void waypoint_unreachable(entity pl)
                it.colormod = '0.5 0.5 0.5';
                it.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE);
        });
+
        entity e2 = navigation_findnearestwaypoint(pl, false);
+       if(!e2)
+       {
+               LOG_INFOF("Can't find any waypoint nearby\n");
+               return;
+       }
+
        navigation_markroutes(pl, e2);
 
        int j = 0;
@@ -161,6 +168,8 @@ void waypoint_setupmodel(entity wp)
                        wp.colormod = '1 0 0';
                else if (wp.wpflags & WAYPOINTFLAG_GENERATED)
                        wp.colormod = '1 1 0';
+               else if (wp.wphardwired)
+                       wp.colormod = '0.5 0 1';
                else
                        wp.colormod = '1 1 1';
        }
@@ -175,9 +184,8 @@ entity waypoint_spawn(vector m1, vector m2, float f)
 {
        if(!(f & WAYPOINTFLAG_PERSONAL))
        {
-               vector em1 = m1;
-               vector em2 = m2;
-               if (m1 == m2)
+               vector em1 = m1, em2 = m2;
+               if (!(f & WAYPOINTFLAG_GENERATED) && m1 == m2)
                {
                        em1 = m1 - '8 8 8';
                        em2 = m2 + '8 8 8';
@@ -261,7 +269,7 @@ void waypoint_spawn_fromeditor(entity pl)
        LABEL(add_wp);
        e = waypoint_spawn(org, org, 0);
        waypoint_schedulerelink(e);
-       bprint(strcat("Waypoint spawned at ", vtos(org), "\n"));
+       bprint(strcat("Waypoint spawned at ", vtos(e.origin), "\n"));
        if(sym)
        {
                org = waypoint_getSymmetricalOrigin(e.origin, ctf_flags);
@@ -391,24 +399,78 @@ bool waypoint_islinked(entity from, entity to)
        return false;
 }
 
-float waypoint_getdistancecost_simple(float dist)
+void waypoint_updatecost_foralllinks()
+{
+       IL_EACH(g_waypoints, !(it.wpflags & WAYPOINTFLAG_TELEPORT),
+       {
+               if(it.wp00) it.wp00mincost = waypoint_getlinkcost(it, it.wp00);
+               if(it.wp01) it.wp01mincost = waypoint_getlinkcost(it, it.wp01);
+               if(it.wp02) it.wp02mincost = waypoint_getlinkcost(it, it.wp02);
+               if(it.wp03) it.wp03mincost = waypoint_getlinkcost(it, it.wp03);
+               if(it.wp04) it.wp04mincost = waypoint_getlinkcost(it, it.wp04);
+               if(it.wp05) it.wp05mincost = waypoint_getlinkcost(it, it.wp05);
+               if(it.wp06) it.wp06mincost = waypoint_getlinkcost(it, it.wp06);
+               if(it.wp07) it.wp07mincost = waypoint_getlinkcost(it, it.wp07);
+               if(it.wp08) it.wp08mincost = waypoint_getlinkcost(it, it.wp08);
+               if(it.wp09) it.wp09mincost = waypoint_getlinkcost(it, it.wp09);
+               if(it.wp10) it.wp10mincost = waypoint_getlinkcost(it, it.wp10);
+               if(it.wp11) it.wp11mincost = waypoint_getlinkcost(it, it.wp11);
+               if(it.wp12) it.wp12mincost = waypoint_getlinkcost(it, it.wp12);
+               if(it.wp13) it.wp13mincost = waypoint_getlinkcost(it, it.wp13);
+               if(it.wp14) it.wp14mincost = waypoint_getlinkcost(it, it.wp14);
+               if(it.wp15) it.wp15mincost = waypoint_getlinkcost(it, it.wp15);
+               if(it.wp16) it.wp16mincost = waypoint_getlinkcost(it, it.wp16);
+               if(it.wp17) it.wp17mincost = waypoint_getlinkcost(it, it.wp17);
+               if(it.wp18) it.wp18mincost = waypoint_getlinkcost(it, it.wp18);
+               if(it.wp19) it.wp19mincost = waypoint_getlinkcost(it, it.wp19);
+               if(it.wp20) it.wp20mincost = waypoint_getlinkcost(it, it.wp20);
+               if(it.wp21) it.wp21mincost = waypoint_getlinkcost(it, it.wp21);
+               if(it.wp22) it.wp22mincost = waypoint_getlinkcost(it, it.wp22);
+               if(it.wp23) it.wp23mincost = waypoint_getlinkcost(it, it.wp23);
+               if(it.wp24) it.wp24mincost = waypoint_getlinkcost(it, it.wp24);
+               if(it.wp25) it.wp25mincost = waypoint_getlinkcost(it, it.wp25);
+               if(it.wp26) it.wp26mincost = waypoint_getlinkcost(it, it.wp26);
+               if(it.wp27) it.wp27mincost = waypoint_getlinkcost(it, it.wp27);
+               if(it.wp28) it.wp28mincost = waypoint_getlinkcost(it, it.wp28);
+               if(it.wp29) it.wp29mincost = waypoint_getlinkcost(it, it.wp29);
+               if(it.wp30) it.wp30mincost = waypoint_getlinkcost(it, it.wp30);
+               if(it.wp31) it.wp31mincost = waypoint_getlinkcost(it, it.wp31);
+       });
+}
+
+float waypoint_getlinearcost(float dist)
 {
+       if(skill >= autocvar_bot_ai_bunnyhop_skilloffset)
+               return dist / (autocvar_sv_maxspeed * 1.25);
        return dist / autocvar_sv_maxspeed;
 }
+float waypoint_getlinearcost_underwater(float dist)
+{
+       // NOTE: this value is hardcoded on the engine too, see SV_WaterMove
+       return dist / (autocvar_sv_maxspeed * 0.7);
+}
 
-float waypoint_getdistancecost(vector from, vector to)
+float waypoint_gettravelcost(vector from, vector to, entity from_ent, entity to_ent)
 {
-       float c = waypoint_getdistancecost_simple(vlen(to - from));
+       bool submerged_from = navigation_check_submerged_state(from_ent, from);
+       bool submerged_to = navigation_check_submerged_state(to_ent, to);
+
+       if (submerged_from && submerged_to)
+               return waypoint_getlinearcost_underwater(vlen(to - from));
+
+       float c = waypoint_getlinearcost(vlen(to - from));
 
        float height = from.z - to.z;
-       if(height > 0 && autocvar_sv_gravity > 0)
+       if(height > jumpheight_vec.z && autocvar_sv_gravity > 0)
        {
                float height_cost = sqrt(height / (autocvar_sv_gravity / 2));
-               float xydist = vlen(vec2(to - from));
-               float xydist_cost = xydist / autocvar_sv_maxspeed;
-               if(max(height_cost, xydist_cost) < c)
-                       c = max(height_cost, xydist_cost);
+               c = waypoint_getlinearcost(vlen(vec2(to - from))); // xy distance cost
+               if(height_cost > c)
+                       c = height_cost;
        }
+
+       if (submerged_from || submerged_to)
+               return (c + waypoint_getlinearcost_underwater(vlen(to - from))) / 2;
        return c;
 }
 
@@ -418,19 +480,19 @@ float waypoint_getlinkcost(entity from, entity to)
        vector v2 = to.origin;
        if (from.wpisbox)
        {
-               vector m1 = to.absmin, m2 = to.absmax;
-               v1_x = bound(m1_x, v1_x, m2_x);
-               v1_y = bound(m1_y, v1_y, m2_y);
-               v1_z = bound(m1_z, v1_z, m2_z);
+               vector m1 = from.absmin, m2 = from.absmax;
+               v1.x = bound(m1.x, v2.x, m2.x);
+               v1.y = bound(m1.y, v2.y, m2.y);
+               v1.z = bound(m1.z, v2.z, m2.z);
        }
        if (to.wpisbox)
        {
-               vector m1 = from.absmin, m2 = from.absmax;
-               v2_x = bound(m1_x, v2_x, m2_x);
-               v2_y = bound(m1_y, v2_y, m2_y);
-               v2_z = bound(m1_z, v2_z, m2_z);
+               vector m1 = to.absmin, m2 = to.absmax;
+               v2.x = bound(m1.x, v1.x, m2.x);
+               v2.y = bound(m1.y, v1.y, m2.y);
+               v2.z = bound(m1.z, v1.z, m2.z);
        }
-       return waypoint_getdistancecost(v1, v2);
+       return waypoint_gettravelcost(v1, v2, from, to);
 }
 
 // add a new link to the spawnfunc_waypoint, replacing the furthest link it already has
@@ -490,15 +552,14 @@ void waypoint_addlink(entity from, entity to)
 // (SLOW!)
 void waypoint_think(entity this)
 {
-       vector sv, sm1, sm2, ev, em1, em2, dv;
+       vector sv, sv2, ev, ev2, dv;
+       float sv2_height, ev2_height;
 
        bot_calculate_stepheightvec();
 
        bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL);
 
        //dprint("waypoint_think wpisbox = ", ftos(this.wpisbox), "\n");
-       sm1 = this.origin + this.mins;
-       sm2 = this.origin + this.maxs;
        IL_EACH(g_waypoints, this != it,
        {
                if (boxesoverlap(this.absmin, this.absmax, it.absmin, it.absmax))
@@ -514,16 +575,10 @@ void waypoint_think(entity this)
                                ++relink_pvsculled;
                                continue;
                        }
-                       sv = it.origin;
-                       sv.x = bound(sm1_x, sv.x, sm2_x);
-                       sv.y = bound(sm1_y, sv.y, sm2_y);
-                       sv.z = bound(sm1_z, sv.z, sm2_z);
-                       ev = this.origin;
-                       em1 = it.origin + it.mins;
-                       em2 = it.origin + it.maxs;
-                       ev.x = bound(em1_x, ev.x, em2_x);
-                       ev.y = bound(em1_y, ev.y, em2_y);
-                       ev.z = bound(em1_z, ev.z, em2_z);
+
+                       SET_TRACEWALK_DESTCOORDS_2(this, it.origin, sv, sv2, sv2_height);
+                       SET_TRACEWALK_DESTCOORDS_2(it, this.origin, ev, ev2, ev2_height);
+
                        dv = ev - sv;
                        dv.z = 0;
                        if(vdist(dv, >=, 1050)) // max search distance in XY
@@ -531,35 +586,30 @@ void waypoint_think(entity this)
                                ++relink_lengthculled;
                                continue;
                        }
+
                        navigation_testtracewalk = 0;
-                       if (!this.wpisbox)
-                       {
-                               tracebox(sv - PL_MIN_CONST.z * '0 0 1', PL_MIN_CONST, PL_MAX_CONST, sv, false, this);
-                               if (!trace_startsolid)
-                               {
-                                       //dprint("sv deviation", vtos(trace_endpos - sv), "\n");
-                                       sv = trace_endpos + '0 0 1';
-                               }
-                       }
-                       if (!it.wpisbox)
-                       {
-                               tracebox(ev - PL_MIN_CONST.z * '0 0 1', PL_MIN_CONST, PL_MAX_CONST, ev, false, it);
-                               if (!trace_startsolid)
-                               {
-                                       //dprint("ev deviation", vtos(trace_endpos - ev), "\n");
-                                       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
+                       {
+                               if (tracewalk(this, sv, PL_MIN_CONST, PL_MAX_CONST, ev2, ev2_height, MOVE_NOMONSTERS))
+                                       waypoint_addlink(this, it);
+                               else
+                                       relink_walkculled += 0.5;
+                       }
+
+                       if (it.wpisbox)
                                relink_walkculled += 0.5;
+                       else
+                       {
+                               if (tracewalk(it, ev, PL_MIN_CONST, PL_MAX_CONST, sv2, sv2_height, MOVE_NOMONSTERS))
+                                       waypoint_addlink(it, this);
+                               else
+                                       relink_walkculled += 0.5;
+                       }
                }
        });
        navigation_testtracewalk = 0;
@@ -1039,7 +1089,7 @@ void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, flo
 void waypoint_spawnforteleporter(entity e, vector destination, float timetaken)
 {
        destination = waypoint_fixorigin(destination);
-       waypoint_spawnforteleporter_boxes(e, WAYPOINTFLAG_TELEPORT, e.absmin, e.absmax, destination, destination, timetaken);
+       waypoint_spawnforteleporter_boxes(e, WAYPOINTFLAG_TELEPORT, e.absmin - PL_MAX_CONST + '1 1 1', e.absmax - PL_MIN_CONST + '-1 -1 -1', destination, destination, timetaken);
 }
 
 entity waypoint_spawnpersonal(entity this, vector position)
@@ -1178,7 +1228,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
 
                // if wp -> porg, then OK
                float maxdist;
-               if(navigation_waypoint_will_link(wp.origin, porg, p, walkfromwp, 1050))
+               if(navigation_waypoint_will_link(wp.origin, porg, p, wp.origin, 0, walkfromwp, 1050))
                {
                        // we may find a better one
                        maxdist = vlen(wp.origin - porg);
@@ -1194,8 +1244,8 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
                {
                        float d = vlen(wp.origin - it.origin) + vlen(it.origin - porg);
                        if(d < bestdist)
-                       if(navigation_waypoint_will_link(wp.origin, it.origin, p, walkfromwp, 1050))
-                       if(navigation_waypoint_will_link(it.origin, porg, p, walkfromwp, 1050))
+                       if(navigation_waypoint_will_link(wp.origin, it.origin, p, wp.origin, 0, walkfromwp, 1050))
+                       if(navigation_waypoint_will_link(it.origin, porg, p, it.origin, 0, walkfromwp, 1050))
                        {
                                bestdist = d;
                                p.(fld) = it;
@@ -1249,7 +1299,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
 
                if(wp)
                {
-                       if(!navigation_waypoint_will_link(wp.origin, o, p, walkfromwp, 1050))
+                       if(!navigation_waypoint_will_link(wp.origin, o, p, wp.origin, 0, walkfromwp, 1050))
                        {
                                // we cannot walk from wp.origin to o
                                // get closer to tmax
@@ -1275,7 +1325,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en
                // if we get here, o is valid regarding waypoints
                // check if o is connected right to the player
                // we break if it succeeds, as that means o is a good waypoint location
-               if(navigation_waypoint_will_link(o, porg, p, walkfromwp, 1050))
+               if(navigation_waypoint_will_link(o, porg, p, o, 0, walkfromwp, 1050))
                        break;
 
                // o is no good, we need to get closer to the player