From 991afcbcdeaf904cd052ad7399d00d0ec6e619f8 Mon Sep 17 00:00:00 2001 From: terencehill Date: Tue, 31 Oct 2017 19:09:24 +0100 Subject: [PATCH] Bot AI: implement goal locking for goals that require bot to stand on the goal's position, currently used in CTF when bot heads to his own base trying to capture flag; it fixes bot wasting a lot of CPU cycles trying to find a new goal every frame if it reaches his own base and his own flag is stolen --- qcsrc/server/bot/default/havocbot/havocbot.qc | 16 ++++++++++++++-- qcsrc/server/bot/default/navigation.qc | 5 ++++- qcsrc/server/bot/default/navigation.qh | 2 ++ qcsrc/server/mutators/mutator/gamemode_ctf.qc | 14 ++++++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/qcsrc/server/bot/default/havocbot/havocbot.qc b/qcsrc/server/bot/default/havocbot/havocbot.qc index d77c5a18e..86826f6b6 100644 --- a/qcsrc/server/bot/default/havocbot/havocbot.qc +++ b/qcsrc/server/bot/default/havocbot/havocbot.qc @@ -753,6 +753,7 @@ void havocbot_movetogoal(entity this) navigation_goalrating_timeout_force(this); return; } + locked_goal = true; // wait for item to respawn } else if(this.goalentity == this.goalcurrent) locked_goal = true; // wait for item to respawn @@ -767,6 +768,9 @@ void havocbot_movetogoal(entity this) } } } + if (this.goalcurrent == this.goalentity && this.goalentity_lock_timeout > time) + locked_goal = true; + if(!locked_goal) { // optimize path finding by anticipating goalrating when bot is near a waypoint; @@ -804,7 +808,15 @@ void havocbot_movetogoal(entity this) } diff = destorg - this.origin; - //dist = vlen(diff); + + if (fabs(diff.x) < 10 && fabs(diff.y) < 10 + && this.goalcurrent == this.goalentity && time < this.goalentity_lock_timeout) + { + destorg = this.origin; + diff.x = 0; + diff.y = 0; + } + dir = normalize(diff); flatdir = diff;flatdir.z = 0; flatdir = normalize(flatdir); @@ -866,7 +878,7 @@ void havocbot_movetogoal(entity this) // if bot for some reason doesn't get close to the current goal find another one if(!this.jumppadcount && !IS_PLAYER(this.goalcurrent)) - if(!(this.goalcurrent.bot_pickup_respawning && this.goalcurrent_distance_z < 50 && this.goalcurrent_distance_2d < 50)) + if(!(locked_goal && this.goalcurrent_distance_z < 50 && this.goalcurrent_distance_2d < 50)) if(havocbot_checkgoaldistance(this, gco)) { if(this.goalcurrent_distance_time < 0) // can't get close for the second time diff --git a/qcsrc/server/bot/default/navigation.qc b/qcsrc/server/bot/default/navigation.qc index 135b5fc68..c512b8eb4 100644 --- a/qcsrc/server/bot/default/navigation.qc +++ b/qcsrc/server/bot/default/navigation.qc @@ -625,7 +625,7 @@ void navigation_clearroute(entity this) this.goalcurrent_distance_2d = FLOAT_MAX; this.goalcurrent_distance_z = FLOAT_MAX; this.goalcurrent_distance_time = 0; - //print("bot ", etos(this), " clear\n"); + this.goalentity_lock_timeout = 0; this.goalentity = NULL; this.goalcurrent = NULL; this.goalstack01 = NULL; @@ -721,7 +721,10 @@ void navigation_poproute(entity this) this.goalcurrent_distance_time = 0; //print("bot ", etos(this), " pop\n"); if(this.goalcurrent == this.goalentity) + { this.goalentity = NULL; + this.goalentity_lock_timeout = 0; + } this.goalcurrent = this.goalstack01; this.goalstack01 = this.goalstack02; this.goalstack02 = this.goalstack03; diff --git a/qcsrc/server/bot/default/navigation.qh b/qcsrc/server/bot/default/navigation.qh index 90777d30c..350367984 100644 --- a/qcsrc/server/bot/default/navigation.qh +++ b/qcsrc/server/bot/default/navigation.qh @@ -29,6 +29,8 @@ entity navigation_bestgoal; .float goalcurrent_distance_2d; .float goalcurrent_distance_time; +.float goalentity_lock_timeout; + .entity nearestwaypoint; .float nearestwaypointtimeout; diff --git a/qcsrc/server/mutators/mutator/gamemode_ctf.qc b/qcsrc/server/mutators/mutator/gamemode_ctf.qc index cd891b6bf..739f672ca 100644 --- a/qcsrc/server/mutators/mutator/gamemode_ctf.qc +++ b/qcsrc/server/mutators/mutator/gamemode_ctf.qc @@ -540,6 +540,9 @@ void ctf_Handle_Capture(entity flag, entity toucher, int capturetype) if(CTF_DIFFTEAM(player, flag)) { return; } if((flag.cnt || enemy_flag.cnt) && flag.cnt != enemy_flag.cnt) { return; } // this should catch some edge cases (capturing grouped flag at ungrouped flag disallowed etc) + if (toucher.goalentity == flag.bot_basewaypoint) + toucher.goalentity_lock_timeout = 0; + if(ctf_oneflag) for(tmp_entity = ctf_worldflaglist; tmp_entity; tmp_entity = tmp_entity.ctf_worldflagnext) if(SAME_TEAM(tmp_entity, player)) @@ -1669,6 +1672,17 @@ void havocbot_role_ctf_carrier(entity this) navigation_goalrating_timeout_set(this); + entity head = ctf_worldflaglist; + while (head) + { + if (this.goalentity == head.bot_basewaypoint) + { + this.goalentity_lock_timeout = time + 5; + break; + } + head = head.ctf_worldflagnext; + } + if (this.goalentity) this.havocbot_cantfindflag = time + 10; else if (time > this.havocbot_cantfindflag) -- 2.39.2