feat(playerbots): staggered taxi take-off for bots (#1281)

* feat(playerbots): staggered taxi take-off for bots

Adds four new configurable settings to playerbots.conf:

- AiPlayerbot.BotTaxiDelayMinMs:   Min random delay before the 1st follower bot clicks the flight-master
- AiPlayerbot.BotTaxiDelayMaxMs:   Upper bound for the overall taxi delay window – larger spreads big raids
- AiPlayerbot.BotTaxiGapMs:        Fixed gap added per group-slot so bots never take off together
- AiPlayerbot.BotTaxiGapJitterMs:  Extra small randomness added to each gap so launches don’t look robotic

These options allow server owners to fine-tune how bots queue up and take off from flight masters, making their behavior appear more natural.

Closes #1017 : Bots use Flight master nearly the same time.

* fixed build errors

Was missing a header and variable declarations.
This commit is contained in:
Type1Error
2025-05-10 11:45:15 +00:00
committed by GitHub
parent 43b0852438
commit 95c572bf48
6 changed files with 91 additions and 0 deletions

View File

@@ -8,6 +8,8 @@
#include "Event.h"
#include "LastMovementValue.h"
#include "Playerbots.h"
#include "PlayerbotAIConfig.h"
#include "Config.h"
bool TaxiAction::Execute(Event event)
{
@@ -48,6 +50,36 @@ bool TaxiAction::Execute(Event event)
}
}
// stagger bot takeoff
uint32 delayMin = sConfigMgr->GetOption<uint32>("AiPlayerbot.BotTaxiDelayMinMs", 350u, false);
uint32 delayMax = sConfigMgr->GetOption<uint32>("AiPlayerbot.BotTaxiDelayMaxMs", 5000u, false);
uint32 gapMs = sConfigMgr->GetOption<uint32>("AiPlayerbot.BotTaxiGapMs", 200u, false);
uint32 gapJitterMs = sConfigMgr->GetOption<uint32>("AiPlayerbot.BotTaxiGapJitterMs", 100u, false);
// Only for follower bots
if (botAI->HasRealPlayerMaster())
{
uint32 index = botAI->GetGroupSlotIndex(bot);
uint32 delay = delayMin + index * gapMs + urand(0, gapJitterMs);
delay = std::min(delay, delayMax);
// Store the npcs GUID so we can re-acquire the pointer later
ObjectGuid npcGuid = npc->GetGUID();
// schedule the take-off
botAI->AddTimedEvent(
[bot = bot, &movement, npcGuid]() -> void
{
if (Creature* npcPtr = ObjectAccessor::GetCreature(*bot, npcGuid))
if (!movement.taxiNodes.empty())
bot->ActivateTaxiPathTo(movement.taxiNodes, npcPtr);
},
delay);
botAI->SetNextCheckDelay(delay + 50);
return true;
}
if (param == "?")
{
botAI->TellMasterNoFacing("=== Taxi ===");