From: terencehill Date: Mon, 17 Jun 2019 13:03:05 +0000 (+0200) Subject: Bot waypoints: allow creating waypoints for "broken" jumppads (mostly the vertical... X-Git-Tag: xonotic-v0.8.5~1356^2~38 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=a9572707e439fde646aaf04a53e0202bdf8028c4;p=xonotic%2Fxonotic-data.pk3dir.git Bot waypoints: allow creating waypoints for "broken" jumppads (mostly the vertical ones). How to do it: 1) aim to a jumppad and spawn a waypoint with "wpeditor spawn crosshair"; 2) spawn another waypoint that will be the jumppad destination waypoint; 3) verify that bots can actually use it --- diff --git a/qcsrc/common/mapobjects/trigger/jumppads.qc b/qcsrc/common/mapobjects/trigger/jumppads.qc index a61935eb8c..30cbc43364 100644 --- a/qcsrc/common/mapobjects/trigger/jumppads.qc +++ b/qcsrc/common/mapobjects/trigger/jumppads.qc @@ -339,13 +339,58 @@ bool trigger_push_testorigin_for_item(entity tracetest_ent, entity item, vector } #endif +#ifdef SVQC +vector trigger_push_get_start_point(entity this) +{ + // calculate a typical start point for the jump + vector org = (this.absmin + this.absmax) * 0.5; + org.z = this.absmax.z - PL_MIN_CONST.z - 7; + return org; +} + +float trigger_push_get_push_time(entity this, vector endpos) +{ + vector org = trigger_push_get_start_point(this); + + entity e = spawn(); + setsize(e, PL_MIN_CONST, PL_MAX_CONST); + e.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP; + float grav = PHYS_GRAVITY(NULL); + if (e && PHYS_ENTGRAVITY(e)) + grav *= PHYS_ENTGRAVITY(e); + + entity t = this.enemy; + if (t) + { + vector v = trigger_push_calculatevelocity(org, t, this.height, e); + vector v2 = trigger_push_calculatevelocity(endpos, t, this.height, e); + return (v.z + v2.z) / grav; + } + else if (!(this.target && this.target != "")) + { + if (!this.team) + { + vector v = this.movedir; + + float t = v.z / grav; + float jump_height = 1/2 * grav * (t ** 2); + float remaining_height = org.z + jump_height - endpos.z; + float v2_z = sqrt(2 * grav * remaining_height); + + return (v.z + v2_z) / grav; + } + } + return 0; +} +#endif + /// if (item != NULL) returns true if the item can be reached by using this jumppad, false otherwise /// if (item == NULL) tests jumppad's trajectory and eventually spawns waypoints for it (return value doesn't matter) bool trigger_push_test(entity this, entity item) { - // first calculate a typical start point for the jump - vector org = (this.absmin + this.absmax) * 0.5; - org.z = this.absmax.z - PL_MIN_CONST.z - 7; +#ifdef SVQC + vector org = trigger_push_get_start_point(this); +#endif if (this.target) { diff --git a/qcsrc/server/bot/default/waypoints.qc b/qcsrc/server/bot/default/waypoints.qc index 8dc27c515a..c36398163f 100644 --- a/qcsrc/server/bot/default/waypoints.qc +++ b/qcsrc/server/bot/default/waypoints.qc @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -273,8 +274,10 @@ void waypoint_setupmodel(entity wp) wp.colormod = '1 0 0'; else if (wp.wpflags & WAYPOINTFLAG_GENERATED) wp.colormod = '1 1 0'; + else if (wp.wpflags & WAYPOINTFLAG_NORELINK) + wp.colormod = '1 0.5 0'; // orange else if (wp.wphardwired) - wp.colormod = '0.5 0 1'; + wp.colormod = '0.5 0 1'; // violet else wp.colormod = '1 1 1'; } @@ -345,14 +348,48 @@ entity waypoint_spawn(vector m1, vector m2, float f) return w; } +float trigger_push_get_push_time(entity this, vector endpos); +void waypoint_addlink_for_custom_jumppad(entity wp_from, entity wp_to) +{ + entity jp = NULL; + IL_EACH(g_jumppads, boxesoverlap(wp_from.absmin, wp_from.absmax, it.absmin, it.absmax), + { + jp = it; + }); + float cost = trigger_push_get_push_time(jp, wp_to.origin); + wp_from.wp00 = wp_to; + wp_from.wp00mincost = cost; + jp.nearestwaypoint = wp_from; + jp.nearestwaypointtimeout = -1; +} + +bool start_wp_is_spawned; +vector start_wp_origin; + +void waypoint_clear_start_wp(entity pl) +{ + start_wp_is_spawned = false; + start_wp_origin = '0 0 0'; + pl.wp_locked = NULL; + LOG_INFO("^xf80Start waypoint has been cleared\n"); +} + void waypoint_spawn_fromeditor(entity pl, bool at_crosshair) { - entity e; + entity e = NULL, jp = NULL; vector org = pl.origin; if (at_crosshair) { crosshair_trace(pl); - org = trace_endpos - eZ * STAT(PL_MIN, pl).z; + org = trace_endpos - eZ * PL_MIN_CONST.z; + IL_EACH(g_jumppads, boxesoverlap(org + PL_MIN_CONST, org + PL_MAX_CONST, it.absmin, it.absmax), + { + jp = it; + break; + }); + if (jp && start_wp_is_spawned) + start_wp_is_spawned = false; + LOG_INFO("^xf80Spawning start waypoint\n"); } int ctf_flags = havocbot_symmetry_origin_order; bool sym = ((autocvar_g_waypointeditor_symmetrical > 0 && ctf_flags >= 2) @@ -378,18 +415,80 @@ void waypoint_spawn_fromeditor(entity pl, bool at_crosshair) }); } + vector start_org = '0 0 0'; + if (start_wp_is_spawned) + { + LOG_INFO("^xf80Spawning destination waypoint\n"); + start_org = start_wp_origin; + } + + // save org as it can be modified spawning symmetrycal waypoints + vector org_save = org; + LABEL(add_wp); - e = waypoint_spawn(org, org, 0); + + if (jp) + { + e = NULL; + IL_EACH(g_waypoints, it.wpflags & WAYPOINTFLAG_NORELINK + && boxesoverlap(org + PL_MIN_CONST, org + PL_MAX_CONST, it.absmin, it.absmax), + { + e = it; break; + }); + if (!e) + e = waypoint_spawn(jp.absmin - PL_MAX_CONST + '1 1 1', jp.absmax - PL_MIN_CONST + '-1 -1 -1', WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_NORELINK); + if (!pl.wp_locked) + pl.wp_locked = e; + } + else + e = waypoint_spawn(org, org, 0); if(!e) { LOG_INFOF("Couldn't spawn waypoint at %v\n", org); + if (start_wp_is_spawned) + waypoint_clear_start_wp(pl); return; } + + entity start_wp = NULL; + if (start_wp_is_spawned) + { + IL_EACH(g_waypoints, it.wpflags & WAYPOINTFLAG_NORELINK + && boxesoverlap(start_org, start_org, it.absmin, it.absmax), + { + start_wp = it; break; + }); + if(!start_wp) + { + // should not happen + LOG_INFOF("Couldn't find custom jumppad waypoint at %v\n", start_org); + waypoint_clear_start_wp(pl); + return; + } + waypoint_addlink_for_custom_jumppad(start_wp, e); + } + waypoint_schedulerelink(e); bprint(strcat("Waypoint spawned at ", vtos(e.origin), "\n")); - if(sym) + + if (start_wp_is_spawned) { - org = waypoint_getSymmetricalPoint(e.origin, ctf_flags); + pl.wp_locked = NULL; + waypoint_schedulerelink(start_wp); + } + + if (sym) + { + org = waypoint_getSymmetricalPoint(org, ctf_flags); + if (jp) + { + IL_EACH(g_jumppads, boxesoverlap(org + PL_MIN_CONST, org + PL_MAX_CONST, it.absmin, it.absmax), + { + jp = it; break; + }); + } + if (start_wp_is_spawned) + start_org = waypoint_getSymmetricalPoint(start_org, ctf_flags); if (vdist(org - pl.origin, >, 32)) { if(wp_num > 2) @@ -399,6 +498,17 @@ void waypoint_spawn_fromeditor(entity pl, bool at_crosshair) goto add_wp; } } + + if (jp) + { + if (!start_wp_is_spawned) + { + // we've just created a custom jumppad waypoint + // the next one created by the user will be the destination waypoint + start_wp_is_spawned = true; + start_wp_origin = org_save; + } + } } void waypoint_remove(entity wp) @@ -426,7 +536,12 @@ void waypoint_remove_fromeditor(entity pl) LABEL(remove_wp); if (!e) return; - if (e.wpflags & WAYPOINTFLAG_GENERATED) return; + if (e.wpflags & WAYPOINTFLAG_GENERATED) + { + if (start_wp_is_spawned) + waypoint_clear_start_wp(pl); + return; + } if (e.wphardwired) { @@ -459,6 +574,9 @@ void waypoint_remove_fromeditor(entity pl) sym = false; goto remove_wp; } + + if (start_wp_is_spawned) + waypoint_clear_start_wp(pl); } void waypoint_removelink(entity from, entity to) @@ -937,7 +1055,10 @@ bool waypoint_load_links() } ++c; - waypoint_addlink(wp_from, wp_to); + if ((wp_from.wpflags & WAYPOINTFLAG_NORELINK) && !(wp_from.wpflags & WAYPOINTFLAG_GENERATED)) + waypoint_addlink_for_custom_jumppad(wp_from, wp_to); + else + waypoint_addlink(wp_from, wp_to); } fclose(file);