// often path can be optimized by not adding the nearest waypoint
if (this.goalentity.navigation_dynamicgoal || autocvar_g_waypointeditor)
{
- if (nearest_wp.enemy.wpcost < autocvar_bot_ai_strategyinterval_movingtarget
- && vdist(vec2(this.goalentity.origin - nearest_wp.origin), >, 16))
+ if (nearest_wp.enemy.wpcost < autocvar_bot_ai_strategyinterval_movingtarget)
{
- set_tracewalk_dest(this.goalentity, nearest_wp.enemy.origin, true);
- if (trace_ent == this || (vdist(tracewalk_dest - nearest_wp.enemy.origin, <, 1050)
- && vlen2(tracewalk_dest - nearest_wp.enemy.origin) < vlen2(nearest_wp.origin - nearest_wp.enemy.origin)
- && tracewalk(this, nearest_wp.enemy.origin, STAT(PL_MIN, this), STAT(PL_MAX, this),
- tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode)))
- {
+ if (vdist(vec2(this.goalentity.origin - nearest_wp.origin), <, 32))
e = nearest_wp.enemy;
+ else
+ {
+ set_tracewalk_dest(this.goalentity, nearest_wp.enemy.origin, true);
+ if (trace_ent == this || (vdist(tracewalk_dest - nearest_wp.enemy.origin, <, 1050)
+ && vlen2(tracewalk_dest - nearest_wp.enemy.origin) < vlen2(nearest_wp.origin - nearest_wp.enemy.origin)
+ && tracewalk(this, nearest_wp.enemy.origin, STAT(PL_MIN, this), STAT(PL_MAX, this),
+ tracewalk_dest, tracewalk_dest_height, bot_navigation_movemode)))
+ {
+ e = nearest_wp.enemy;
+ }
}
}
}
{
// make sure jumppad is really hit, don't rely on distance based checks
// as they may report a touch even if it didn't really happen
- if(this.lastteleporttime > 0
- && time - this.lastteleporttime < ((this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL) ? 2 : 0.15))
+ if(this.lastteleporttime > 0 && TELEPORT_USED(this, this.goalcurrent))
{
if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
if(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL && this.goalcurrent.owner==this)
else
return removed_goals;
}
+ else if (this.lastteleporttime > 0)
+ {
+ // sometimes bot is pushed so hard (by a jumppad or a shot) that ends up touching the next
+ // teleport / jumppad / warpzone present in its path skipping check of one or more goals
+ // if so immediately fix bot path by removing skipped goals
+ entity tele_ent = NULL;
+ if (this.goalstack01 && (this.goalstack01.wpflags & WAYPOINTFLAG_TELEPORT))
+ tele_ent = this.goalstack01;
+ else if (this.goalstack02 && (this.goalstack02.wpflags & WAYPOINTFLAG_TELEPORT))
+ tele_ent = this.goalstack02;
+ else if (this.goalstack03 && (this.goalstack03.wpflags & WAYPOINTFLAG_TELEPORT))
+ tele_ent = this.goalstack03;
+ if (tele_ent && TELEPORT_USED(this, tele_ent))
+ {
+ if (this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_GOING)
+ if (tele_ent.wpflags & WAYPOINTFLAG_PERSONAL && tele_ent.owner == this)
+ {
+ this.aistatus &= ~AI_STATUS_WAYPOINT_PERSONAL_GOING;
+ this.aistatus |= AI_STATUS_WAYPOINT_PERSONAL_REACHED;
+ }
+ while (this.goalcurrent != tele_ent)
+ {
+ navigation_poproute(this);
+ ++removed_goals;
+ }
+ navigation_poproute(this);
+ this.lastteleporttime = 0;
+ ++removed_goals;
+ return removed_goals;
+ }
+ }
// Loose goal touching check when running
if(this.aistatus & AI_STATUS_RUNNING)
entity navigation_get_really_close_waypoint(entity this)
{
entity wp = this.goalcurrent;
- if(!wp || vdist(wp.origin - this.origin, >, 50))
+ if(!wp)
wp = this.goalcurrent_prev;
if(!wp)
return NULL;
+ if(wp != this.goalcurrent_prev && vdist(wp.origin - this.origin, >, 50))
+ {
+ wp = this.goalcurrent_prev;
+ if(!wp)
+ return NULL;
+ }
if(wp.classname != "waypoint")
{
wp = wp.nearestwaypoint;
}
if(vdist(wp.origin - this.origin, >, 50))
{
+ wp = NULL;
IL_EACH(g_waypoints, !(it.wpflags & WAYPOINTFLAG_TELEPORT),
{
if(vdist(it.origin - this.origin, <, 50))
break;
}
});
+ if(!wp)
+ return NULL;
}
if(wp.wpflags & WAYPOINTFLAG_TELEPORT)
return NULL;
void navigation_unstuck(entity this)
{
- float search_radius = 1000;
-
if (!autocvar_bot_wander_enable)
return;
+ bool has_user_waypoints = false;
+ IL_EACH(g_waypoints, !(it.wpflags & WAYPOINTFLAG_GENERATED),
+ {
+ has_user_waypoints = true;
+ break;
+ });
+ if (!has_user_waypoints)
+ return;
+
+ float search_radius = 1000;
+
if (!bot_waypoint_queue_owner)
{
LOG_DEBUG(this.netname, " stuck, taking over the waypoints queue");