#endif
}
-.entity goalcurrent_prev;
-.float goalcurrent_distance;
-.float goalcurrent_distance_time;
+// return true when bot isn't getting closer to the current goal
+bool havocbot_checkgoaldistance(entity this, vector gco)
+{
+ float curr_dist = vlen(this.origin - gco);
+ if(curr_dist > this.goalcurrent_distance)
+ {
+ if(!this.goalcurrent_distance_time)
+ this.goalcurrent_distance_time = time;
+ else if (time - this.goalcurrent_distance_time > 0.5)
+ return true;
+ }
+ else
+ {
+ // reduce it a little bit so it works even with very small approaches to the goal
+ this.goalcurrent_distance = max(20, curr_dist - 15);
+ this.goalcurrent_distance_time = 0;
+ }
+ return false;
+}
+
void havocbot_movetogoal(entity this)
{
vector destorg;
// Handling of jump pads
if(this.jumppadcount)
{
- // If got stuck on the jump pad try to reach the farthest visible waypoint
- // but with some randomness so it can try out different paths
- if(this.aistatus & AI_STATUS_OUT_JUMPPAD)
+ if(this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)
+ {
+ this.aistatus |= AI_STATUS_OUT_JUMPPAD;
+ navigation_poptouchedgoals(this);
+ return;
+ }
+ else if(this.aistatus & AI_STATUS_OUT_JUMPPAD)
{
- if(fabs(this.velocity.z)<50)
+ // If got stuck on the jump pad try to reach the farthest visible waypoint
+ // but with some randomness so it can try out different paths
+ if(!this.goalcurrent)
{
entity newgoal = NULL;
- if (vdist(this.origin - this.goalcurrent.origin, <, 150))
- this.aistatus &= ~AI_STATUS_OUT_JUMPPAD;
- else IL_EACH(g_waypoints, vdist(it.origin - this.origin, <=, 1000),
+ IL_EACH(g_waypoints, vdist(it.origin - this.origin, <=, 1000),
{
+ if(it.wpflags & WAYPOINTFLAG_TELEPORT)
+ if(it.origin.z < this.origin.z - 100 && vdist(vec2(it.origin - this.origin), <, 100))
+ continue;
+
traceline(this.origin + this.view_ofs, ((it.absmin + it.absmax) * 0.5), true, this);
if(trace_fraction < 1)
}
}
else
- return;
+ {
+ gco = (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5;
+ if (this.origin.z > gco.z && vdist(vec2(this.velocity), <, autocvar_sv_maxspeed))
+ this.aistatus &= ~AI_STATUS_OUT_JUMPPAD;
+ else if(havocbot_checkgoaldistance(this, gco))
+ {
+ navigation_clearroute(this);
+ this.bot_strategytime = 0;
+ }
+ else
+ return;
+ }
}
else
{
- if(time - this.lastteleporttime > 0.3 && this.velocity.z > 0)
+ if(time - this.lastteleporttime > 0.2 && this.velocity.z > 0)
{
vector velxy = this.velocity; velxy_z = 0;
if(vdist(velxy, <, autocvar_sv_maxspeed * 0.2))
return;
}
- else if(this.health>WEP_CVAR(devastator, damage)*0.5)
+ else if(this.health > WEP_CVAR(devastator, damage) * 0.5 * ((this.strength_finished < time) ? autocvar_g_balance_powerup_strength_selfdamage : 1))
{
if(this.velocity.z < 0)
{
destorg.x = bound(m1_x, destorg.x, m2_x);
destorg.y = bound(m1_y, destorg.y, m2_y);
destorg.z = bound(m1_z, destorg.z, m2_z);
+
+ // in case bot ends up inside the teleport waypoint without touching
+ // the teleport itself, head to the teleport origin
+ if(destorg == this.origin)
+ destorg = this.goalcurrent.origin;
+
diff = destorg - this.origin;
//dist = vlen(diff);
dir = normalize(diff);
evadeobstacle = '0 0 0';
evadelava = '0 0 0';
+ this.aistatus &= ~AI_STATUS_DANGER_AHEAD;
makevectors(this.v_angle.y * '0 1 0');
if (this.waterlevel)
{
}
// if bot for some reason doesn't get close to the current goal find another one
- float curr_dist = vlen(this.origin - this.goalcurrent.origin);
- if(!IS_PLAYER(this.goalcurrent))
+ if(!this.jumppadcount && !IS_PLAYER(this.goalcurrent) && !(this.goalcurrent.bot_pickup_respawning && this.goalcurrent_distance < 50))
+ if(havocbot_checkgoaldistance(this, gco))
{
- if(this.goalcurrent != this.goalcurrent_prev)
- {
- this.goalcurrent_prev = this.goalcurrent;
- this.goalcurrent_distance = curr_dist;
- this.goalcurrent_distance_time = 0;
- }
- else if(curr_dist > this.goalcurrent_distance)
- {
- if(!this.goalcurrent_distance_time)
- this.goalcurrent_distance_time = time;
- else if (time - this.goalcurrent_distance_time > 0.5)
- {
- this.goalcurrent_prev = NULL;
- navigation_clearroute(this);
- this.bot_strategytime = 0;
- return;
- }
- }
- else
- {
- // reduce it a little bit so it works even with very small approaches to the goal
- this.goalcurrent_distance = max(20, curr_dist - 15);
- this.goalcurrent_distance_time = 0;
- }
+ navigation_clearroute(this);
+ this.bot_strategytime = 0;
+ return;
}
// Check for water/slime/lava and dangerous edges
// (only when the bot is on the ground or jumping intentionally)
- this.aistatus &= ~AI_STATUS_DANGER_AHEAD;
vector dst_ahead = this.origin + this.view_ofs + offset;
vector dst_down = dst_ahead - '0 0 3000';
void havocbot_aim(entity this)
{
- vector myvel, enemyvel;
-// if(this.flags & FL_INWATER)
-// return;
if (time < this.nextaim)
return;
this.nextaim = time + 0.1;
- myvel = this.velocity;
+ vector myvel = this.velocity;
if (!this.waterlevel)
myvel.z = 0;
- if (this.enemy)
+ if(MUTATOR_CALLHOOK(HavocBot_Aim, this)) { /* do nothing */ }
+ else if (this.enemy)
{
- enemyvel = this.enemy.velocity;
+ vector enemyvel = this.enemy.velocity;
if (!this.enemy.waterlevel)
enemyvel.z = 0;
lag_additem(this, time + this.ping, 0, 0, this.enemy, this.origin, myvel, (this.enemy.absmin + this.enemy.absmax) * 0.5, enemyvel);