diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index e9d6b734..33077932 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -271,6 +271,9 @@ AiPlayerbot.DispelAuraDuration = 700 # Delay between two bot actions AiPlayerbot.ReactDelay = 100 +# Dynamically adjust react delay for bots in different status to reduce server delays +AiPlayerbot.DynamicReactDelay = 1 + # Inactivity delay AiPlayerbot.PassiveDelay = 10000 diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index 8254362c..05f2daec 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -276,116 +276,116 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa if (!player->InBattleground()) { - engine->addStrategies("racials", "chat", "default", "cast time", "duel", "boost", nullptr); + engine->addStrategiesNoInit("racials", "chat", "default", "cast time", "duel", "boost", nullptr); } if (sPlayerbotAIConfig->autoSaveMana) { - engine->addStrategy("auto save mana"); + engine->addStrategy("smana", false); } if (sPlayerbotAIConfig->autoAvoidAoe && facade->HasRealPlayerMaster()) { - engine->addStrategy("avoid aoe"); + engine->addStrategy("aaoe", false); } - engine->addStrategy("combat formation"); + engine->addStrategy("formation", false); switch (player->getClass()) { case CLASS_PRIEST: if (tab == 2) { - engine->addStrategies("dps", "shadow debuff", "shadow aoe", nullptr); + engine->addStrategiesNoInit("dps", "shadow debuff", "shadow aoe", nullptr); } else if (tab == PRIEST_TAB_DISIPLINE) { - engine->addStrategies("heal", nullptr); + engine->addStrategiesNoInit("heal", nullptr); } else { - engine->addStrategies("holy heal", nullptr); + engine->addStrategiesNoInit("holy heal", nullptr); } - engine->addStrategies("dps assist", "cure", nullptr); + engine->addStrategiesNoInit("dps assist", "cure", nullptr); break; case CLASS_MAGE: if (tab == 0) - engine->addStrategies("arcane", "arcane aoe", nullptr); + engine->addStrategiesNoInit("arcane", "arcane aoe", nullptr); else if (tab == 1) - engine->addStrategies("fire", "fire aoe", nullptr); + engine->addStrategiesNoInit("fire", "fire aoe", nullptr); else - engine->addStrategies("frost", "frost aoe", nullptr); + engine->addStrategiesNoInit("frost", "frost aoe", nullptr); - engine->addStrategies("dps", "dps assist", "cure", nullptr); + engine->addStrategiesNoInit("dps", "dps assist", "cure", nullptr); break; case CLASS_WARRIOR: if (tab == 2) - engine->addStrategies("tank", "tank assist", "aoe", "mark rti", nullptr); + engine->addStrategiesNoInit("tank", "tank assist", "aoe", "mark rti", nullptr); else if (player->GetLevel() < 36 || tab == 0) - engine->addStrategies("arms", "aoe", "dps assist", /*"behind",*/ nullptr); + engine->addStrategiesNoInit("arms", "aoe", "dps assist", /*"behind",*/ nullptr); else - engine->addStrategies("fury", "aoe", "dps assist", /*"behind",*/ nullptr); + engine->addStrategiesNoInit("fury", "aoe", "dps assist", /*"behind",*/ nullptr); break; case CLASS_SHAMAN: if (tab == 0) - engine->addStrategies("caster", "caster aoe", "bmana", nullptr); + engine->addStrategiesNoInit("caster", "caster aoe", "bmana", nullptr); else if (tab == 2) - engine->addStrategies("heal", "bmana", nullptr); + engine->addStrategiesNoInit("heal", "bmana", nullptr); else - engine->addStrategies("melee", "melee aoe", "bdps", nullptr); + engine->addStrategiesNoInit("melee", "melee aoe", "bdps", nullptr); - engine->addStrategies("dps assist", "cure", "totems", nullptr); + engine->addStrategiesNoInit("dps assist", "cure", "totems", nullptr); break; case CLASS_PALADIN: if (tab == 1) - engine->addStrategies("tank", "tank assist", "bthreat", "barmor", "cure", nullptr); + engine->addStrategiesNoInit("tank", "tank assist", "bthreat", "barmor", "cure", nullptr); else if (tab == 0) - engine->addStrategies("heal", "dps assist", "cure", "bcast", nullptr); + engine->addStrategiesNoInit("heal", "dps assist", "cure", "bcast", nullptr); else - engine->addStrategies("dps", "dps assist", "cure", "baoe", nullptr); + engine->addStrategiesNoInit("dps", "dps assist", "cure", "baoe", nullptr); break; case CLASS_DRUID: if (tab == 0) { - engine->addStrategies("caster", "cure", "caster aoe", "dps assist", nullptr); - engine->addStrategy("caster debuff"); + engine->addStrategiesNoInit("caster", "cure", "caster aoe", "dps assist", nullptr); + engine->addStrategy("caster debuff", false); } else if (tab == 2) - engine->addStrategies("heal", "cure", "dps assist", nullptr); + engine->addStrategiesNoInit("heal", "cure", "dps assist", nullptr); else { if (player->GetLevel() >= 20 && !player->HasAura(16931) /*thick hide*/) { - engine->addStrategies("cat", "dps assist", nullptr); + engine->addStrategiesNoInit("cat", "dps assist", nullptr); } else { - engine->addStrategies("bear", "tank assist", nullptr); + engine->addStrategiesNoInit("bear", "tank assist", nullptr); } } break; case CLASS_HUNTER: - engine->addStrategies("dps", "aoe", "bdps", "dps assist", nullptr); - engine->addStrategy("dps debuff"); + engine->addStrategiesNoInit("dps", "aoe", "bdps", "dps assist", nullptr); + engine->addStrategy("dps debuff", false); break; case CLASS_ROGUE: if (tab == ROGUE_TAB_ASSASSINATION) { - engine->addStrategies("melee", "dps assist", "aoe", /*"behind",*/ nullptr); + engine->addStrategiesNoInit("melee", "dps assist", "aoe", /*"behind",*/ nullptr); } else { - engine->addStrategies("dps", "dps assist", "aoe", /*"behind",*/ nullptr); + engine->addStrategiesNoInit("dps", "dps assist", "aoe", /*"behind",*/ nullptr); } break; case CLASS_WARLOCK: - engine->addStrategies("dps assist", "dps", "dps debuff", "aoe", nullptr); + engine->addStrategiesNoInit("dps assist", "dps", "dps debuff", "aoe", nullptr); break; case CLASS_DEATH_KNIGHT: if (tab == 0) - engine->addStrategies("blood", "tank assist", nullptr); + engine->addStrategiesNoInit("blood", "tank assist", nullptr); else if (tab == 1) - engine->addStrategies("frost", "frost aoe", "dps assist", nullptr); + engine->addStrategiesNoInit("frost", "frost aoe", "dps assist", nullptr); else - engine->addStrategies("unholy", "unholy aoe", "dps assist", nullptr); + engine->addStrategiesNoInit("unholy", "unholy aoe", "dps assist", nullptr); break; } @@ -395,9 +395,9 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa if (!player->GetGroup()) { // change for heal spec - engine->addStrategy("boost"); - engine->addStrategy("dps assist"); - engine->removeStrategy("threat"); + engine->addStrategy("boost", false); + engine->addStrategy("dps assist", false); + engine->removeStrategy("threat", false); // engine- switch (player->getClass()) { @@ -405,7 +405,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa { if (tab != PRIEST_TAB_SHADOW) { - engine->addStrategies("holy dps", "shadow debuff", "shadow aoe", nullptr); + engine->addStrategiesNoInit("holy dps", "shadow debuff", "shadow aoe", nullptr); } break; } @@ -413,8 +413,8 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa { if (tab == DRUID_TAB_RESTORATION) { - engine->addStrategies("caster", "caster aoe", nullptr); - engine->addStrategy("caster debuff"); + engine->addStrategiesNoInit("caster", "caster aoe", nullptr); + engine->addStrategy("caster debuff", false); } break; } @@ -422,7 +422,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa { if (tab == SHAMAN_TAB_RESTORATION) { - engine->addStrategies("caster", "caster aoe", "bmana", nullptr); + engine->addStrategiesNoInit("caster", "caster aoe", "bmana", nullptr); } break; } @@ -430,7 +430,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa { if (tab == PALADIN_TAB_HOLY) { - engine->addStrategies("dps", "dps assist", "baoe", nullptr); + engine->addStrategiesNoInit("dps", "dps assist", "baoe", nullptr); } break; } @@ -452,40 +452,40 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa bgType = player->GetBattleground()->GetBgTypeID(true); if (bgType == BATTLEGROUND_WS) - engine->addStrategy("warsong"); + engine->addStrategy("warsong", false); if (bgType == BATTLEGROUND_AB) - engine->addStrategy("arathi"); + engine->addStrategy("arathi", false); if (bgType == BATTLEGROUND_AV) - engine->addStrategy("alterac"); + engine->addStrategy("alterac", false); if (bgType == BATTLEGROUND_EY) - engine->addStrategy("eye"); + engine->addStrategy("eye", false); if (bgType == BATTLEGROUND_IC) - engine->addStrategy("isle"); + engine->addStrategy("isle", false); if (player->InArena()) { - engine->addStrategy("arena"); + engine->addStrategy("arena", false); } - engine->addStrategies("boost", "racials", "chat", "default", "aoe", "potions", "cast time", "dps assist", + engine->addStrategiesNoInit("boost", "racials", "chat", "default", "aoe", "potions", "cast time", "dps assist", nullptr); - engine->removeStrategy("custom::say"); - engine->removeStrategy("flee"); - engine->removeStrategy("threat"); - engine->addStrategy("boost"); + engine->removeStrategy("custom::say", false); + engine->removeStrategy("flee", false); + engine->removeStrategy("threat", false); + engine->addStrategy("boost", false); if ((player->getClass() == CLASS_DRUID && tab == 2) || (player->getClass() == CLASS_SHAMAN && tab == 2)) - engine->addStrategies("caster", "caster aoe", nullptr); + engine->addStrategiesNoInit("caster", "caster aoe", nullptr); if (player->getClass() == CLASS_DRUID && tab == 1) - engine->addStrategies(/*"behind",*/ "dps", nullptr); + engine->addStrategiesNoInit(/*"behind",*/ "dps", nullptr); if (player->getClass() == CLASS_ROGUE) - engine->addStrategies(/*"behind",*/ "stealth", nullptr); + engine->addStrategiesNoInit(/*"behind",*/ "stealth", nullptr); } } @@ -493,6 +493,7 @@ Engine* AiFactory::createCombatEngine(Player* player, PlayerbotAI* const facade, { Engine* engine = new Engine(facade, aiObjectContext); AddDefaultCombatStrategies(player, facade, engine); + engine->Init(); return engine; } @@ -503,103 +504,103 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const switch (player->getClass()) { case CLASS_PRIEST: - nonCombatEngine->addStrategies("dps assist", "cure", nullptr); + nonCombatEngine->addStrategiesNoInit("dps assist", "cure", nullptr); break; case CLASS_PALADIN: if (tab == 1) { - nonCombatEngine->addStrategies("bthreat", "tank assist", "barmor", nullptr); + nonCombatEngine->addStrategiesNoInit("bthreat", "tank assist", "barmor", nullptr); if (player->GetLevel() >= 20) { - nonCombatEngine->addStrategy("bstats"); + nonCombatEngine->addStrategy("bstats", false); } else { - nonCombatEngine->addStrategy("bdps"); + nonCombatEngine->addStrategy("bdps", false); } } else if (tab == 0) - nonCombatEngine->addStrategies("dps assist", "bmana", "bcast", nullptr); + nonCombatEngine->addStrategiesNoInit("dps assist", "bmana", "bcast", nullptr); else - nonCombatEngine->addStrategies("dps assist", "bdps", "baoe", nullptr); + nonCombatEngine->addStrategiesNoInit("dps assist", "bdps", "baoe", nullptr); - nonCombatEngine->addStrategies("cure", nullptr); + nonCombatEngine->addStrategiesNoInit("cure", nullptr); break; case CLASS_HUNTER: - nonCombatEngine->addStrategies("bdps", "dps assist", "pet", nullptr); + nonCombatEngine->addStrategiesNoInit("bdps", "dps assist", "pet", nullptr); break; case CLASS_SHAMAN: if (tab == 0 || tab == 2) - nonCombatEngine->addStrategy("bmana"); + nonCombatEngine->addStrategy("bmana", false); else - nonCombatEngine->addStrategy("bdps"); + nonCombatEngine->addStrategy("bdps", false); - nonCombatEngine->addStrategies("dps assist", "cure", nullptr); + nonCombatEngine->addStrategiesNoInit("dps assist", "cure", nullptr); break; case CLASS_MAGE: if (tab == MAGE_TAB_ARCANE || tab == MAGE_TAB_FIRE) - nonCombatEngine->addStrategy("bdps"); + nonCombatEngine->addStrategy("bdps", false); else - nonCombatEngine->addStrategy("bmana"); + nonCombatEngine->addStrategy("bmana", false); - nonCombatEngine->addStrategies("dps assist", "cure", nullptr); + nonCombatEngine->addStrategiesNoInit("dps assist", "cure", nullptr); break; case CLASS_DRUID: if (tab == 1) { if (player->GetLevel() >= 20 && !player->HasAura(16931) /*thick hide*/) { - nonCombatEngine->addStrategy("dps assist"); + nonCombatEngine->addStrategy("dps assist", false); } else { - nonCombatEngine->addStrategy("tank assist"); + nonCombatEngine->addStrategy("tank assist", false); } } else - nonCombatEngine->addStrategies("dps assist", "cure", nullptr); + nonCombatEngine->addStrategiesNoInit("dps assist", "cure", nullptr); break; case CLASS_WARRIOR: if (tab == 2) - nonCombatEngine->addStrategy("tank assist"); + nonCombatEngine->addStrategy("tank assist", false); else - nonCombatEngine->addStrategy("dps assist"); + nonCombatEngine->addStrategy("dps assist", false); break; case CLASS_WARLOCK: if (tab == WARLOCK_TAB_AFFLICATION) { - nonCombatEngine->addStrategies("bmana", nullptr); + nonCombatEngine->addStrategiesNoInit("bmana", nullptr); } else if (tab == WARLOCK_TAB_DEMONOLOGY) { - nonCombatEngine->addStrategies("bdps", nullptr); + nonCombatEngine->addStrategiesNoInit("bdps", nullptr); } else if (tab == WARLOCK_TAB_DESTRUCTION) { - nonCombatEngine->addStrategies("bhealth", nullptr); + nonCombatEngine->addStrategiesNoInit("bhealth", nullptr); } - nonCombatEngine->addStrategies("dps assist", nullptr); + nonCombatEngine->addStrategiesNoInit("dps assist", nullptr); break; case CLASS_DEATH_KNIGHT: if (tab == 0) - nonCombatEngine->addStrategy("tank assist"); + nonCombatEngine->addStrategy("tank assist", false); else - nonCombatEngine->addStrategy("dps assist"); + nonCombatEngine->addStrategy("dps assist", false); break; default: - nonCombatEngine->addStrategy("dps assist"); + nonCombatEngine->addStrategy("dps assist", false); break; } if (!player->InBattleground()) { - nonCombatEngine->addStrategies("nc", "food", "chat", "follow", "default", "quest", "loot", "gather", "duel", + nonCombatEngine->addStrategiesNoInit("nc", "food", "chat", "follow", "default", "quest", "loot", "gather", "duel", "buff", "mount", "emote", nullptr); } if (sPlayerbotAIConfig->autoSaveMana) { - nonCombatEngine->addStrategy("auto save mana"); + nonCombatEngine->addStrategy("smana", false); } if ((sRandomPlayerbotMgr->IsRandomBot(player)) && !player->InBattleground()) { @@ -607,10 +608,10 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const // let 25% of free bots start duels. if (!urand(0, 3)) - nonCombatEngine->addStrategy("start duel"); + nonCombatEngine->addStrategy("start duel", false); if (sPlayerbotAIConfig->randomBotJoinLfg) - nonCombatEngine->addStrategy("lfg"); + nonCombatEngine->addStrategy("lfg", false); if (!player->GetGroup() || player->GetGroup()->GetLeaderGUID() == player->GetGUID()) { @@ -618,24 +619,24 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const // if (!urand(0, 3)) // nonCombatEngine->addStrategy("attack tagged"); - nonCombatEngine->addStrategy("pvp"); + nonCombatEngine->addStrategy("pvp", false); // nonCombatEngine->addStrategy("collision"); - nonCombatEngine->addStrategy("grind"); + nonCombatEngine->addStrategy("grind", false); // nonCombatEngine->addStrategy("group"); // nonCombatEngine->addStrategy("guild"); if (sPlayerbotAIConfig->autoDoQuests) { // nonCombatEngine->addStrategy("travel"); - nonCombatEngine->addStrategy("rpg"); + nonCombatEngine->addStrategy("rpg", false); } else { - nonCombatEngine->addStrategy("move random"); + nonCombatEngine->addStrategy("move random", false); } if (sPlayerbotAIConfig->randomBotJoinBG) - nonCombatEngine->addStrategy("bg"); + nonCombatEngine->addStrategy("bg", false); // if (!master || GET_PLAYERBOT_AI(master)) // nonCombatEngine->addStrategy("maintenance"); @@ -651,7 +652,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const PlayerbotAI* masterBotAI = GET_PLAYERBOT_AI(master); if (masterBotAI || sRandomPlayerbotMgr->IsRandomBot(player)) { - nonCombatEngine->addStrategy("pvp"); + nonCombatEngine->addStrategy("pvp", false); // nonCombatEngine->addStrategy("collision"); // nonCombatEngine->addStrategy("group"); // nonCombatEngine->addStrategy("guild"); @@ -671,7 +672,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const } else { - nonCombatEngine->addStrategy("pvp"); + nonCombatEngine->addStrategy("pvp", false); nonCombatEngine->ChangeStrategy(sPlayerbotAIConfig->nonCombatStrategies); } } @@ -687,12 +688,12 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const // Battleground switch if (player->InBattleground() && player->GetBattleground()) { - nonCombatEngine->addStrategies("nc", "chat", "default", "buff", "food", "mount", "pvp", "dps assist", + nonCombatEngine->addStrategiesNoInit("nc", "chat", "default", "buff", "food", "mount", "pvp", "dps assist", "attack tagged", "emote", nullptr); - nonCombatEngine->removeStrategy("custom::say"); - nonCombatEngine->removeStrategy("travel"); - nonCombatEngine->removeStrategy("rpg"); - nonCombatEngine->removeStrategy("grind"); + nonCombatEngine->removeStrategy("custom::say", false); + nonCombatEngine->removeStrategy("travel", false); + nonCombatEngine->removeStrategy("rpg", false); + nonCombatEngine->removeStrategy("grind", false); BattlegroundTypeId bgType = player->GetBattlegroundTypeId(); if (bgType == BATTLEGROUND_RB) @@ -700,27 +701,27 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const if ((bgType <= BATTLEGROUND_EY || bgType == BATTLEGROUND_IC) && !player->InArena()) // do not add for not supported bg or arena - nonCombatEngine->addStrategy("battleground"); + nonCombatEngine->addStrategy("battleground", false); if (bgType == BATTLEGROUND_WS) - nonCombatEngine->addStrategy("warsong"); + nonCombatEngine->addStrategy("warsong", false); if (bgType == BATTLEGROUND_AV) - nonCombatEngine->addStrategy("alterac"); + nonCombatEngine->addStrategy("alterac", false); if (bgType == BATTLEGROUND_AB) - nonCombatEngine->addStrategy("arathi"); + nonCombatEngine->addStrategy("arathi", false); if (bgType == BATTLEGROUND_EY) - nonCombatEngine->addStrategy("eye"); + nonCombatEngine->addStrategy("eye", false); if (bgType == BATTLEGROUND_IC) - nonCombatEngine->addStrategy("isle"); + nonCombatEngine->addStrategy("isle", false); if (player->InArena()) { - nonCombatEngine->addStrategy("arena"); - nonCombatEngine->removeStrategy("mount"); + nonCombatEngine->addStrategy("arena", false); + nonCombatEngine->removeStrategy("mount", false); } } } @@ -730,17 +731,18 @@ Engine* AiFactory::createNonCombatEngine(Player* player, PlayerbotAI* const faca Engine* nonCombatEngine = new Engine(facade, aiObjectContext); AddDefaultNonCombatStrategies(player, facade, nonCombatEngine); + nonCombatEngine->Init(); return nonCombatEngine; } void AiFactory::AddDefaultDeadStrategies(Player* player, PlayerbotAI* const facade, Engine* deadEngine) { (void)facade; // unused and remove warning - deadEngine->addStrategies("dead", "stay", "chat", "default", "follow", nullptr); + deadEngine->addStrategiesNoInit("dead", "stay", "chat", "default", "follow", nullptr); if (sRandomPlayerbotMgr->IsRandomBot(player) && !player->GetGroup()) { - deadEngine->removeStrategy("follow"); + deadEngine->removeStrategy("follow", false); } } @@ -748,5 +750,6 @@ Engine* AiFactory::createDeadEngine(Player* player, PlayerbotAI* const facade, A { Engine* deadEngine = new Engine(facade, AiObjectContext); AddDefaultDeadStrategies(player, facade, deadEngine); + deadEngine->Init(); return deadEngine; } diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 0948a5da..c5a4a375 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -342,16 +342,7 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal) bool min = minimal; UpdateAIInternal(elapsed, min); - inCombat = bot->IsInCombat(); - // test fix lags because of BG - bool inBG = bot->InBattleground() || bot->InArena(); - if (bot && !inCombat) - min = true; - - if (HasRealPlayerMaster() || (sPlayerbotAIConfig->fastReactInBG && inBG)) - min = false; - - YieldThread(min); + YieldThread(GetReactDelay()); } void PlayerbotAI::UpdateAIInternal([[maybe_unused]] uint32 elapsed, bool minimal) @@ -940,6 +931,7 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet) if (!AllowActivity()) return; + WorldPacket p(packet); if (!p.empty() && (p.GetOpcode() == SMSG_MESSAGECHAT || p.GetOpcode() == SMSG_GM_MESSAGECHAT)) { @@ -1584,6 +1576,9 @@ void PlayerbotAI::ResetStrategies(bool load) AiFactory::AddDefaultNonCombatStrategies(bot, this, engines[BOT_STATE_NON_COMBAT]); AiFactory::AddDefaultDeadStrategies(bot, this, engines[BOT_STATE_DEAD]); + for (uint8 i = 0; i < BOT_STATE_MAX; i++) + engines[i]->Init(); + // if (load) // sPlayerbotDbStore->Load(this); } @@ -2748,7 +2743,8 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, } uint32 CastingTime = !spellInfo->IsChanneled() ? spellInfo->CalcCastTime(bot) : spellInfo->GetDuration(); - if (CastingTime && bot->isMoving()) + bool interruptOnMove = spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT; + if ((CastingTime || interruptOnMove) && bot->isMoving()) { if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { @@ -4795,7 +4791,8 @@ Item* PlayerbotAI::FindOilFor(Item* weapon) const { for (const auto& id : uPriorizedWizardOilIds) { - if (oil = FindConsumable(id)) + oil = FindConsumable(id); + if (oil) return oil; } } @@ -4804,7 +4801,8 @@ Item* PlayerbotAI::FindOilFor(Item* weapon) const { for (const auto& id : uPriorizedManaOilIds) { - if (oil = FindConsumable(id)) + oil = FindConsumable(id); + if (oil) return oil; } } @@ -5691,3 +5689,56 @@ std::set PlayerbotAI::GetCurrentIncompleteQuestIds() return result; } +uint32 PlayerbotAI::GetReactDelay() +{ + uint32 base = sPlayerbotAIConfig->reactDelay; + // old calculate method + if (!sPlayerbotAIConfig->dynamicReactDelay) + { + inCombat = bot->IsInCombat(); + bool min = false; + // test fix lags because of BG + bool inBG = bot->InBattleground() || bot->InArena(); + if (bot && !inCombat) + min = true; + + if (HasRealPlayerMaster() || (sPlayerbotAIConfig->fastReactInBG && inBG)) + min = false; + if (min) + return base * 10; + + return base; + } + + float multiplier = 1.0f; + + if (HasRealPlayerMaster()) + { + multiplier = 1.0f; + return base * multiplier; + } + + bool inBg = bot->InBattleground() || bot->InArena(); + if (inBg) + { + multiplier = sPlayerbotAIConfig->fastReactInBG ? 1.0f : 10.0f; + return base * multiplier; + } + + if (bot->IsInCombat() || currentState == BOT_STATE_COMBAT) + { + multiplier = 5.0f; + return base * multiplier; + } + + bool isResting = bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); + if (!isResting) + { + multiplier = urand(5, 20); + return base * multiplier; + } + + multiplier = urand(20, 200); + return base * multiplier; +} + diff --git a/src/PlayerbotAI.h b/src/PlayerbotAI.h index f0be101f..f9edd7ff 100644 --- a/src/PlayerbotAI.h +++ b/src/PlayerbotAI.h @@ -554,6 +554,7 @@ public: uint32 GetInventoryItemsCountWithId(uint32 itemId); bool HasItemInInventory(uint32 itemId); std::vector> GetCurrentQuestsRequiringItemId(uint32 itemId); + uint32 GetReactDelay(); std::vector GetAllCurrentQuests(); std::vector GetCurrentIncompleteQuests(); diff --git a/src/PlayerbotAIBase.cpp b/src/PlayerbotAIBase.cpp index b26a3e64..37cc9ebd 100644 --- a/src/PlayerbotAIBase.cpp +++ b/src/PlayerbotAIBase.cpp @@ -49,10 +49,10 @@ void PlayerbotAIBase::IncreaseNextCheckDelay(uint32 delay) bool PlayerbotAIBase::CanUpdateAI() { return nextAICheckDelay == 0; } -void PlayerbotAIBase::YieldThread(bool delay) +void PlayerbotAIBase::YieldThread(uint32 delay) { - if (nextAICheckDelay < sPlayerbotAIConfig->reactDelay) - nextAICheckDelay = delay ? sPlayerbotAIConfig->reactDelay * 10 : sPlayerbotAIConfig->reactDelay; + if (nextAICheckDelay < delay) + nextAICheckDelay = delay; } bool PlayerbotAIBase::IsActive() { return nextAICheckDelay < sPlayerbotAIConfig->maxWaitForMove; } diff --git a/src/PlayerbotAIBase.h b/src/PlayerbotAIBase.h index a1322211..6c1772e2 100644 --- a/src/PlayerbotAIBase.h +++ b/src/PlayerbotAIBase.h @@ -7,6 +7,7 @@ #define _PLAYERBOT_PLAYERBOTAIBASE_H #include "Define.h" +#include "PlayerbotAIConfig.h" class PlayerbotAIBase { @@ -16,7 +17,7 @@ public: bool CanUpdateAI(); void SetNextCheckDelay(uint32 const delay); void IncreaseNextCheckDelay(uint32 delay); - void YieldThread(bool delay = false); + void YieldThread(uint32 delay = sPlayerbotAIConfig->reactDelay); virtual void UpdateAI(uint32 elapsed, bool minimal = false); virtual void UpdateAIInternal(uint32 elapsed, bool minimal = false) = 0; bool IsActive(); diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 3782735e..7803fafb 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -59,7 +59,8 @@ bool PlayerbotAIConfig::Initialize() maxMovementSearchTime = sConfigMgr->GetOption("AiPlayerbot.MaxMovementSearchTime", 3); expireActionTime = sConfigMgr->GetOption("AiPlayerbot.ExpireActionTime", 5000); dispelAuraDuration = sConfigMgr->GetOption("AiPlayerbot.DispelAuraDuration", 7000); - reactDelay = sConfigMgr->GetOption("AiPlayerbot.ReactDelay", 500); + reactDelay = sConfigMgr->GetOption("AiPlayerbot.ReactDelay", 100); + dynamicReactDelay = sConfigMgr->GetOption("AiPlayerbot.DynamicReactDelay", true); passiveDelay = sConfigMgr->GetOption("AiPlayerbot.PassiveDelay", 10000); repeatDelay = sConfigMgr->GetOption("AiPlayerbot.RepeatDelay", 2000); errorDelay = sConfigMgr->GetOption("AiPlayerbot.ErrorDelay", 5000); @@ -77,7 +78,7 @@ bool PlayerbotAIConfig::Initialize() fleeDistance = sConfigMgr->GetOption("AiPlayerbot.FleeDistance", 7.5f); aggroDistance = sConfigMgr->GetOption("AiPlayerbot.AggroDistance", 22.0f); tooCloseDistance = sConfigMgr->GetOption("AiPlayerbot.TooCloseDistance", 5.0f); - meleeDistance = sConfigMgr->GetOption("AiPlayerbot.MeleeDistance", 1.5f); + meleeDistance = sConfigMgr->GetOption("AiPlayerbot.MeleeDistance", 0.75f); followDistance = sConfigMgr->GetOption("AiPlayerbot.FollowDistance", 1.5f); whisperDistance = sConfigMgr->GetOption("AiPlayerbot.WhisperDistance", 6000.0f); contactDistance = sConfigMgr->GetOption("AiPlayerbot.ContactDistance", 0.5f); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 11d45965..e7fd94cd 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -58,6 +58,7 @@ public: bool randomBotGuildNearby, randomBotInvitePlayer, inviteChat; uint32 globalCoolDown, reactDelay, maxWaitForMove, disableMoveSplinePath, maxMovementSearchTime, expireActionTime, dispelAuraDuration, passiveDelay, repeatDelay, errorDelay, rpgDelay, sitDelay, returnDelay, lootDelay; + bool dynamicReactDelay; float sightDistance, spellDistance, reactDistance, grindDistance, lootDistance, shootDistance, fleeDistance, tooCloseDistance, meleeDistance, followDistance, whisperDistance, contactDistance, aoeRadius, rpgDistance, targetPosRecalcDistance, farDistance, healDistance, aggroDistance; diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index cc806663..564403d2 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -29,6 +29,7 @@ #include "LFGMgr.h" #include "MapMgr.h" #include "PerformanceMonitor.h" +#include "PlayerbotAI.h" #include "PlayerbotAIConfig.h" #include "PlayerbotCommandServer.h" #include "PlayerbotFactory.h" @@ -2333,6 +2334,11 @@ void RandomPlayerbotMgr::PrintStats() uint32 taxi = 0; uint32 moving = 0; uint32 mounted = 0; + uint32 inBg = 0; + uint32 rest = 0; + uint32 engine_noncombat = 0; + uint32 engine_combat = 0; + uint32 engine_dead = 0; uint32 stateCount[MAX_TRAVEL_STATE + 1] = {0}; std::vector> questCount; for (PlayerBotMap::iterator i = playerBots.begin(); i != playerBots.end(); ++i) @@ -2369,7 +2375,33 @@ void RandomPlayerbotMgr::PrintStats() // if (!GetEventValue(botId, "dead")) //++revive; } - + if (bot->IsInCombat()) + { + ++combat; + } + if (bot->isMoving()) + { + ++moving; + } + if (bot->IsMounted()) + { + ++mounted; + } + if (bot->InBattleground() || bot->InArena()) + { + ++inBg; + } + if (bot->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING)) + { + ++rest; + } + if (botAI->GetState() == BOT_STATE_NON_COMBAT) + ++engine_noncombat; + else if (botAI->GetState() == BOT_STATE_COMBAT) + ++engine_combat; + else + ++engine_dead; + uint8 spec = AiFactory::GetPlayerSpecTab(bot); switch (bot->getClass()) { @@ -2490,8 +2522,15 @@ void RandomPlayerbotMgr::PrintStats() LOG_INFO("playerbots", " On taxi: {}", taxi); LOG_INFO("playerbots", " On mount: {}", mounted); LOG_INFO("playerbots", " In combat: {}", combat); + LOG_INFO("playerbots", " In BG: {}", inBg); + LOG_INFO("playerbots", " In Rest: {}", rest); LOG_INFO("playerbots", " Dead: {}", dead); + LOG_INFO("playerbots", "Bots engine:", dead); + LOG_INFO("playerbots", " Non-combat: {}", engine_noncombat); + LOG_INFO("playerbots", " Combat: {}", engine_combat); + LOG_INFO("playerbots", " Dead: {}", engine_dead); + LOG_INFO("playerbots", "Bots questing:"); LOG_INFO("playerbots", " Picking quests: {}", stateCount[TRAVEL_STATE_TRAVEL_PICK_UP_QUEST] + stateCount[TRAVEL_STATE_WORK_PICK_UP_QUEST]); @@ -2746,3 +2785,4 @@ ObjectGuid const RandomPlayerbotMgr::GetBattleMasterGUID(Player* bot, Battlegrou return battleMasterGUID; } + diff --git a/src/factory/PlayerbotFactory.cpp b/src/factory/PlayerbotFactory.cpp index 78744c50..9f87bc74 100644 --- a/src/factory/PlayerbotFactory.cpp +++ b/src/factory/PlayerbotFactory.cpp @@ -412,10 +412,10 @@ void PlayerbotFactory::Randomize(bool incremental) void PlayerbotFactory::Refresh() { // Prepare(); - if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) - { - InitEquipment(true); - } + // if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) + // { + // InitEquipment(true); + // } ClearInventory(); InitAmmo(); InitFood(); diff --git a/src/strategy/Engine.cpp b/src/strategy/Engine.cpp index a4e3845d..d298aaf5 100644 --- a/src/strategy/Engine.cpp +++ b/src/strategy/Engine.cpp @@ -409,26 +409,26 @@ ActionResult Engine::ExecuteAction(std::string const name, Event event, std::str return result ? ACTION_RESULT_OK : ACTION_RESULT_FAILED; } -void Engine::addStrategy(std::string const name) +void Engine::addStrategy(std::string const name, bool init) { - removeStrategy(name); + removeStrategy(name, init); if (Strategy* strategy = aiObjectContext->GetStrategy(name)) { std::set siblings = aiObjectContext->GetSiblingStrategy(name); for (std::set::iterator i = siblings.begin(); i != siblings.end(); i++) - removeStrategy(*i); + removeStrategy(*i, init); LogAction("S:+%s", strategy->getName().c_str()); strategies[strategy->getName()] = strategy; } - - Init(); + if (init) + Init(); } void Engine::addStrategies(std::string first, ...) { - addStrategy(first); + addStrategy(first, false); va_list vl; va_start(vl, first); @@ -438,13 +438,34 @@ void Engine::addStrategies(std::string first, ...) { cur = va_arg(vl, const char*); if (cur) - addStrategy(cur); + addStrategy(cur, false); + } while (cur); + + Init(); + + va_end(vl); +} + +void Engine::addStrategiesNoInit(std::string first, ...) +{ + addStrategy(first, false); + + va_list vl; + va_start(vl, first); + + const char* cur; + do + { + cur = va_arg(vl, const char*); + if (cur) + addStrategy(cur, false); } while (cur); va_end(vl); } -bool Engine::removeStrategy(std::string const name) + +bool Engine::removeStrategy(std::string const name, bool init) { std::map::iterator i = strategies.find(name); if (i == strategies.end()) @@ -452,7 +473,8 @@ bool Engine::removeStrategy(std::string const name) LogAction("S:-%s", name.c_str()); strategies.erase(i); - Init(); + if (init) + Init(); return true; } diff --git a/src/strategy/Engine.h b/src/strategy/Engine.h index bd51c16b..c3a5d743 100644 --- a/src/strategy/Engine.h +++ b/src/strategy/Engine.h @@ -65,9 +65,10 @@ public: Engine(PlayerbotAI* botAI, AiObjectContext* factory); void Init(); - void addStrategy(std::string const name); + void addStrategy(std::string const name, bool init = true); void addStrategies(std::string first, ...); - bool removeStrategy(std::string const name); + void addStrategiesNoInit(std::string first, ...); + bool removeStrategy(std::string const name, bool init = true); bool HasStrategy(std::string const name); void removeAllStrategies(); void toggleStrategy(std::string const name); diff --git a/src/strategy/StrategyContext.h b/src/strategy/StrategyContext.h index 9c694364..0a2501bb 100644 --- a/src/strategy/StrategyContext.h +++ b/src/strategy/StrategyContext.h @@ -60,7 +60,7 @@ public: creators["emote"] = &StrategyContext::emote; creators["passive"] = &StrategyContext::passive; // creators["conserve mana"] = &StrategyContext::conserve_mana; - creators["auto save mana"] = &StrategyContext::auto_save_mana; + creators["smana"] = &StrategyContext::auto_save_mana; creators["food"] = &StrategyContext::food; creators["chat"] = &StrategyContext::chat; creators["default"] = &StrategyContext::world_packet; @@ -112,9 +112,9 @@ public: creators["group"] = &StrategyContext::group; creators["guild"] = &StrategyContext::guild; creators["grind"] = &StrategyContext::grind; - creators["avoid aoe"] = &StrategyContext::avoid_aoe; + creators["aaoe"] = &StrategyContext::avoid_aoe; creators["move random"] = &StrategyContext::move_random; - creators["combat formation"] = &StrategyContext::combat_formation; + creators["formation"] = &StrategyContext::combat_formation; } private: diff --git a/src/strategy/actions/ActionContext.h b/src/strategy/actions/ActionContext.h index 724c35f2..87c4e9e1 100644 --- a/src/strategy/actions/ActionContext.h +++ b/src/strategy/actions/ActionContext.h @@ -92,7 +92,7 @@ public: creators["reach party member to resurrect"] = &ActionContext::reach_party_member_to_resurrect; creators["flee"] = &ActionContext::flee; creators["flee with pet"] = &ActionContext::flee_with_pet; - creators["avoid aoe"] = &ActionContext::avoid_aoe; + creators["aaoe"] = &ActionContext::avoid_aoe; creators["combat formation move"] = &ActionContext::combat_formation_move; creators["disperse set"] = &ActionContext::disperse_set; creators["gift of the naaru"] = &ActionContext::gift_of_the_naaru; @@ -158,10 +158,8 @@ public: creators["berserking"] = &ActionContext::berserking; creators["use trinket"] = &ActionContext::use_trinket; creators["auto talents"] = &ActionContext::auto_talents; - creators["auto learn spell"] = &ActionContext::auto_learn_spell; creators["auto share quest"] = &ActionContext::auto_share_quest; - creators["auto teleport for level"] = &ActionContext::auto_teleport_for_level; - creators["auto upgrade equip"] = &ActionContext::auto_upgrade_equip; + creators["auto maintenance on levelup"] = &ActionContext::auto_maintenance_on_levelup; creators["xp gain"] = &ActionContext::xp_gain; creators["invite nearby"] = &ActionContext::invite_nearby; creators["invite guild"] = &ActionContext::invite_guild; @@ -331,10 +329,8 @@ private: static Action* berserking(PlayerbotAI* botAI) { return new CastBerserkingAction(botAI); } static Action* use_trinket(PlayerbotAI* botAI) { return new UseTrinketAction(botAI); } static Action* auto_talents(PlayerbotAI* botAI) { return new AutoSetTalentsAction(botAI); } - static Action* auto_learn_spell(PlayerbotAI* botAI) { return new AutoLearnSpellAction(botAI); } static Action* auto_share_quest(PlayerbotAI* ai) { return new AutoShareQuestAction(ai); } - static Action* auto_teleport_for_level(PlayerbotAI* botAI) { return new AutoTeleportForLevelAction(botAI); } - static Action* auto_upgrade_equip(PlayerbotAI* botAI) { return new AutoUpgradeEquipAction(botAI); } + static Action* auto_maintenance_on_levelup(PlayerbotAI* botAI) { return new AutoMaintenanceOnLevelupAction(botAI); } static Action* xp_gain(PlayerbotAI* botAI) { return new XpGainAction(botAI); } static Action* invite_nearby(PlayerbotAI* botAI) { return new InviteNearbyToGroupAction(botAI); } static Action* invite_guild(PlayerbotAI* botAI) { return new InviteGuildToGroupAction(botAI); } diff --git a/src/strategy/generic/CombatStrategy.cpp b/src/strategy/generic/CombatStrategy.cpp index 92bb27f8..9d2d9932 100644 --- a/src/strategy/generic/CombatStrategy.cpp +++ b/src/strategy/generic/CombatStrategy.cpp @@ -70,7 +70,7 @@ AvoidAoeStrategy::AvoidAoeStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} NextAction** AvoidAoeStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("avoid aoe", ACTION_EMERGENCY), nullptr); + return NextAction::array(0, new NextAction("aaoe", ACTION_EMERGENCY), nullptr); } void AvoidAoeStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/generic/CombatStrategy.h b/src/strategy/generic/CombatStrategy.h index 422b4b22..e96a3eaf 100644 --- a/src/strategy/generic/CombatStrategy.h +++ b/src/strategy/generic/CombatStrategy.h @@ -23,7 +23,7 @@ class AvoidAoeStrategy : public Strategy { public: explicit AvoidAoeStrategy(PlayerbotAI* ai); - const std::string getName() override { return "avoid aoe"; } + const std::string getName() override { return "aaoe"; } NextAction** getDefaultActions() override; void InitMultipliers(std::vector& multipliers) override; void InitTriggers(std::vector& triggers) override; @@ -33,7 +33,7 @@ class CombatFormationStrategy : public Strategy { public: CombatFormationStrategy(PlayerbotAI* ai) : Strategy(ai) {} - const std::string getName() override { return "combat formation"; } + const std::string getName() override { return "formation"; } NextAction** getDefaultActions() override; }; diff --git a/src/strategy/generic/ConserveManaStrategy.h b/src/strategy/generic/ConserveManaStrategy.h index 4af44222..d63daae6 100644 --- a/src/strategy/generic/ConserveManaStrategy.h +++ b/src/strategy/generic/ConserveManaStrategy.h @@ -49,7 +49,7 @@ class PlayerbotAI; class HealerAutoSaveManaMultiplier : public Multiplier { public: - HealerAutoSaveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "auto save mana") {} + HealerAutoSaveManaMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "smana") {} float GetValue(Action* action) override; }; @@ -60,7 +60,7 @@ public: HealerAutoSaveManaStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} void InitMultipliers(std::vector& multipliers) override; - std::string const getName() override { return "auto save mana"; } + std::string const getName() override { return "smana"; } }; #endif