From 42c08e5c16159929187a67150750bce1770b6355 Mon Sep 17 00:00:00 2001 From: terencehill Date: Sun, 26 Mar 2017 16:27:53 +0200 Subject: [PATCH] Implement symmetrical editing of waypoints for ctf maps with rotational symmetry (gasoline_3teams) and with reflectional symmetry (runningmanctf) --- defaultXonotic.cfg | 6 +- qcsrc/server/autocvars.qh | 4 +- qcsrc/server/bot/api.qh | 1 + qcsrc/server/impulse.qc | 70 ++++++++++++++----- qcsrc/server/mutators/mutator/gamemode_ctf.qc | 15 ++++ 5 files changed, 76 insertions(+), 20 deletions(-) diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg index 4bbf2cb0d..b196e2148 100644 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@ -404,8 +404,10 @@ set bot_ai_timeitems_minrespawndelay 25 "bots run to items with this minimum res // waypoint editor enable set g_waypointeditor 0 set g_waypointeditor_auto 0 "Automatically create waypoints for bots while playing; BEWARE, this currently creates too many of them" -set g_waypointeditor_symmetrical 0 "Enable symmetrical editing of waypoints: 1: center is automatically determined based on CTF flag positions (NOTE: it assumes that the map is perfectly symmetrical), 2: use custom center (g_waypointeditor_symmetrical_center)" -set g_waypointeditor_symmetrical_center "0 0" "Custom center (x y) for symmetrical editing of waypoints" +set g_waypointeditor_symmetrical 0 "Enable symmetrical editing of waypoints on symmetrical CTF maps (NOTE: it assumes that the map is perfectly symmetrical). 1: automatically determine origin of symmetry; -1: use custom origin (g_waypointeditor_symmetrical_origin); 2: automatically determine axys of symmetry; -2: use custom axys (g_waypointeditor_symmetrical_axys)" +set g_waypointeditor_symmetrical_origin "0 0" "Custom origin of symmetry (x y)" +set g_waypointeditor_symmetrical_order 0 "apply rotational symmetry (around origin of symmetry) of this order instead of the default 2 (minimum value)" +set g_waypointeditor_symmetrical_axys "0 0" "Custom axys of symmetry (m q parameters of y = mx + q)" set bot_ignore_bots 0 "When set, bots don't shoot at other bots" set bot_join_empty 0 "When set, bots also play if no player has joined the server" set bot_vs_human 0 "Bots and humans play in different teams when set. positive values to make an all-bot blue team, set to negative values to make an all-bot red team, the absolute value is the ratio bots vs humans (1 for equal count). Changes will be correctly applied only from the next game" diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index 8f397397f..799259d61 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -245,7 +245,9 @@ float autocvar_g_turrets_targetscan_mindelay; bool autocvar_g_use_ammunition; bool autocvar_g_waypointeditor; bool autocvar_g_waypointeditor_symmetrical; -vector autocvar_g_waypointeditor_symmetrical_center; +vector autocvar_g_waypointeditor_symmetrical_origin; +int autocvar_g_waypointeditor_symmetrical_order; +vector autocvar_g_waypointeditor_symmetrical_axys; bool autocvar_g_waypoints_for_items; #define autocvar_g_weapon_stay cvar("g_weapon_stay") bool autocvar_g_weapon_throwable; diff --git a/qcsrc/server/bot/api.qh b/qcsrc/server/bot/api.qh index 4501d5b03..c682a25ba 100644 --- a/qcsrc/server/bot/api.qh +++ b/qcsrc/server/bot/api.qh @@ -71,6 +71,7 @@ void havocbot_goalrating_waypoints(entity this, float ratingscale, vector org, f vector havocbot_middlepoint; float havocbot_middlepoint_radius; +vector havocbot_symmetryaxys_equation; .entity bot_basewaypoint; .bool navigation_dynamicgoal; diff --git a/qcsrc/server/impulse.qc b/qcsrc/server/impulse.qc index 4f8fb32b5..aa18dab2b 100644 --- a/qcsrc/server/impulse.qc +++ b/qcsrc/server/impulse.qc @@ -571,12 +571,47 @@ IMPULSE(waypoint_clear) sprint(this, "all waypoints cleared\n"); } +vector waypoint_getSymmetricalOrigin(vector org, int ctf_flags) +{ + vector new_org = org; + if (fabs(autocvar_g_waypointeditor_symmetrical) == 1) + { + vector map_center = havocbot_middlepoint; + if (autocvar_g_waypointeditor_symmetrical == -1) + map_center = autocvar_g_waypointeditor_symmetrical_origin; + + new_org = Rotate(org - map_center, 360 * DEG2RAD / ctf_flags) + map_center; + } + else if (fabs(autocvar_g_waypointeditor_symmetrical) == 2) + { + float m = havocbot_symmetryaxys_equation.x; + float q = havocbot_symmetryaxys_equation.y; + if (autocvar_g_waypointeditor_symmetrical == -2) + { + m = autocvar_g_waypointeditor_symmetrical_axys.x; + q = autocvar_g_waypointeditor_symmetrical_axys.y; + } + + new_org.x = (1 / (1 + m*m)) * ((1 - m*m) * org.x + 2 * m * org.y - 2 * m * q); + new_org.y = (1 / (1 + m*m)) * (2 * m * org.x + (m*m - 1) * org.y + 2 * q); + } + new_org.z = org.z; + return new_org; +} + IMPULSE(navwaypoint_spawn) { if (!autocvar_g_waypointeditor) return; entity e; vector org = this.origin; bool sym = boolean(autocvar_g_waypointeditor_symmetrical); + int ctf_flags = havocbot_symmetryaxys_equation.z; + int order = ctf_flags; + if(autocvar_g_waypointeditor_symmetrical_order >= 2) + { + order = autocvar_g_waypointeditor_symmetrical_order; + ctf_flags = order; + } LABEL(add_wp); e = waypoint_spawn(org, org, 0); @@ -584,16 +619,13 @@ IMPULSE(navwaypoint_spawn) bprint(strcat("Waypoint spawned at ", vtos(org), "\n")); if(sym) { - vector map_center = havocbot_middlepoint; - if (autocvar_g_waypointeditor_symmetrical == 2) - map_center = autocvar_g_waypointeditor_symmetrical_center; - - org = e.origin; - org.x = map_center.x - (org.x - map_center.x); - org.y = map_center.y - (org.y - map_center.y); - if (vdist(org - this.origin, >, 10)) + org = waypoint_getSymmetricalOrigin(e.origin, ctf_flags); + if (vdist(org - this.origin, >, 32)) { - sym = false; + if(order > 2) + order--; + else + sym = false; goto add_wp; } } @@ -604,6 +636,13 @@ IMPULSE(navwaypoint_remove) if (!autocvar_g_waypointeditor) return; entity e = navigation_findnearestwaypoint(this, false); bool sym = boolean(autocvar_g_waypointeditor_symmetrical); + int ctf_flags = havocbot_symmetryaxys_equation.z; + int order = ctf_flags; + if(autocvar_g_waypointeditor_symmetrical_order >= 2) + { + order = autocvar_g_waypointeditor_symmetrical_order; + ctf_flags = order; + } LABEL(remove_wp); if (!e) return; @@ -618,13 +657,7 @@ IMPULSE(navwaypoint_remove) entity wp_sym = NULL; if (sym) { - vector map_center = havocbot_middlepoint; - if (autocvar_g_waypointeditor_symmetrical == 2) - map_center = autocvar_g_waypointeditor_symmetrical_center; - - vector org = e.origin; - org.x = map_center.x - (org.x - map_center.x); - org.y = map_center.y - (org.y - map_center.y); + vector org = waypoint_getSymmetricalOrigin(e.origin, ctf_flags); FOREACH_ENTITY_CLASS("waypoint", !(it.wpflags & WAYPOINTFLAG_GENERATED), { if(vdist(org - it.origin, <, 3)) { @@ -638,7 +671,10 @@ IMPULSE(navwaypoint_remove) if (sym && wp_sym) { e = wp_sym; - sym = false; + if(order > 2) + order--; + else + sym = false; goto remove_wp; } } diff --git a/qcsrc/server/mutators/mutator/gamemode_ctf.qc b/qcsrc/server/mutators/mutator/gamemode_ctf.qc index 8d5155035..4690cd8f5 100644 --- a/qcsrc/server/mutators/mutator/gamemode_ctf.qc +++ b/qcsrc/server/mutators/mutator/gamemode_ctf.qc @@ -1392,8 +1392,23 @@ void havocbot_ctf_calculate_middlepoint() } if(!n) return; + havocbot_middlepoint = s / n; havocbot_middlepoint_radius = vlen(fo - havocbot_middlepoint); + + havocbot_symmetryaxys_equation = '0 0 0'; + if(n == 2) + { + // for symmetrical editing of waypoints + entity f1 = ctf_worldflaglist; + entity f2 = f1.ctf_worldflagnext; + float m = -(f1.origin.y - f2.origin.y) / (f1.origin.x - f2.origin.x); + float q = havocbot_middlepoint.y - m * havocbot_middlepoint.x; + havocbot_symmetryaxys_equation.x = m; + havocbot_symmetryaxys_equation.y = q; + } + // store number of flags in this otherwise unused vector component + havocbot_symmetryaxys_equation.z = n; } -- 2.39.2