X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fbot%2Fdefault%2Fwaypoints.qc;h=2ea30b50fe31ab5f742df66155f60c327ce3e073;hb=7e5268799e95d0dd6f2b77ed4e097b0adc755f2b;hp=d4ef6d14d0ca576376fc86a987677e3f86d4be5e;hpb=5a7362e456f39815970f1d71cfc8822446e3cb60;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/bot/default/waypoints.qc b/qcsrc/server/bot/default/waypoints.qc index d4ef6d14d..2ea30b50f 100644 --- a/qcsrc/server/bot/default/waypoints.qc +++ b/qcsrc/server/bot/default/waypoints.qc @@ -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; @@ -179,24 +179,27 @@ 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; }); } + // 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); @@ -223,7 +226,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"); } } @@ -243,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)) { @@ -260,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; @@ -279,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; @@ -293,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)) @@ -306,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; @@ -329,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)) { @@ -345,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; @@ -453,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); } @@ -564,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"); @@ -583,8 +586,12 @@ void waypoint_think(entity this) continue; } - SET_TRACEWALK_DESTCOORDS_2(this, it.origin, sv, sv2, sv2_height); - SET_TRACEWALK_DESTCOORDS_2(it, this.origin, ev, ev2, ev2_height); + 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; @@ -612,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; @@ -621,6 +628,7 @@ void waypoint_think(entity this) }); navigation_testtracewalk = 0; this.wplinked = true; + this.dphitcontentsmask = dphitcontentsmask_save; } void waypoint_clearlinks(entity wp) @@ -682,27 +690,38 @@ 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; + string links_time = string_null; while ((s = fgets(file))) { @@ -710,14 +729,32 @@ bool waypoint_load_links() { if(substring(s, 0, 2) == "//") { - if(substring(s, 2, 8) == "VERSION ") - ver = stof(substring(s, 10, -1)); + 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) - return false; + if(ver < WAYPOINT_VERSION || links_time != waypoint_time) + { + 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"); + } + else + { + LOG_TRACE("automatically updating..."); + waypoint_schedulerelinkall(); + fclose(file); + return false; + } + } parse_comments = false; } } @@ -728,6 +765,7 @@ bool waypoint_load_links() { // bad file format fclose(file); + waypoint_schedulerelinkall(); // link all the autogenerated waypoints (teleporters) return false; } @@ -755,7 +793,6 @@ bool waypoint_load_links() LOG_TRACE("waypoint_load_links: couldn't find 'from' waypoint at ", vtos(wp_from_pos)); continue; } - } // Search "to" waypoint @@ -784,7 +821,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; @@ -792,14 +841,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) @@ -844,7 +902,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; } } @@ -866,7 +924,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; } @@ -886,8 +944,8 @@ void waypoint_load_or_remove_links_hardwired(bool removal_mode) 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"); } entity waypoint_get_link(entity w, float i) @@ -936,15 +994,19 @@ 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("//", "VERSION ", ftos_decimals(WAYPOINT_VERSION, 2), "\n")); + 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, @@ -954,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; @@ -961,9 +1024,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(); } @@ -971,22 +1035,52 @@ 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; } - // 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("//", "VERSION ", ftos_decimals(WAYPOINT_VERSION, 2), "\n")); - fputs(file, strcat("//", "\n")); - fputs(file, strcat("//", "\n")); + fputs(file, strcat("//", "WAYPOINT_VERSION ", ftos_decimals(WAYPOINT_VERSION, 2), "\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, @@ -995,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"); @@ -1007,23 +1102,29 @@ 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); - bool parse_comments = true; - float ver = 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) { @@ -1031,20 +1132,38 @@ float waypoint_loadall() 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))) { if(parse_comments) { if(substring(s, 0, 2) == "//") { - if(substring(s, 2, 8) == "VERSION ") - ver = stof(substring(s, 10, -1)); + 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 { 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; } } @@ -1066,12 +1185,48 @@ 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; } -vector waypoint_fixorigin(vector position, entity tracetest_ent) +#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, tracetest_ent); + 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; return position; @@ -1129,10 +1284,18 @@ void waypoint_spawnforteleporter_boxes(entity e, int teleport_flag, vector org1, e.nearestwaypointtimeout = -1; } -void waypoint_spawnforteleporter_wz(entity e, vector org, vector destination, float timetaken, entity tracetest_ent) +void waypoint_spawnforteleporter_wz(entity e, vector org, vector destination, float timetaken, vector down_dir, entity tracetest_ent) { - org = waypoint_fixorigin(org, tracetest_ent); - destination = waypoint_fixorigin(destination, tracetest_ent); + // 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); } @@ -1210,6 +1373,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)) @@ -1278,7 +1443,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); @@ -1294,8 +1459,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; @@ -1303,7 +1468,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; } @@ -1349,7 +1514,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 @@ -1375,14 +1540,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; } @@ -1398,7 +1563,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); @@ -1472,7 +1637,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;