]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Bot AI: smooth walk direction instead of aim direction when bot crosses a waypoint...
authorterencehill <piuntn@gmail.com>
Sat, 26 May 2018 21:40:25 +0000 (23:40 +0200)
committerterencehill <piuntn@gmail.com>
Sun, 27 May 2018 10:12:21 +0000 (12:12 +0200)
qcsrc/server/bot/default/aim.qc
qcsrc/server/bot/default/aim.qh
qcsrc/server/bot/default/havocbot/havocbot.qc

index 5d74a8f062e026c1e038b5c7b6fe82bc22e4e527..a742071c4878476b9e6497c5fe56f711665c4082 100644 (file)
@@ -180,6 +180,8 @@ void bot_aimdir(entity this, vector v, float maxfiredeviation)
        float dist, delta_t, blend;
        vector desiredang, diffang;
 
+       this.bot_aimdir_executed = true;
+
        //dprint("aim ", this.netname, ": old:", vtos(this.v_angle));
        // make sure v_angle is sane first
        this.v_angle_y = this.v_angle.y - floor(this.v_angle.y / 360) * 360;
index b8b35f1c203a08968e3b82e7029bbfd17109e6dd..1eb71bc7ff58fee1cdaa2eecdf81003495eb5d91 100644 (file)
@@ -59,6 +59,7 @@ vector shotdir;
 .vector lag5_vec3;
 .vector lag5_vec4;
 
+.bool bot_aimdir_executed;
 .float bot_badaimtime;
 .float bot_aimthinktime;
 .float bot_prevaimtime;
index 26ded65e3d4e3022321d9bae0433ca87daf91ed0..1aa305ab3540689f0e6834ef278187ee37f29d72 100644 (file)
@@ -104,6 +104,9 @@ void havocbot_ai(entity this)
        }
        havocbot_aim(this);
        lag_update(this);
+
+       this.bot_aimdir_executed = false;
+
        if (this.bot_aimtarg)
        {
                this.aistatus |= AI_STATUS_ATTACKING;
@@ -140,48 +143,17 @@ void havocbot_ai(entity this)
        {
                this.aistatus |= AI_STATUS_ROAMING;
                this.aistatus &= ~AI_STATUS_ATTACKING;
-
-               vector now, next;
-               float aimdistance,skillblend,distanceblend,blend;
-
-               vector v = get_closer_dest(this.goalcurrent, this.origin);
-               if(this.goalcurrent.wpisbox)
-               {
-                       // avoid a glitch when bot is teleported but teleport waypoint isn't removed yet
-                       if(this.goalstack02 && this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT
-                       && this.lastteleporttime > 0 && time - this.lastteleporttime < 0.15)
-                               v = (this.goalstack02.absmin + this.goalstack02.absmax) * 0.5;
-                       // aim to teleport origin if bot is inside teleport waypoint but hasn't touched the real teleport yet
-                       else if(boxesoverlap(this.goalcurrent.absmin, this.goalcurrent.absmax, this.origin, this.origin))
-                               v = this.goalcurrent.origin;
-               }
-               next = now = v - (this.origin + this.view_ofs);
-               aimdistance = vlen(now);
-
-               //dprint(this.goalstack01.classname,etos(this.goalstack01),"\n");
-               if(
-                       this.goalstack01 != this && this.goalstack01 && !wasfreed(this.goalstack01) && ((this.aistatus & AI_STATUS_RUNNING) == 0) &&
-                       !(this.goalcurrent.wpflags & WAYPOINTFLAG_TELEPORT)
-               )
-                       next = ((this.goalstack01.absmin + this.goalstack01.absmax) * 0.5) - (this.origin + this.view_ofs);
-
-               skillblend=bound(0,(skill+this.bot_moveskill-2.5)*0.5,1); //lower skill player can't preturn
-               distanceblend=bound(0,aimdistance/autocvar_bot_ai_keyboard_distance,1);
-               blend = skillblend * (1-distanceblend);
-               //v = (now * (distanceblend) + next * (1-distanceblend)) * (skillblend) + now * (1-skillblend);
-               //v = now * (distanceblend) * (skillblend) + next * (1-distanceblend) * (skillblend) + now * (1-skillblend);
-               //v = now * ((1-skillblend) + (distanceblend) * (skillblend)) + next * (1-distanceblend) * (skillblend);
-               v = now + blend * (next - now);
-               //dprint(etos(this), " ");
-               //dprint(vtos(now), ":", vtos(next), "=", vtos(v), " (blend ", ftos(blend), ")\n");
-               //v = now * (distanceblend) + next * (1-distanceblend);
-               if (this.waterlevel < WATERLEVEL_SWIMMING)
-                       v.z = 0;
-               //dprint("walk at:", vtos(v), "\n");
-               //te_lightning2(NULL, this.origin, this.goalcurrent.origin);
-               bot_aimdir(this, v, -1);
        }
+
        havocbot_movetogoal(this);
+       if (!this.bot_aimdir_executed && this.goalcurrent)
+       {
+               // Heading
+               vector dir = get_closer_dest(this.goalcurrent, this.origin);
+               dir -= this.origin + this.view_ofs;
+               dir.z = 0;
+               bot_aimdir(this, dir, -1);
+       }
 
        // if the bot is not attacking, consider reloading weapons
        if (!(this.aistatus & AI_STATUS_ATTACKING))
@@ -488,6 +460,7 @@ void havocbot_movetogoal(entity this)
        vector flatdir;
        vector evadeobstacle;
        vector evadelava;
+       float dodge_enemy_factor = 1;
        float maxspeed;
        //float dist;
        vector dodge;
@@ -939,14 +912,18 @@ void havocbot_movetogoal(entity this)
                        // jump if going toward an obstacle that doesn't look like stairs we
                        // can walk up directly
                        vector deviation = '0 0 0';
-                       if (this.velocity)
+                       float current_speed = vlen(vec2(this.velocity));
+                       if (current_speed < maxspeed * 0.2)
+                               current_speed = maxspeed * 0.2;
+                       else
                        {
                                deviation = vectoangles(diff) - vectoangles(this.velocity);
                                while (deviation.y < -180) deviation.y += 360;
                                while (deviation.y > 180) deviation.y -= 360;
                        }
+                       float turning = false;
                        vector flat_diff = vec2(diff);
-                       offset = max(32, vlen(vec2(this.velocity)) * cos(deviation.y * DEG2RAD) * 0.2) * flatdir;
+                       offset = max(32, current_speed * cos(deviation.y * DEG2RAD) * 0.3) * flatdir;
                        vector actual_destorg = this.origin + offset;
                        if (!this.goalstack01 || this.goalcurrent.wpflags & (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_LADDER))
                        {
@@ -973,31 +950,44 @@ void havocbot_movetogoal(entity this)
                                else
                                        actual_destorg = vec2(destorg) + dist * next_dir;
                                actual_destorg.z = this.origin.z;
-
+                               turning = true;
                        }
 
-                       tracebox(this.origin, this.mins, this.maxs, actual_destorg, false, this);
-                       if (trace_fraction < 1)
-                       if (trace_plane_normal.z < 0.7)
+                       LABEL(jump_check);
+                       dir = flatdir = normalize(actual_destorg - this.origin);
+
+                       if (turning || fabs(deviation.y) < 50) // don't even try to jump if deviation is too high
                        {
-                               s = trace_fraction;
-                               tracebox(this.origin + stepheightvec, this.mins, this.maxs, actual_destorg + stepheightvec, false, this);
-                               if (trace_fraction < s + 0.01)
-                               if (trace_plane_normal.z < 0.7)
+                               tracebox(this.origin, this.mins, this.maxs, actual_destorg, false, this);
+                               if (trace_fraction < 1 && trace_plane_normal.z < 0.7)
                                {
                                        s = trace_fraction;
-                                       // don't artificially reduce max jump height in real-time
-                                       // (jumpstepheightvec is reduced a bit to make the jumps easy in tracewalk)
-                                       vector jump_height = (IS_ONGROUND(this)) ? stepheightvec + jumpheight_vec : jumpstepheightvec;
-                                       tracebox(this.origin + jump_height, this.mins, this.maxs, actual_destorg + jump_height, false, this);
-                                       if (trace_fraction > s)
-                                               PHYS_INPUT_BUTTON_JUMP(this) = true;
-                                       else
+                                       tracebox(this.origin + stepheightvec, this.mins, this.maxs, actual_destorg + stepheightvec, false, this);
+                                       if (trace_fraction < s + 0.01 && trace_plane_normal.z < 0.7)
                                        {
-                                               jump_height = stepheightvec + jumpheight_vec / 2;
+                                               // found an obstacle
+                                               if (turning && fabs(deviation.y) > 5)
+                                               {
+                                                       // check if the obstacle is still there without turning
+                                                       actual_destorg = destorg;
+                                                       turning = false;
+                                                       this.bot_tracewalk_time = time + 0.25;
+                                                       goto jump_check;
+                                               }
+                                               s = trace_fraction;
+                                               // don't artificially reduce max jump height in real-time
+                                               // (jumpstepheightvec is reduced a bit to make the jumps easy in tracewalk)
+                                               vector jump_height = (IS_ONGROUND(this)) ? stepheightvec + jumpheight_vec : jumpstepheightvec;
                                                tracebox(this.origin + jump_height, this.mins, this.maxs, actual_destorg + jump_height, false, this);
                                                if (trace_fraction > s)
                                                        PHYS_INPUT_BUTTON_JUMP(this) = true;
+                                               else
+                                               {
+                                                       jump_height = stepheightvec + jumpheight_vec / 2;
+                                                       tracebox(this.origin + jump_height, this.mins, this.maxs, actual_destorg + jump_height, false, this);
+                                                       if (trace_fraction > s)
+                                                               PHYS_INPUT_BUTTON_JUMP(this) = true;
+                                               }
                                        }
                                }
                        }
@@ -1109,33 +1099,57 @@ void havocbot_movetogoal(entity this)
                dodge = havocbot_dodge(this);
                if (dodge)
                        dodge *= bound(0, 0.5 + (skill + this.bot_dodgeskill) * 0.1, 1);
+               dodge += evadeobstacle + evadelava;
                evadelava = evadelava * bound(1,3-(skill+this.bot_dodgeskill),3); //Noobs fear lava a lot and take more distance from it
                if (this.enemy)
                {
                        traceline(this.origin, (this.enemy.absmin + this.enemy.absmax) * 0.5, true, NULL);
                        if (IS_PLAYER(trace_ent))
-                               dir = dir * bound(0, (skill + this.bot_dodgeskill) / 7, 1);
+                               dodge_enemy_factor = bound(0, (skill + this.bot_dodgeskill) / 7, 1);
                }
-
-               dir = normalize(dir + dodge + evadeobstacle + evadelava);
        //      this.bot_dodgevector = dir;
        //      this.bot_dodgevector_jumpbutton = PHYS_INPUT_BUTTON_JUMP(this);
        }
 
+       float ladder_zdir = 0;
        if(time < this.ladder_time)
        {
                if(this.goalcurrent.origin.z + this.goalcurrent.mins.z > this.origin.z + this.mins.z)
                {
                        if(this.origin.z + this.mins.z  < this.ladder_entity.origin.z + this.ladder_entity.maxs.z)
-                               dir.z = 1;
+                               ladder_zdir = 1;
                }
                else
                {
                        if(this.origin.z + this.mins.z  > this.ladder_entity.origin.z + this.ladder_entity.mins.z)
-                               dir.z = -1;
+                               ladder_zdir = -1;
+               }
+               if (ladder_zdir)
+               {
+                       dir.z = ladder_zdir * 1.3;
+                       dir = normalize(dir);
                }
        }
 
+       if (this.goalcurrent.wpisbox
+               && boxesoverlap(this.goalcurrent.absmin, this.goalcurrent.absmax, this.origin, this.origin))
+       {
+               // bot is inside teleport waypoint but hasn't touched the real teleport yet
+               // head to teleport origin
+               dir = (this.goalcurrent.origin - this.origin);
+               dir.z = 0;
+               dir = normalize(dir);
+       }
+
+       if (!this.bot_aimdir_executed)
+               bot_aimdir(this, dir, -1);
+
+       if (!ladder_zdir)
+       {
+               dir *= dodge_enemy_factor;
+               dir = normalize(dir + dodge);
+       }
+
        //dir = this.bot_dodgevector;
        //if (this.bot_dodgevector_jumpbutton)
        //      PHYS_INPUT_BUTTON_JUMP(this) = true;
@@ -1489,15 +1503,19 @@ float havocbot_moveto(entity this, vector pos)
                if(autocvar_bot_debug_goalstack)
                        debuggoalstack(this);
 
-               // Heading
-               vector dir = get_closer_dest(this.goalcurrent, this.origin);
-               dir = dir - (this.origin + this.view_ofs);
-               dir.z = 0;
-               bot_aimdir(this, dir, -1);
 
                // Go!
                havocbot_movetogoal(this);
 
+               if (!this.bot_aimdir_executed && this.goalcurrent)
+               {
+                       // Heading
+                       vector dir = get_closer_dest(this.goalcurrent, this.origin);
+                       dir -= this.origin + this.view_ofs;
+                       dir.z = 0;
+                       bot_aimdir(this, dir, -1);
+               }
+
                if(this.aistatus & AI_STATUS_WAYPOINT_PERSONAL_REACHED)
                {
                        // Step 5: Waypoint reached