mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
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:
@@ -18,6 +18,7 @@
|
||||
# COMBAT
|
||||
# CHEATS
|
||||
# SPELLS
|
||||
# FLIGHTPATH
|
||||
# PLAYERBOT RNDBOT SPECIFIC SETTINGS
|
||||
# GENERAL
|
||||
# LEVELS
|
||||
@@ -495,6 +496,28 @@ AiPlayerbot.OpenGoSpell = 6477
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
####################################################################################################
|
||||
# FLIGHTPATH
|
||||
#
|
||||
#
|
||||
|
||||
# Min random delay before the 1st follower bot clicks the flight-master (ms)
|
||||
AiPlayerbot.BotTaxiDelayMinMs = 350
|
||||
|
||||
# Upper bound for the overall taxi delay window (ms) – larger spreads big raids
|
||||
AiPlayerbot.BotTaxiDelayMaxMs = 5000
|
||||
|
||||
# Fixed gap added per group-slot so bots never take off together (ms)
|
||||
AiPlayerbot.BotTaxiGapMs = 200
|
||||
|
||||
# Extra small randomness added to each gap so launches don’t look robotic (ms)
|
||||
AiPlayerbot.BotTaxiGapJitterMs = 100
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
#######################################
|
||||
# #
|
||||
# PLAYERBOT RNDBOT SPECIFIC SETTINGS #
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "CreatureData.h"
|
||||
#include "EmoteAction.h"
|
||||
#include "Engine.h"
|
||||
#include "EventProcessor.h"
|
||||
#include "ExternalEventHelper.h"
|
||||
#include "GameObjectData.h"
|
||||
#include "GameTime.h"
|
||||
@@ -6279,3 +6280,23 @@ SpellFamilyNames PlayerbotAI::Class2SpellFamilyName(uint8 cls)
|
||||
}
|
||||
return SPELLFAMILY_GENERIC;
|
||||
}
|
||||
|
||||
void PlayerbotAI::AddTimedEvent(std::function<void()> callback, uint32 delayMs)
|
||||
{
|
||||
class LambdaEvent final : public BasicEvent
|
||||
{
|
||||
std::function<void()> _cb;
|
||||
public:
|
||||
explicit LambdaEvent(std::function<void()> cb) : _cb(std::move(cb)) {}
|
||||
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
|
||||
{
|
||||
_cb();
|
||||
return true; // remove after execution
|
||||
}
|
||||
};
|
||||
|
||||
// Every Player already owns an EventMap called m_Events
|
||||
bot->m_Events.AddEvent(
|
||||
new LambdaEvent(std::move(callback)),
|
||||
bot->m_Events.CalculateTime(delayMs));
|
||||
}
|
||||
@@ -590,6 +590,9 @@ public:
|
||||
NewRpgStatistic rpgStatistic;
|
||||
std::unordered_set<uint32> lowPriorityQuest;
|
||||
|
||||
// Schedules a callback to run once after <delayMs> milliseconds.
|
||||
void AddTimedEvent(std::function<void()> callback, uint32 delayMs);
|
||||
|
||||
private:
|
||||
static void _fillGearScoreData(Player* player, Item* item, std::vector<uint32>* gearScore, uint32& twoHandScore,
|
||||
bool mixed = false);
|
||||
|
||||
@@ -331,6 +331,12 @@ bool PlayerbotAIConfig::Initialize()
|
||||
useFlyMountAtMinLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.UseFlyMountAtMinLevel", 60);
|
||||
useFastFlyMountAtMinLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.UseFastFlyMountAtMinLevel", 70);
|
||||
|
||||
// stagger bot flightpath takeoff
|
||||
delayMin = sConfigMgr->GetOption<uint32>("AiPlayerbot.BotTaxiDelayMinMs", 350u);
|
||||
delayMax = sConfigMgr->GetOption<uint32>("AiPlayerbot.BotTaxiDelayMaxMs", 5000u);
|
||||
gapMs = sConfigMgr->GetOption<uint32>("AiPlayerbot.BotTaxiGapMs", 200u);
|
||||
gapJitterMs = sConfigMgr->GetOption<uint32>("AiPlayerbot.BotTaxiGapJitterMs", 100u);
|
||||
|
||||
LOG_INFO("server.loading", "Loading TalentSpecs...");
|
||||
|
||||
for (uint32 cls = 1; cls < MAX_CLASSES; ++cls)
|
||||
|
||||
@@ -348,6 +348,12 @@ public:
|
||||
uint32 useFlyMountAtMinLevel;
|
||||
uint32 useFastFlyMountAtMinLevel;
|
||||
|
||||
// stagger flightpath takeoff
|
||||
uint32 delayMin;
|
||||
uint32 delayMax;
|
||||
uint32 gapMs;
|
||||
uint32 gapJitterMs;
|
||||
|
||||
std::string const GetTimestampStr();
|
||||
bool hasLog(std::string const fileName)
|
||||
{
|
||||
|
||||
@@ -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 npc’s 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 ===");
|
||||
|
||||
Reference in New Issue
Block a user