]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/bot/default/havocbot/havocbot.qc
Merge branch 'master' into terencehill/bot_waypoints
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / bot / default / havocbot / havocbot.qc
index 4c3c3f02cd74cfcf1c1f7ce609cfab534e9e2efc..c533071b029871e9b4c1436b6a0f406061cd005e 100644 (file)
@@ -413,9 +413,26 @@ void havocbot_bunnyhop(entity this, vector dir)
 #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;
@@ -507,17 +524,25 @@ void havocbot_movetogoal(entity this)
        // 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)
@@ -539,11 +564,22 @@ void havocbot_movetogoal(entity this)
                                }
                        }
                        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))
@@ -608,7 +644,7 @@ void havocbot_movetogoal(entity this)
 
                        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)
                        {
@@ -722,6 +758,12 @@ void havocbot_movetogoal(entity this)
        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);
@@ -736,6 +778,7 @@ void havocbot_movetogoal(entity this)
                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)
                {
@@ -781,38 +824,16 @@ void havocbot_movetogoal(entity this)
                        }
 
                        // 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';
@@ -1190,18 +1211,16 @@ void havocbot_chooseweapon(entity this, .entity weaponentity)
 
 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);