]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/default/waypoints.qc
Minor cleanups
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / default / waypoints.qc
index fa82d926b63e92776cfd293dbebccf15ba20ad04..c8e723260078ef33aab9cd3e818286c5a1048f36 100644 (file)
@@ -128,7 +128,7 @@ void waypoint_unreachable(entity pl)
        if (j) LOG_INFOF("%d items have no nearest waypoint and cannot be walked to (marked with blue light)\n", j);
 }
 
-vector waypoint_getSymmetricalOrigin(vector org, int ctf_flags)
+vector waypoint_getSymmetricalPoint(vector org, int ctf_flags)
 {
        vector new_org = org;
        if (fabs(autocvar_g_waypointeditor_symmetrical) == 1)
@@ -141,8 +141,8 @@ vector waypoint_getSymmetricalOrigin(vector org, int ctf_flags)
        }
        else if (fabs(autocvar_g_waypointeditor_symmetrical) == 2)
        {
-               float m = havocbot_symmetryaxis_equation.x;
-               float q = havocbot_symmetryaxis_equation.y;
+               float m = havocbot_symmetry_axis_m;
+               float q = havocbot_symmetry_axis_q;
                if (autocvar_g_waypointeditor_symmetrical == -2)
                {
                        m = autocvar_g_waypointeditor_symmetrical_axis.x;
@@ -190,6 +190,16 @@ entity waypoint_spawn(vector m1, vector m2, float f)
                        return it;
                });
        }
+       // spawn only one destination waypoint for teleports teleporting player to the exact same spot
+       // otherwise links loaded from file would be applied only to the first destination
+       // waypoint since link format doesn't specify waypoint entities but just positions
+       if((f & WAYPOINTFLAG_GENERATED) && !(f & WAYPOINTFLAG_NORELINK) && m1 == m2)
+       {
+               IL_EACH(g_waypoints, boxesoverlap(m1, m2, it.absmin, it.absmax),
+               {
+                       return it;
+               });
+       }
 
        entity w = new(waypoint);
        IL_PUSH(g_waypoints, w);
@@ -236,15 +246,14 @@ void waypoint_spawn_fromeditor(entity pl)
 {
        entity e;
        vector org = pl.origin;
-       int ctf_flags = havocbot_symmetryaxis_equation.z;
+       int ctf_flags = havocbot_symmetry_origin_order;
        bool sym = ((autocvar_g_waypointeditor_symmetrical > 0 && ctf_flags >= 2)
                   || (autocvar_g_waypointeditor_symmetrical < 0));
-       int order = ctf_flags;
        if(autocvar_g_waypointeditor_symmetrical_order >= 2)
-       {
-               order = autocvar_g_waypointeditor_symmetrical_order;
-               ctf_flags = order;
-       }
+               ctf_flags = autocvar_g_waypointeditor_symmetrical_order;
+       if (sym && ctf_flags < 2)
+               ctf_flags = 2;
+       int wp_num = ctf_flags;
 
        if(!PHYS_INPUT_BUTTON_CROUCH(pl))
        {
@@ -253,7 +262,7 @@ void waypoint_spawn_fromeditor(entity pl)
                {
                        vector item_org = (it.absmin + it.absmax) * 0.5;
                        item_org.z = it.absmin.z - PL_MIN_CONST.z;
-                       if(vlen(item_org - org) < 30)
+                       if (vlen(item_org - org) < 20)
                        {
                                org = item_org;
                                break;
@@ -272,11 +281,11 @@ void waypoint_spawn_fromeditor(entity pl)
        bprint(strcat("Waypoint spawned at ", vtos(e.origin), "\n"));
        if(sym)
        {
-               org = waypoint_getSymmetricalOrigin(e.origin, ctf_flags);
+               org = waypoint_getSymmetricalPoint(e.origin, ctf_flags);
                if (vdist(org - pl.origin, >, 32))
                {
-                       if(order > 2)
-                               order--;
+                       if(wp_num > 2)
+                               wp_num--;
                        else
                                sym = false;
                        goto add_wp;
@@ -286,7 +295,6 @@ void waypoint_spawn_fromeditor(entity pl)
 
 void waypoint_remove(entity wp)
 {
-       // tell all waypoints linked to wp that they need to relink
        IL_EACH(g_waypoints, it != wp,
        {
                if (waypoint_islinked(it, wp))
@@ -299,15 +307,14 @@ void waypoint_remove_fromeditor(entity pl)
 {
        entity e = navigation_findnearestwaypoint(pl, false);
 
-       int ctf_flags = havocbot_symmetryaxis_equation.z;
+       int ctf_flags = havocbot_symmetry_origin_order;
        bool sym = ((autocvar_g_waypointeditor_symmetrical > 0 && ctf_flags >= 2)
                   || (autocvar_g_waypointeditor_symmetrical < 0));
-       int order = ctf_flags;
        if(autocvar_g_waypointeditor_symmetrical_order >= 2)
-       {
-               order = autocvar_g_waypointeditor_symmetrical_order;
-               ctf_flags = order;
-       }
+               ctf_flags = autocvar_g_waypointeditor_symmetrical_order;
+       if (sym && ctf_flags < 2)
+               ctf_flags = 2;
+       int wp_num = ctf_flags;
 
        LABEL(remove_wp);
        if (!e) return;
@@ -322,7 +329,7 @@ void waypoint_remove_fromeditor(entity pl)
        entity wp_sym = NULL;
        if (sym)
        {
-               vector org = waypoint_getSymmetricalOrigin(e.origin, ctf_flags);
+               vector org = waypoint_getSymmetricalPoint(e.origin, ctf_flags);
                FOREACH_ENTITY_CLASS("waypoint", !(it.wpflags & WAYPOINTFLAG_GENERATED), {
                        if(vdist(org - it.origin, <, 3))
                        {
@@ -338,8 +345,8 @@ void waypoint_remove_fromeditor(entity pl)
        if (sym && wp_sym)
        {
                e = wp_sym;
-               if(order > 2)
-                       order--;
+               if(wp_num > 2)
+                       wp_num--;
                else
                        sym = false;
                goto remove_wp;
@@ -446,7 +453,7 @@ float waypoint_getlinearcost(float dist)
 }
 float waypoint_getlinearcost_underwater(float dist)
 {
-       // NOTE: this value is hardcoded on the engine too, see SV_WaterMove
+       // NOTE: underwater speed factor is hardcoded in the engine too, see SV_WaterMove
        return dist / (autocvar_sv_maxspeed * 0.7);
 }
 
@@ -557,6 +564,9 @@ void waypoint_think(entity this)
 
        bot_calculate_stepheightvec();
 
+       int dphitcontentsmask_save = this.dphitcontentsmask;
+       this.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
+
        bot_navigation_movemode = ((autocvar_bot_navigation_ignoreplayers) ? MOVE_NOMONSTERS : MOVE_NORMAL);
 
        //dprint("waypoint_think wpisbox = ", ftos(this.wpisbox), "\n");
@@ -609,7 +619,7 @@ void waypoint_think(entity this)
                                relink_walkculled += 0.5;
                        else
                        {
-                               if (tracewalk(it, ev, PL_MIN_CONST, PL_MAX_CONST, sv2, sv2_height, MOVE_NOMONSTERS))
+                               if (tracewalk(this, ev, PL_MIN_CONST, PL_MAX_CONST, sv2, sv2_height, MOVE_NOMONSTERS))
                                        waypoint_addlink(it, this);
                                else
                                        relink_walkculled += 0.5;
@@ -618,6 +628,7 @@ void waypoint_think(entity this)
        });
        navigation_testtracewalk = 0;
        this.wplinked = true;
+       this.dphitcontentsmask = dphitcontentsmask_save;
 }
 
 void waypoint_clearlinks(entity wp)
@@ -710,6 +721,7 @@ bool waypoint_load_links()
 
        bool parse_comments = true;
        float ver = 0;
+       string links_time = string_null;
 
        while ((s = fgets(file)))
        {
@@ -719,13 +731,18 @@ bool waypoint_load_links()
                        {
                                if(substring(s, 2, 17) == "WAYPOINT_VERSION ")
                                        ver = stof(substring(s, 19, -1));
+                               else if(substring(s, 2, 14) == "WAYPOINT_TIME ")
+                                       links_time = substring(s, 16, -1);
                                continue;
                        }
                        else
                        {
-                               if(ver < WAYPOINT_VERSION)
+                               if(ver < WAYPOINT_VERSION || links_time != waypoint_time)
                                {
-                                       LOG_TRACE("waypoint links for this map are outdated.");
+                                       if (links_time != waypoint_time)
+                                               LOG_TRACE("waypoint links for this map are not made for these waypoints.");
+                                       else
+                                               LOG_TRACE("waypoint links for this map are outdated.");
                                        if (g_assault)
                                        {
                                                LOG_TRACE("Assault waypoint links need to be manually updated in the editor");
@@ -988,6 +1005,8 @@ void waypoint_save_links()
        }
 
        fputs(file, strcat("//", "WAYPOINT_VERSION ", ftos_decimals(WAYPOINT_VERSION, 2), "\n"));
+       if (waypoint_time != "")
+               fputs(file, strcat("//", "WAYPOINT_TIME ", waypoint_time, "\n"));
 
        int c = 0;
        IL_EACH(g_waypoints, true,
@@ -997,6 +1016,7 @@ void waypoint_save_links()
                        entity link = waypoint_get_link(it, j);
                        if(link)
                        {
+                               // NOTE: vtos rounds vector components to 1 decimal place
                                string s = strcat(vtos(it.origin), "*", vtos(link.origin), "\n");
                                fputs(file, s);
                                ++c;
@@ -1028,11 +1048,39 @@ void waypoint_saveall()
                return;
        }
 
-       // add 3 comments to not break compatibility with older Xonotic versions
+       float sym = autocvar_g_waypointeditor_symmetrical;
+       string sym_str = ftos(sym);
+       if (sym == -1 || (sym == 1 && autocvar_g_waypointeditor_symmetrical_order >= 2))
+       {
+               if (sym == 1)
+               {
+                       sym_str = cons(sym_str, "-");
+                       sym_str = cons(sym_str, "-");
+               }
+               else
+               {
+                       sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_origin.x));
+                       sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_origin.y));
+               }
+               if (autocvar_g_waypointeditor_symmetrical_order >= 2)
+                       sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_order));
+       }
+       else if (autocvar_g_waypointeditor_symmetrical == -2)
+       {
+               sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_axis.x));
+               sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_axis.y));
+       }
+
+       // a group of 3 comments doesn't break compatibility with older Xonotic versions
        // (they are read as a waypoint with origin '0 0 0' and flag 0 though)
        fputs(file, strcat("//", "WAYPOINT_VERSION ", ftos_decimals(WAYPOINT_VERSION, 2), "\n"));
-       fputs(file, strcat("//", "\n"));
-       fputs(file, strcat("//", "\n"));
+       fputs(file, strcat("//", "WAYPOINT_SYMMETRY ", sym_str, "\n"));
+
+       strcpy(waypoint_time, strftime(true, "%Y-%m-%d %H:%M:%S"));
+       fputs(file, strcat("//", "WAYPOINT_TIME ", waypoint_time, "\n"));
+       //fputs(file, strcat("//", "\n"));
+       //fputs(file, strcat("//", "\n"));
+       //fputs(file, strcat("//", "\n"));
 
        int c = 0;
        IL_EACH(g_waypoints, true,
@@ -1041,6 +1089,7 @@ void waypoint_saveall()
                        continue;
 
                string s;
+               // NOTE: vtos rounds vector components to 1 decimal place
                s = strcat(vtos(it.origin + it.mins), "\n");
                s = strcat(s, vtos(it.origin + it.maxs));
                s = strcat(s, "\n");
@@ -1085,6 +1134,8 @@ float waypoint_loadall()
 
        bool parse_comments = true;
        float ver = 0;
+       float sym = 0;
+       float sym_param1 = 0, sym_param2 = 0, sym_param3 = 0;
 
        while ((s = fgets(file)))
        {
@@ -1094,6 +1145,16 @@ float waypoint_loadall()
                        {
                                if(substring(s, 2, 17) == "WAYPOINT_VERSION ")
                                        ver = stof(substring(s, 19, -1));
+                               else if(substring(s, 2, 18) == "WAYPOINT_SYMMETRY ")
+                               {
+                                       int tokens = tokenizebyseparator(substring(s, 20, -1), " ");
+                                       if (tokens) { sym = stof(argv(0)); }
+                                       if (tokens > 1) { sym_param1 = stof(argv(1)); }
+                                       if (tokens > 2) { sym_param2 = stof(argv(2)); }
+                                       if (tokens > 3) { sym_param3 = stof(argv(3)); }
+                               }
+                               else if(substring(s, 2, 14) == "WAYPOINT_TIME ")
+                                       strcpy(waypoint_time, substring(s, 16, -1));
                                continue;
                        }
                        else
@@ -1124,6 +1185,35 @@ float waypoint_loadall()
        fclose(file);
        LOG_TRACE("loaded ", ftos(cwp), " waypoints and ", ftos(cwb), " wayboxes from maps/", mapname, ".waypoints");
 
+       if (autocvar_g_waypointeditor && autocvar_g_waypointeditor_symmetrical_allowload)
+       {
+               cvar_set("g_waypointeditor_symmetrical", ftos(sym));
+               if (sym == 1 && sym_param3 < 2)
+                       cvar_set("g_waypointeditor_symmetrical_order", "0"); // make sure this is reset if not loaded
+               if (sym == -1 || (sym == 1 && sym_param3 >= 2))
+               {
+                       string params;
+                       if (sym == 1)
+                               params = cons("-", "-");
+                       else
+                       {
+                               params = cons(ftos(sym_param1), ftos(sym_param2));
+                               cvar_set("g_waypointeditor_symmetrical_origin", params);
+                       }
+                       cvar_set("g_waypointeditor_symmetrical_order", ftos(sym_param3));
+                       LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym), " with origin ", params, " and order ", ftos(sym_param3));
+               }
+               else if (sym == -2)
+               {
+                       string params = strcat(ftos(sym_param1), " ", ftos(sym_param2));
+                       cvar_set("g_waypointeditor_symmetrical_axis", params);
+                       LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym), " with axis ", params);
+               }
+               else
+                       LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym));
+               LOG_INFO(strcat("g_waypointeditor_symmetrical", " has been set to ", cvar_string("g_waypointeditor_symmetrical")));
+       }
+
        return cwp + cwb;
 }
 
@@ -1132,11 +1222,12 @@ float waypoint_loadall()
 
 vector waypoint_fixorigin_down_dir(vector position, entity tracetest_ent, vector down_dir)
 {
-       tracebox(position + '0 0 1', PL_MIN_CONST, PL_MAX_CONST, position + down_dir * 3000, MOVE_NOMONSTERS, tracetest_ent);
+       vector endpos = position + down_dir * 3000;
+       tracebox(position + '0 0 1', PL_MIN_CONST, PL_MAX_CONST, endpos, MOVE_NOMONSTERS, tracetest_ent);
        if(trace_startsolid)
-               tracebox(position + '0 0 1' * (1 - PL_MIN_CONST.z / 2), PL_MIN_CONST, PL_MAX_CONST, position + down_dir * 3000, MOVE_NOMONSTERS, tracetest_ent);
+               tracebox(position + '0 0 1' * (1 - PL_MIN_CONST.z / 2), PL_MIN_CONST, PL_MAX_CONST, endpos, MOVE_NOMONSTERS, tracetest_ent);
        if(trace_startsolid)
-               tracebox(position + '0 0 1' * (1 - PL_MIN_CONST.z), PL_MIN_CONST, PL_MAX_CONST, position + down_dir * 3000, MOVE_NOMONSTERS, tracetest_ent);
+               tracebox(position + '0 0 1' * (1 - PL_MIN_CONST.z), PL_MIN_CONST, PL_MAX_CONST, endpos, MOVE_NOMONSTERS, tracetest_ent);
        if(trace_fraction < 1)
                position = trace_endpos;
        return position;
@@ -1283,6 +1374,8 @@ void botframe_showwaypointlinks()
        {
                int display_type = 0;
                entity head = navigation_findnearestwaypoint(it, false);
+               it.nearestwaypoint = head; // mainly useful for debug
+               it.nearestwaypointtimeout = time + 2; // while I'm at it...
                if (IS_ONGROUND(it) || it.waterlevel > WATERLEVEL_NONE)
                        display_type = 1; // default
                else if(head && (head.wphardwired))