vector m2;
vector evadeobstacle;
vector evadelava;
- float s;
float maxspeed;
vector gco;
//float dist;
}
else
{
+ float s;
if(this.aistatus & AI_STATUS_OUT_WATER)
this.aistatus &= ~AI_STATUS_OUT_WATER;
// (only when the bot is on the ground or jumping intentionally)
this.aistatus &= ~AI_STATUS_DANGER_AHEAD;
+ bool unreachable = false;
+ s = CONTENT_SOLID;
if(trace_fraction == 1 && this.jumppadcount == 0 && !this.goalcurrent.wphardwired )
if((IS_ONGROUND(this)) || (this.aistatus & AI_STATUS_RUNNING) || (this.aistatus & AI_STATUS_ROAMING) || PHYS_INPUT_BUTTON_JUMP(this))
{
if (tracebox_hits_trigger_hurt(dst_ahead, this.mins, this.maxs, trace_endpos))
{
if (gco.z > this.origin.z + jumpstepheightvec.z)
- {
+ {
// the goal is probably on an upper platform, assume bot can't get there
- LOG_TRACE("bot ", this.netname, " avoided the goal ", this.goalcurrent.classname, " ", etos(this.goalcurrent), " because it led to a dangerous path; goal stack cleared");
- navigation_clearroute(this);
- this.bot_strategytime = 0;
+ unreachable = true;
}
else
evadelava = normalize(this.velocity) * -1;
evadelava.z = 0;
makevectors(this.v_angle.y * '0 1 0');
- if(evadeobstacle!='0 0 0'||evadelava!='0 0 0')
+ if(evadeobstacle || evadelava || (s == CONTENT_WATER))
+ {
this.aistatus |= AI_STATUS_DANGER_AHEAD;
+ if(IS_PLAYER(this.goalcurrent))
+ unreachable = true;
+ }
+ if(unreachable)
+ {
+ navigation_clearroute(this);
+ this.bot_strategytime = 0;
+ }
}
dodge = havocbot_dodge(this);
ratingscale = ratingscale * 0.00005; // enemies are rated around 20000 already
int t;
-
FOREACH_CLIENT(IS_PLAYER(it) && bot_shouldattack(this, it), LAMBDA(
// TODO: Merge this logic with the bot_shouldattack function
if(vdist(it.origin - org, <, 100) || vdist(it.origin - org, >, sradius))
continue;
*/
+ bool rate_wps = false;
if((it.flags & FL_INWATER) || (it.flags & FL_PARTIALGROUND))
- continue;
+ rate_wps = true;
// not falling
if(!IS_ONGROUND(it))
traceline(it.origin, it.origin + '0 0 -1500', true, NULL);
t = pointcontents(trace_endpos + '0 0 1');
if(t != CONTENT_SOLID )
- if(t == CONTENT_WATER || t == CONTENT_SLIME || t == CONTENT_LAVA)
- continue;
- if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos))
- continue;
+ {
+ if(t == CONTENT_WATER || t == CONTENT_SLIME || t == CONTENT_LAVA)
+ rate_wps = true;
+ else if(tracebox_hits_trigger_hurt(it.origin, it.mins, it.maxs, trace_endpos))
+ continue;
+ }
}
- // TODO: rate waypoints near the targeted player at that moment, instead of the player itself
- // adding a player as a goal seems to be quite dangerous, especially on space maps
- // remove hack in navigation_poptouchedgoals() after performing this change
-
t = ((this.health + this.armorvalue) - (it.health + it.armorvalue)) / 150;
t = bound(0, 1 + t, 3);
if (skill > 3)
t += max(0, 8 - skill) * 0.05; // less skilled bots attack more mindlessly
ratingscale *= t;
if (ratingscale > 0)
- navigation_routerating(this, it, ratingscale * BOT_RATING_ENEMY, 2000);
+ {
+ if(rate_wps)
+ {
+ entity theEnemy = it;
+ entity best_wp = NULL;
+ float best_dist = 10000;
+ IL_EACH(g_waypoints, vdist(it.origin - theEnemy.origin, <, 500) && vdist(it.origin - this.origin, >, 100),
+ {
+ float dist = vlen(it.origin - theEnemy.origin);
+ if (dist < best_dist)
+ {
+ best_wp = it;
+ best_dist = dist;
+ }
+ });
+ if (best_wp)
+ navigation_routerating(this, best_wp, ratingscale * BOT_RATING_ENEMY, 2000);
+ }
+ else
+ navigation_routerating(this, it, ratingscale * BOT_RATING_ENEMY, 2000);
+ }
));
}
// personality property
}
- // HACK: remove players/bots as goals, they can lead a bot to unexpected places (cliffs, lava, etc)
- // TODO: rate waypoints near the targetted player at that moment, instead of the player itself
- if(IS_PLAYER(this.goalcurrent))
- navigation_poproute(this);
-
// Loose goal touching check when running
if(this.aistatus & AI_STATUS_RUNNING)
if(this.speed >= autocvar_sv_maxspeed) // if -really- running
}
}
- while (this.goalcurrent && boxesoverlap(m1, m2, this.goalcurrent.absmin, this.goalcurrent.absmax))
+ while (this.goalcurrent && !IS_PLAYER(this.goalcurrent) && boxesoverlap(m1, m2, this.goalcurrent.absmin, this.goalcurrent.absmax))
{
if((this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT))
break;