]> 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 cede62366848b6407f7e8924863290c62a905099..f0b229bae48e151018ca143584bfef4019522a28 100644 (file)
@@ -44,7 +44,6 @@ void havocbot_ai(entity this)
                                this.havocbot_role(this); // little too far down the rabbit hole
                }
 
-               // TODO: tracewalk() should take care of this job (better path finding under water)
                // if we don't have a goal and we're under water look for a waypoint near the "shore" and push it
                if(!(IS_DEAD(this) || STAT(FROZEN, this)))
                if(!this.goalcurrent)
@@ -139,7 +138,9 @@ void havocbot_ai(entity this)
 
                vector now,v,next;//,heading;
                float aimdistance,skillblend,distanceblend,blend;
-               next = now = ( (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5) - (this.origin + this.view_ofs);
+
+               SET_DESTCOORDS(this.goalcurrent, this.origin, now);
+               next = now = now - (this.origin + this.view_ofs);
                aimdistance = vlen(now);
                //heading = this.velocity;
                //dprint(this.goalstack01.classname,etos(this.goalstack01),"\n");
@@ -306,12 +307,12 @@ void havocbot_bunnyhop(entity this, vector dir)
                this.bot_timelastseengoal = 0;
        }
 
-       gco = (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5;
+       SET_DESTCOORDS(this.goalcurrent, this.origin, gco);
        bunnyhopdistance = vlen(this.origin - gco);
 
        // Run only to visible goals
        if(IS_ONGROUND(this))
-       if(vlen(this.velocity - eZ * this.velocity.z) >= autocvar_sv_maxspeed) // if -really- running
+       if(vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed)) // if -really- running
        if(checkpvs(this.origin + this.view_ofs, this.goalcurrent))
        {
                        this.bot_lastseengoal = this.goalcurrent;
@@ -413,17 +414,32 @@ 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;
        vector diff;
        vector dir;
        vector flatdir;
-       vector m1;
-       vector m2;
        vector evadeobstacle;
        vector evadelava;
        float maxspeed;
@@ -507,17 +523,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)
                {
-                       if(fabs(this.velocity.z)<50)
+                       this.aistatus |= AI_STATUS_OUT_JUMPPAD;
+                       navigation_poptouchedgoals(this);
+                       return;
+               }
+               else if(this.aistatus & AI_STATUS_OUT_JUMPPAD)
+               {
+                       // 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 +563,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))
@@ -716,12 +751,13 @@ void havocbot_movetogoal(entity this)
        if(autocvar_bot_debug_goalstack)
                debuggoalstack(this);
 
-       m1 = this.goalcurrent.origin + this.goalcurrent.mins;
-       m2 = this.goalcurrent.origin + this.goalcurrent.maxs;
-       destorg = this.origin;
-       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);
+       SET_DESTCOORDS(this.goalcurrent, this.origin, destorg);
+
+       // 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);
@@ -731,8 +767,8 @@ void havocbot_movetogoal(entity this)
 
        //if (this.bot_dodgevector_time < time)
        {
-       //      this.bot_dodgevector_time = time + cvar("bot_ai_dodgeupdateinterval");
-       //      this.bot_dodgevector_jumpbutton = 1;
+               //this.bot_dodgevector_time = time + cvar("bot_ai_dodgeupdateinterval");
+               //this.bot_dodgevector_jumpbutton = 1;
                evadeobstacle = '0 0 0';
                evadelava = '0 0 0';
 
@@ -742,18 +778,18 @@ void havocbot_movetogoal(entity this)
                {
                        if(this.waterlevel>WATERLEVEL_SWIMMING)
                        {
-                       //      flatdir_z = 1;
+                               //flatdir_z = 1;
                                this.aistatus |= AI_STATUS_OUT_WATER;
                        }
                        else
                        {
+                               dir = flatdir;
                                if(this.velocity.z >= 0 && !(this.watertype == CONTENT_WATER && gco.z < this.origin.z) &&
                                        ( !(this.waterlevel == WATERLEVEL_WETFEET && this.watertype == CONTENT_WATER) || this.aistatus & AI_STATUS_OUT_WATER))
                                        PHYS_INPUT_BUTTON_JUMP(this) = true;
                                else
                                        PHYS_INPUT_BUTTON_JUMP(this) = false;
                        }
-                       dir = normalize(flatdir);
                }
                else
                {
@@ -782,33 +818,12 @@ void havocbot_movetogoal(entity this)
                        }
 
                        // if bot for some reason doesn't get close to the current goal find another one
-                       if(!IS_PLAYER(this.goalcurrent) && !(this.goalcurrent.bot_pickup_respawning && this.goalcurrent_distance < 50))
+                       if(!this.jumppadcount && !IS_PLAYER(this.goalcurrent) && !(this.goalcurrent.bot_pickup_respawning && this.goalcurrent_distance < 50))
+                       if(havocbot_checkgoaldistance(this, gco))
                        {
-                               float curr_dist = vlen(this.origin - this.goalcurrent.origin);
-                               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
@@ -1263,7 +1278,9 @@ float havocbot_moveto(entity this, vector pos)
                        debuggoalstack(this);
 
                // Heading
-               vector dir = ( ( this.goalcurrent.absmin + this.goalcurrent.absmax ) * 0.5 ) - (this.origin + this.view_ofs);
+               vector dir;
+               SET_DESTCOORDS(this.goalcurrent, this.origin, dir);
+               dir = dir - (this.origin + this.view_ofs);
                dir.z = 0;
                bot_aimdir(this, dir, -1);