From 736d448f49fd631876f7dd83d81cee03eb9607f4 Mon Sep 17 00:00:00 2001 From: terencehill Date: Thu, 2 Nov 2017 23:17:38 +0100 Subject: [PATCH] Bot AI: when assigning a bot frame to find a new goal prioritize bots that have just reached a goal, so that they are more responsive especially when there are many bots and they get an item in a dangerous place (e.g. mortar in Dance). Delay goal removal for bots that see an item already taken by someone else so they have a lower priority; it also helps to find a new goal more efficiently in case they touch a waypoint --- qcsrc/server/bot/api.qh | 1 + qcsrc/server/bot/default/bot.qc | 5 ++++- qcsrc/server/bot/default/havocbot/havocbot.qc | 10 +++------- qcsrc/server/bot/default/navigation.qc | 13 ++++++++++++- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/qcsrc/server/bot/api.qh b/qcsrc/server/bot/api.qh index 1bab0b02b..cde97db88 100644 --- a/qcsrc/server/bot/api.qh +++ b/qcsrc/server/bot/api.qh @@ -87,6 +87,7 @@ void navigation_goalrating_end(entity this); void navigation_goalrating_start(entity this); void navigation_goalrating_timeout_set(entity this); void navigation_goalrating_timeout_force(entity this); +void navigation_goalrating_timeout_expire(entity this, float seconds); bool navigation_goalrating_timeout(entity this); bool navigation_goalrating_timeout_can_be_anticipated(entity this); void navigation_markroutes(entity this, entity fixed_source_waypoint); diff --git a/qcsrc/server/bot/default/bot.qc b/qcsrc/server/bot/default/bot.qc index 61a69747c..23a58dca8 100644 --- a/qcsrc/server/bot/default/bot.qc +++ b/qcsrc/server/bot/default/bot.qc @@ -770,6 +770,8 @@ void bot_serverframe() // frame, which causes choppy framerates) if (bot_strategytoken_taken) { + // give goal token to the first bot without goals; if all bots don't have + // any goal (or are dead/frozen) simply give it to the next one bot_strategytoken_taken = false; entity bot_strategytoken_save = bot_strategytoken; while (true) @@ -779,7 +781,8 @@ void bot_serverframe() if (!bot_strategytoken) bot_strategytoken = bot_list; - if (!(IS_DEAD(bot_strategytoken) || STAT(FROZEN, bot_strategytoken))) + if (!(IS_DEAD(bot_strategytoken) || STAT(FROZEN, bot_strategytoken)) + && !bot_strategytoken.goalcurrent) break; if (!bot_strategytoken_save) // break loop if all the bots are dead or frozen diff --git a/qcsrc/server/bot/default/havocbot/havocbot.qc b/qcsrc/server/bot/default/havocbot/havocbot.qc index 98f8b790b..7ca929859 100644 --- a/qcsrc/server/bot/default/havocbot/havocbot.qc +++ b/qcsrc/server/bot/default/havocbot/havocbot.qc @@ -752,9 +752,7 @@ void havocbot_movetogoal(entity this) if(checkpvs(this.origin, this.goalentity)) { this.goalentity.bot_pickup_respawning = false; - navigation_clearroute(this); - navigation_goalrating_timeout_force(this); - return; + navigation_goalrating_timeout_expire(this, random()); } locked_goal = true; // wait for item to respawn } @@ -765,9 +763,7 @@ void havocbot_movetogoal(entity this) { if(checkpvs(this.origin, this.goalentity)) { - navigation_clearroute(this); - navigation_goalrating_timeout_force(this); - return; + navigation_goalrating_timeout_expire(this, random()); } } } @@ -797,7 +793,7 @@ void havocbot_movetogoal(entity this) if(autocvar_bot_debug_goalstack) debuggoalstack(this); - bool bunnyhop_forbidden = false;; + bool bunnyhop_forbidden = false; SET_DESTCOORDS(this.goalcurrent, this.origin, destorg); // in case bot ends up inside the teleport waypoint without touching diff --git a/qcsrc/server/bot/default/navigation.qc b/qcsrc/server/bot/default/navigation.qc index cd21f7aa8..d2b073b5c 100644 --- a/qcsrc/server/bot/default/navigation.qc +++ b/qcsrc/server/bot/default/navigation.qc @@ -25,9 +25,20 @@ void navigation_goalrating_timeout_set(entity this) this.bot_strategytime = time + autocvar_bot_ai_strategyinterval; } +// use this when current goal must be discarded immediately void navigation_goalrating_timeout_force(entity this) { - this.bot_strategytime = 0; + navigation_goalrating_timeout_expire(this, 0); +} + +// use this when current goal can be kept for a short while to increase the chance +// of bot touching a waypoint, which helps to find a new goal more efficiently +void navigation_goalrating_timeout_expire(entity this, float seconds) +{ + if (seconds <= 0) + this.bot_strategytime = 0; + else if (this.bot_strategytime > time + seconds) + this.bot_strategytime = time + seconds; } bool navigation_goalrating_timeout(entity this) -- 2.39.2