X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fbot%2Fdefault%2Fwaypoints.qc;h=384f1e7ce1c87ddebc1d048a8838d69181f051a6;hb=3cfa3eaf6856fe76f7fd8c945fbfab2e9e28014c;hp=74df45583fededaf0afc2969eff412d647f2bd08;hpb=9ab463ad54b6f121536bc399e68c43b419fb82b0;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/bot/default/waypoints.qc b/qcsrc/server/bot/default/waypoints.qc index 74df45583..384f1e7ce 100644 --- a/qcsrc/server/bot/default/waypoints.qc +++ b/qcsrc/server/bot/default/waypoints.qc @@ -1,5 +1,7 @@ #include "waypoints.qh" +#include +#include #include "cvars.qh" #include "bot.qh" @@ -177,19 +179,12 @@ void waypoint_setupmodel(entity wp) wp.model = ""; } -// create a new spawnfunc_waypoint and automatically link it to other waypoints, and link -// them back to it as well -// (suitable for spawnfunc_waypoint editor) entity waypoint_spawn(vector m1, vector m2, float f) { - if(!(f & WAYPOINTFLAG_PERSONAL)) + if(!(f & (WAYPOINTFLAG_PERSONAL | WAYPOINTFLAG_GENERATED)) && m1 == m2) { - vector em1 = m1, em2 = m2; - if (!(f & WAYPOINTFLAG_GENERATED) && m1 == m2) - { - em1 = m1 - '8 8 8'; - em2 = m2 + '8 8 8'; - } + vector em1 = m1 - '8 8 8'; + vector em2 = m2 + '8 8 8'; IL_EACH(g_waypoints, boxesoverlap(em1, em2, it.absmin, it.absmax), { return it; @@ -221,7 +216,7 @@ entity waypoint_spawn(vector m1, vector m2, float f) { if(autocvar_developer) { - LOG_INFO("A generated waypoint is stuck in solid at ", vtos(w.origin), "\n"); + LOG_INFO("A generated waypoint is stuck in solid at ", vtos(w.origin)); backtrace("Waypoint stuck"); } } @@ -268,8 +263,13 @@ void waypoint_spawn_fromeditor(entity pl) LABEL(add_wp); e = waypoint_spawn(org, org, 0); + if(!e) + { + LOG_INFOF("Couldn't spawn waypoint at %v\n", org); + return; + } 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); @@ -444,9 +444,20 @@ float waypoint_getlinearcost(float dist) 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_gettravelcost(vector from, vector to) +float waypoint_gettravelcost(vector from, vector to, entity from_ent, entity to_ent) { + 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; @@ -457,6 +468,9 @@ float waypoint_gettravelcost(vector from, vector to) if(height_cost > c) c = height_cost; } + + if (submerged_from || submerged_to) + return (c + waypoint_getlinearcost_underwater(vlen(to - from))) / 2; return c; } @@ -466,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_gettravelcost(v1, v2); + return waypoint_gettravelcost(v1, v2, from, to); } // add a new link to the spawnfunc_waypoint, replacing the furthest link it already has @@ -538,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 = '0 0 0', sv2 = '0 0 0', ev = '0 0 0', ev2 = '0 0 0', dv; + float sv2_height = 0, ev2_height = 0; 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)) @@ -562,16 +575,14 @@ 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); + + sv = set_tracewalk_dest_2(this, it.origin); + sv2 = tracewalk_dest; + sv2_height = tracewalk_dest_height; + ev = set_tracewalk_dest_2(it, this.origin); + ev2 = tracewalk_dest; + ev2_height = tracewalk_dest_height; + dv = ev - sv; dv.z = 0; if(vdist(dv, >=, 1050)) // max search distance in XY @@ -579,39 +590,16 @@ void waypoint_think(entity this) ++relink_lengthculled; continue; } - float sv_deviation = 0; - float ev_deviation = 0; + 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_deviation = trace_endpos.z + 1 - sv.z; - 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_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) relink_walkculled += 0.5; 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)) + if (tracewalk(this, sv, PL_MIN_CONST, PL_MAX_CONST, ev2, ev2_height, MOVE_NOMONSTERS)) waypoint_addlink(this, it); else relink_walkculled += 0.5; @@ -621,10 +609,7 @@ void waypoint_think(entity this) 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)) + if (tracewalk(it, ev, PL_MIN_CONST, PL_MAX_CONST, sv2, sv2_height, MOVE_NOMONSTERS)) waypoint_addlink(it, this); else relink_walkculled += 0.5; @@ -694,33 +679,76 @@ void waypoint_schedulerelinkall() waypoint_load_links_hardwired(); } +#define GET_GAMETYPE_EXTENSION() ((g_race) ? ".race" : "") + // Load waypoint links from file bool waypoint_load_links() { - string filename, s; + string s; float file, tokens, c = 0, found; entity wp_from = NULL, wp_to; vector wp_to_pos, wp_from_pos; - filename = strcat("maps/", mapname); - filename = strcat(filename, ".waypoints.cache"); + + string gt_ext = GET_GAMETYPE_EXTENSION(); + + string filename = sprintf("maps/%s.waypoints.cache", strcat(mapname, gt_ext)); file = fopen(filename, FILE_READ); + if (gt_ext != "" && file < 0) + { + // if race waypoint file doesn't exist load the default one + filename = sprintf("maps/%s.waypoints.cache", mapname); + file = fopen(filename, FILE_READ); + } + if (file < 0) { - LOG_TRACE("waypoint links load from "); - LOG_TRACE(filename); - LOG_TRACE(" failed"); + LOG_TRACE("waypoint links load from ", filename, " failed"); + waypoint_schedulerelinkall(); return false; } + bool parse_comments = true; + float ver = 0; + while ((s = fgets(file))) { + if(parse_comments) + { + if(substring(s, 0, 2) == "//") + { + if(substring(s, 2, 17) == "WAYPOINT_VERSION ") + ver = stof(substring(s, 19, -1)); + continue; + } + else + { + if(ver < WAYPOINT_VERSION) + { + 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"); + } + else + { + LOG_TRACE("automatically updating..."); + waypoint_schedulerelinkall(); + fclose(file); + return false; + } + } + parse_comments = false; + } + } + tokens = tokenizebyseparator(s, "*"); if (tokens!=2) { // bad file format fclose(file); + waypoint_schedulerelinkall(); // link all the autogenerated waypoints (teleporters) return false; } @@ -748,7 +776,6 @@ bool waypoint_load_links() LOG_TRACE("waypoint_load_links: couldn't find 'from' waypoint at ", vtos(wp_from_pos)); continue; } - } // Search "to" waypoint @@ -777,7 +804,19 @@ bool waypoint_load_links() fclose(file); - LOG_TRACE("loaded ", ftos(c), " waypoint links from maps/", mapname, ".waypoints.cache"); + LOG_TRACE("loaded ", ftos(c), " waypoint links from ", filename); + + bool scheduled = false; + IL_EACH(g_waypoints, it.wpflags & WAYPOINTFLAG_ITEM, + { + if (!it.wp00) + { + waypoint_schedulerelink(it); + scheduled = true; + } + }); + if (scheduled) + return false; botframe_cachedwaypointlinks = true; return true; @@ -785,14 +824,23 @@ bool waypoint_load_links() void waypoint_load_or_remove_links_hardwired(bool removal_mode) { - string filename, s; + string s; float file, tokens, c = 0, found; entity wp_from = NULL, wp_to; vector wp_to_pos, wp_from_pos; - filename = strcat("maps/", mapname); - filename = strcat(filename, ".waypoints.hardwired"); + + string gt_ext = GET_GAMETYPE_EXTENSION(); + + string filename = sprintf("maps/%s.waypoints.hardwired", strcat(mapname, gt_ext)); file = fopen(filename, FILE_READ); + if (gt_ext != "" && file < 0) + { + // if race waypoint file doesn't exist load the default one + filename = sprintf("maps/%s.waypoints.hardwired", mapname); + file = fopen(filename, FILE_READ); + } + botframe_loadedforcedlinks = true; if (file < 0) @@ -837,7 +885,7 @@ void waypoint_load_or_remove_links_hardwired(bool removal_mode) if(!found) { if(!removal_mode) - LOG_INFO(strcat("NOTICE: Can not find waypoint at ", vtos(wp_from_pos), ". Path skipped\n")); + LOG_INFO("NOTICE: Can not find waypoint at ", vtos(wp_from_pos), ". Path skipped"); continue; } } @@ -859,7 +907,7 @@ void waypoint_load_or_remove_links_hardwired(bool removal_mode) if(!found) { if(!removal_mode) - LOG_INFO(strcat("NOTICE: Can not find waypoint at ", vtos(wp_to_pos), ". Path skipped\n")); + LOG_INFO("NOTICE: Can not find waypoint at ", vtos(wp_to_pos), ". Path skipped"); continue; } @@ -873,17 +921,16 @@ void waypoint_load_or_remove_links_hardwired(bool removal_mode) waypoint_addlink(wp_from, wp_to); wp_from.wphardwired = true; wp_to.wphardwired = true; + waypoint_setupmodel(wp_from); + waypoint_setupmodel(wp_to); } fclose(file); - if(!removal_mode) - LOG_TRACE("loaded ", ftos(c), " waypoint links from maps/", mapname, ".waypoints.hardwired"); + LOG_TRACE(((removal_mode) ? "unloaded " : "loaded "), + ftos(c), " waypoint links from maps/", mapname, ".waypoints.hardwired"); } -void waypoint_load_links_hardwired() { waypoint_load_or_remove_links_hardwired(false); } -void waypoint_remove_links_hardwired() { waypoint_load_or_remove_links_hardwired(true); } - entity waypoint_get_link(entity w, float i) { switch(i) @@ -930,14 +977,18 @@ void waypoint_save_links() // temporarily remove hardwired links so they don't get saved among normal links waypoint_remove_links_hardwired(); - string filename = sprintf("maps/%s.waypoints.cache", mapname); + string gt_ext = GET_GAMETYPE_EXTENSION(); + + string filename = sprintf("maps/%s.waypoints.cache", strcat(mapname, gt_ext)); int file = fopen(filename, FILE_WRITE); if (file < 0) { - LOG_INFOF("waypoint link save to %s failed\n", filename); + LOG_INFOF("waypoint link save to %s failed", filename); return; } + fputs(file, strcat("//", "WAYPOINT_VERSION ", ftos_decimals(WAYPOINT_VERSION, 2), "\n")); + int c = 0; IL_EACH(g_waypoints, true, { @@ -953,9 +1004,10 @@ void waypoint_save_links() } }); fclose(file); + botframe_cachedwaypointlinks = true; - LOG_INFOF("saved %d waypoint links to maps/%s.waypoints.cache\n", c, mapname); + LOG_INFOF("saved %d waypoint links to %s", c, filename); waypoint_load_links_hardwired(); } @@ -963,17 +1015,48 @@ void waypoint_save_links() // save waypoints to gamedir/data/maps/mapname.waypoints void waypoint_saveall() { - string filename = sprintf("maps/%s.waypoints", mapname); + string gt_ext = GET_GAMETYPE_EXTENSION(); + + string filename = sprintf("maps/%s.waypoints", strcat(mapname, gt_ext)); int file = fopen(filename, FILE_WRITE); if (file < 0) { waypoint_save_links(); // save anyway? botframe_loadedforcedlinks = false; - LOG_INFOF("waypoint links: save to %s failed\n", filename); + LOG_INFOF("waypoint links: save to %s failed", filename); return; } + 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("//", "WAYPOINT_SYMMETRY ", sym_str, "\n")); + fputs(file, strcat("//", "\n")); + int c = 0; IL_EACH(g_waypoints, true, { @@ -993,63 +1076,138 @@ void waypoint_saveall() waypoint_save_links(); botframe_loadedforcedlinks = false; - LOG_INFOF("saved %d waypoints to maps/%s.waypoints\n", c, mapname); + LOG_INFOF("saved %d waypoints to %s", c, filename); } // load waypoints from file float waypoint_loadall() { - string filename, s; + string s; float file, cwp, cwb, fl; vector m1, m2; cwp = 0; cwb = 0; - filename = strcat("maps/", mapname); - filename = strcat(filename, ".waypoints"); + + string gt_ext = GET_GAMETYPE_EXTENSION(); + + string filename = sprintf("maps/%s.waypoints", strcat(mapname, gt_ext)); file = fopen(filename, FILE_READ); - if (file >= 0) + + if (gt_ext != "" && file < 0) + { + // if race waypoint file doesn't exist load the default one + filename = sprintf("maps/%s.waypoints", mapname); + file = fopen(filename, FILE_READ); + } + + if (file < 0) + { + LOG_TRACE("waypoint load from ", filename, " failed"); + return 0; + } + + bool parse_comments = true; + float ver = 0; + float sym = 0; + float sym_param1 = 0, sym_param2 = 0, sym_param3 = 0; + + while ((s = fgets(file))) { - while ((s = fgets(file))) + if(parse_comments) { - m1 = stov(s); - s = fgets(file); - if (!s) - break; - m2 = stov(s); - s = fgets(file); - if (!s) - break; - fl = stof(s); - waypoint_spawn(m1, m2, fl); - if (m1 == m2) - cwp = cwp + 1; + if(substring(s, 0, 2) == "//") + { + 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)); } + } + continue; + } else - cwb = cwb + 1; + { + if(floor(ver) < floor(WAYPOINT_VERSION)) + { + LOG_TRACE("waypoints for this map are outdated"); + LOG_TRACE("please update them in the editor"); + } + parse_comments = false; + } } - fclose(file); - LOG_TRACE("loaded ", ftos(cwp), " waypoints and ", ftos(cwb), " wayboxes from maps/", mapname, ".waypoints"); + m1 = stov(s); + s = fgets(file); + if (!s) + break; + m2 = stov(s); + s = fgets(file); + if (!s) + break; + fl = stof(s); + waypoint_spawn(m1, m2, fl); + if (m1 == m2) + cwp = cwp + 1; + else + cwb = cwb + 1; } - else + 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) { - LOG_TRACE("waypoint load from ", filename, " failed"); + 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; } -vector waypoint_fixorigin(vector position) +#define waypoint_fixorigin(position, tracetest_ent) \ + waypoint_fixorigin_down_dir(position, tracetest_ent, '0 0 -1') + +vector waypoint_fixorigin_down_dir(vector position, entity tracetest_ent, vector down_dir) { - tracebox(position + '0 0 1' * (1 - PL_MIN_CONST.z), PL_MIN_CONST, PL_MAX_CONST, position + '0 0 -512', MOVE_NOMONSTERS, NULL); + tracebox(position + '0 0 1', PL_MIN_CONST, PL_MAX_CONST, position + down_dir * 3000, 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); + 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); if(trace_fraction < 1) position = trace_endpos; - //traceline(position, position + '0 0 -512', MOVE_NOMONSTERS, NULL); - //print("position is ", ftos(trace_endpos_z - position_z), " above solid\n"); return position; } void waypoint_spawnforitem_force(entity e, vector org) { // Fix the waypoint altitude if necessary - org = waypoint_fixorigin(org); + org = waypoint_fixorigin(org, NULL); // don't spawn an item spawnfunc_waypoint if it already exists IL_EACH(g_waypoints, true, @@ -1098,16 +1256,24 @@ void waypoint_spawnforteleporter_boxes(entity e, int teleport_flag, vector org1, e.nearestwaypointtimeout = -1; } -void waypoint_spawnforteleporter_v(entity e, vector org, vector destination, float timetaken) +void waypoint_spawnforteleporter_wz(entity e, vector org, vector destination, float timetaken, vector down_dir, entity tracetest_ent) { - org = waypoint_fixorigin(org); - destination = waypoint_fixorigin(destination); + // warpzones with oblique warp plane rely on down_dir to snap waypoints + // to the ground without leaving the warp plane + // warpzones with horizontal warp plane (down_dir.x == -1) generate + // destination waypoint snapped to the ground (leaving warpzone), source + // waypoint in the center of the warp plane + if(down_dir.x != -1) + org = waypoint_fixorigin_down_dir(org, tracetest_ent, down_dir); + if(down_dir.x == -1) + down_dir = '0 0 -1'; + destination = waypoint_fixorigin_down_dir(destination, tracetest_ent, down_dir); waypoint_spawnforteleporter_boxes(e, WAYPOINTFLAG_TELEPORT, org, org, destination, destination, timetaken); } -void waypoint_spawnforteleporter(entity e, vector destination, float timetaken) +void waypoint_spawnforteleporter(entity e, vector destination, float timetaken, entity tracetest_ent) { - destination = waypoint_fixorigin(destination); + destination = waypoint_fixorigin(destination, tracetest_ent); 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); } @@ -1118,7 +1284,7 @@ entity waypoint_spawnpersonal(entity this, vector position) // drop the waypoint to a proper location: // first move it up by a player height // then move it down to hit the floor with player bbox size - position = waypoint_fixorigin(position); + position = waypoint_fixorigin(position, this); w = waypoint_spawn(position, position, WAYPOINTFLAG_GENERATED | WAYPOINTFLAG_PERSONAL); w.nearestwaypoint = NULL; @@ -1247,7 +1413,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, wp.origin, 0, walkfromwp, 1050)) + if(navigation_waypoint_will_link(wp.origin, porg, p, porg, 0, wp.origin, 0, walkfromwp, 1050)) { // we may find a better one maxdist = vlen(wp.origin - porg); @@ -1263,8 +1429,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, wp.origin, 0, walkfromwp, 1050)) - if(navigation_waypoint_will_link(it.origin, porg, p, it.origin, 0, walkfromwp, 1050)) + if(navigation_waypoint_will_link(wp.origin, it.origin, p, it.origin, 0, wp.origin, 0, walkfromwp, 1050)) + if(navigation_waypoint_will_link(it.origin, porg, p, porg, 0, it.origin, 0, walkfromwp, 1050)) { bestdist = d; p.(fld) = it; @@ -1272,7 +1438,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en }); if(bestdist < maxdist) { - LOG_INFO("update chain to new nearest WP ", etos(p.(fld)), "\n"); + LOG_INFO("update chain to new nearest WP ", etos(p.(fld))); return 0; } @@ -1318,7 +1484,7 @@ float botframe_autowaypoints_fix_from(entity p, float walkfromwp, entity wp, .en if(wp) { - if(!navigation_waypoint_will_link(wp.origin, o, p, wp.origin, 0, walkfromwp, 1050)) + if(!navigation_waypoint_will_link(wp.origin, o, p, o, 0, wp.origin, 0, walkfromwp, 1050)) { // we cannot walk from wp.origin to o // get closer to tmax @@ -1344,14 +1510,14 @@ 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, o, 0, walkfromwp, 1050)) + if(navigation_waypoint_will_link(o, porg, p, porg, 0, o, 0, walkfromwp, 1050)) break; // o is no good, we need to get closer to the player tmax = t; } - LOG_INFO("spawning a waypoint for connecting to ", etos(wp), "\n"); + LOG_INFO("spawning a waypoint for connecting to ", etos(wp)); botframe_autowaypoints_createwp(o, p, fld, 0); return 1; } @@ -1367,7 +1533,7 @@ void botframe_autowaypoints_fix(entity p, float walkfromwp, .entity fld) if(r != -1) return; - LOG_INFO("emergency: got no good nearby WP to build a link from, starting a new chain\n"); + LOG_INFO("emergency: got no good nearby WP to build a link from, starting a new chain"); if(!botframe_autowaypoints_fixdown(p.origin)) return; // shouldn't happen, caught above botframe_autowaypoints_createwp(trace_endpos, p, fld, WAYPOINTFLAG_PROTECTED); @@ -1441,7 +1607,7 @@ LABEL(next) IL_EACH(g_waypoints, !(it.wpflags & (WAYPOINTFLAG_USEFUL | WAYPOINTFLAG_DEAD_END)), { - LOG_INFOF("Removed a waypoint at %v. Try again for more!\n", it.origin); + LOG_INFOF("Removed a waypoint at %v. Try again for more!", it.origin); te_explosion(it.origin); waypoint_remove(it); break; @@ -1455,12 +1621,12 @@ LABEL(next) void botframe_autowaypoints() { - FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && !IS_DEAD(it), LAMBDA( + FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && !IS_DEAD(it), { // going back is broken, so only fix waypoints to walk TO the player //botframe_autowaypoints_fix(p, false, botframe_autowaypoints_lastwp0); botframe_autowaypoints_fix(it, true, botframe_autowaypoints_lastwp1); //te_explosion(p.botframe_autowaypoints_lastwp0.origin); - )); + }); if (autocvar_g_waypointeditor_auto >= 2) { botframe_deleteuselesswaypoints();