From 762ac0142bab860b0d579d1208db5e9dd99037b8 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 7 Sep 2023 14:18:20 +0800 Subject: [PATCH 1/6] miscs --- src/PlayerbotAIConfig.cpp | 4 +-- src/RandomPlayerbotFactory.cpp | 2 +- src/strategy/deathknight/DKActions.h | 10 +++++-- src/strategy/deathknight/FrostDKStrategy.cpp | 2 +- .../deathknight/GenericDKStrategy.cpp | 28 +++++++++++-------- src/strategy/values/ExpectedLifetimeValue.cpp | 3 +- src/strategy/values/ExpectedLifetimeValue.h | 2 +- .../GenericWarlockNonCombatStrategy.cpp | 2 +- 8 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index f21d0864..0ccf397c 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -162,9 +162,9 @@ bool PlayerbotAIConfig::Initialize() { for (uint32 spec = 0; spec < 3; ++spec) { - std::ostringstream os; os << "AiPlayerbot.RandomClassSpecProbability." << cls << "." << spec; + std::ostringstream os; + os << "AiPlayerbot.RandomClassSpecProbability." << cls << "." << spec; specProbability[cls][spec] = sConfigMgr->GetOption(os.str().c_str(), 33); - os.str(""); os.clear(); os << "AiPlayerbot.DefaultTalentsOrder." << cls << "." << spec; diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index 5284c0f2..063b3089 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -396,7 +396,7 @@ void RandomPlayerbotFactory::CreateRandomBots() } if (bot_creation) { - LOG_INFO("playerbots", "Wait for {} characters load into database...", totalCharCount); + LOG_INFO("playerbots", "Waiting for {} characters load into database...", totalCharCount); /* wait for characters load into database, or characters will fail to loggin */ std::this_thread::sleep_for(15ms * totalCharCount); } diff --git a/src/strategy/deathknight/DKActions.h b/src/strategy/deathknight/DKActions.h index 2457b52e..170bd0a2 100644 --- a/src/strategy/deathknight/DKActions.h +++ b/src/strategy/deathknight/DKActions.h @@ -91,8 +91,14 @@ class CastPestilenceAction : public CastSpellAction //debuff -BEGIN_DEBUFF_ACTION(CastHowlingBlastAction, "howling blast") -END_SPELL_ACTION() +// BEGIN_DEBUFF_ACTION(CastHowlingBlastAction, "howling blast") +// END_SPELL_ACTION() + +class CastHowlingBlastAction : public CastSpellAction +{ + public: + CastHowlingBlastAction(PlayerbotAI* ai) : CastSpellAction(ai, "howling blast") {} +}; //debuff it // BEGIN_DEBUFF_ACTION(CastIcyTouchAction, "icy touch") diff --git a/src/strategy/deathknight/FrostDKStrategy.cpp b/src/strategy/deathknight/FrostDKStrategy.cpp index 2a9ea33d..307801db 100644 --- a/src/strategy/deathknight/FrostDKStrategy.cpp +++ b/src/strategy/deathknight/FrostDKStrategy.cpp @@ -96,5 +96,5 @@ void FrostDKStrategy::InitTriggers(std::vector& triggers) void FrostDKAoeStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("high aoe", NextAction::array(0, new NextAction("howling blast", ACTION_NORMAL + 4), nullptr))); + triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("howling blast", ACTION_NORMAL + 4), nullptr))); } diff --git a/src/strategy/deathknight/GenericDKStrategy.cpp b/src/strategy/deathknight/GenericDKStrategy.cpp index e5286faa..241816eb 100644 --- a/src/strategy/deathknight/GenericDKStrategy.cpp +++ b/src/strategy/deathknight/GenericDKStrategy.cpp @@ -157,26 +157,32 @@ void GenericDKStrategy::InitTriggers(std::vector& triggers) { MeleeCombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("high aoe", NextAction::array(0, new NextAction("anti magic shell", ACTION_NORMAL + 3), nullptr))); + // triggers.push_back(new TriggerNode("high aoe", NextAction::array(0, new NextAction("anti magic shell", ACTION_NORMAL + 3), nullptr))); // triggers.push_back(new TriggerNode("death coil", NextAction::array(0, new NextAction("death coil", ACTION_NORMAL + 3), nullptr))); - triggers.push_back(new TriggerNode("critical aoe heal", NextAction::array(0, new NextAction("anti magic zone", ACTION_EMERGENCY + 1), nullptr))); + // triggers.push_back(new TriggerNode("critical aoe heal", NextAction::array(0, new NextAction("anti magic zone", ACTION_EMERGENCY + 1), nullptr))); triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("raise dead", ACTION_NORMAL + 5), nullptr))); triggers.push_back(new TriggerNode("mind freeze", NextAction::array(0, new NextAction("mind freeze", ACTION_HIGH + 1), nullptr))); + triggers.push_back(new TriggerNode("mind freeze on enemy healer", NextAction::array(0, new NextAction("mind freeze on enemy healer", ACTION_HIGH + 1), nullptr))); triggers.push_back(new TriggerNode("bone shield", NextAction::array(0, new NextAction("bone shield", ACTION_NORMAL + 1), nullptr))); triggers.push_back(new TriggerNode("horn of winter", NextAction::array(0, new NextAction("horn of winter", ACTION_NORMAL + 1), nullptr))); - triggers.push_back(new TriggerNode("mind freeze on enemy healer", NextAction::array(0, new NextAction("mind freeze on enemy healer", ACTION_HIGH + 1), nullptr))); // triggers.push_back(new TriggerNode("enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), nullptr))); triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("icebound fortitude", ACTION_HIGH + 5), new NextAction("rune tap", ACTION_HIGH + 4), nullptr))); triggers.push_back(new TriggerNode("medium health", NextAction::array(0, new NextAction("rune tap", ACTION_NORMAL + 4), new NextAction("death strike", ACTION_NORMAL + 3), nullptr))); - triggers.push_back(new TriggerNode("icy touch", NextAction::array(0, new NextAction("icy touch", ACTION_HIGH + 1), nullptr))); + triggers.push_back(new TriggerNode("icy touch", NextAction::array(0, new NextAction("icy touch", ACTION_HIGH + 2), nullptr))); triggers.push_back(new TriggerNode("icy touch on attacker", NextAction::array(0, new NextAction("icy touch on attacker", ACTION_HIGH + 1), nullptr))); - triggers.push_back(new TriggerNode("plague strike", NextAction::array(0, new NextAction("plague strike", ACTION_HIGH + 1), nullptr))); + triggers.push_back(new TriggerNode("plague strike", NextAction::array(0, new NextAction("plague strike", ACTION_HIGH + 2), nullptr))); triggers.push_back(new TriggerNode("plague strike on attacker", NextAction::array(0, new NextAction("plague strike on attacker", ACTION_HIGH + 1), nullptr))); - triggers.push_back(new TriggerNode("high aoe", NextAction::array(0, new NextAction("unholy blight", ACTION_HIGH + 6), new NextAction("death and decay", ACTION_NORMAL + 5), - new NextAction("pestilence", ACTION_NORMAL + 4), new NextAction("blood boil", ACTION_NORMAL + 3), nullptr))); - triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("death and decay", ACTION_HIGH + 9), - new NextAction("pestilence", ACTION_NORMAL + 4), new NextAction("blood boil", ACTION_NORMAL + 3), nullptr))); - triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("howling blast", ACTION_NORMAL + 5), new NextAction("pestilence", ACTION_NORMAL + 4), - new NextAction("hearth strike", ACTION_NORMAL + 3), new NextAction("blood boil", ACTION_NORMAL + 3), nullptr))); + // triggers.push_back(new TriggerNode("high aoe", + // NextAction::array(0, + // new NextAction("death and decay", ACTION_NORMAL + 5), + // new NextAction("pestilence", ACTION_NORMAL + 4), + // new NextAction("blood boil", ACTION_NORMAL + 3), nullptr))); + triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, + new NextAction("death and decay", ACTION_HIGH + 9), + new NextAction("pestilence", ACTION_NORMAL + 4), + new NextAction("blood boil", ACTION_NORMAL + 3), nullptr))); + // triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, + // new NextAction("pestilence", ACTION_NORMAL + 4), + // nullptr))); triggers.push_back(new TriggerNode("pestilence", NextAction::array(0, new NextAction("pestilence", ACTION_HIGH + 9), NULL))); } diff --git a/src/strategy/values/ExpectedLifetimeValue.cpp b/src/strategy/values/ExpectedLifetimeValue.cpp index 0d4d6352..2e41b10c 100644 --- a/src/strategy/values/ExpectedLifetimeValue.cpp +++ b/src/strategy/values/ExpectedLifetimeValue.cpp @@ -13,6 +13,7 @@ float ExpectedLifetimeValue::Calculate() // bot->Say(target->GetName() + " lifetime: " + std::to_string(res), LANG_UNIVERSAL); return res; } + float ExpectedGroupDpsValue::Calculate() { float dps_num; @@ -37,7 +38,7 @@ float ExpectedGroupDpsValue::Calculate() } else if (bot->GetLevel() < 80) { dps_efficiency = 12; } else { - dps_efficiency = 30; + dps_efficiency = 25; } return dps_num * bot->GetLevel() * dps_efficiency; } \ No newline at end of file diff --git a/src/strategy/values/ExpectedLifetimeValue.h b/src/strategy/values/ExpectedLifetimeValue.h index 5288b859..e9f432f2 100644 --- a/src/strategy/values/ExpectedLifetimeValue.h +++ b/src/strategy/values/ExpectedLifetimeValue.h @@ -28,7 +28,7 @@ class ExpectedGroupDpsValue : public FloatCalculatedValue { public: ExpectedGroupDpsValue(PlayerbotAI* botAI) : - FloatCalculatedValue(botAI, "expected group dps") { } + FloatCalculatedValue(botAI, "expected group dps", 20 * 1000) { } public: float Calculate() override; diff --git a/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp b/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp index 51ecd53f..1f55c9ae 100644 --- a/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp +++ b/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp @@ -53,7 +53,7 @@ class GenericWarlockNonCombatStrategyActionNodeFactory : public NamedObjectFacto { return new ActionNode("summon felhunter", /*P*/ nullptr, - /*A*/ NextAction::array(0, new NextAction("summon succubus"), nullptr), + /*A*/ NextAction::array(0, new NextAction("summon voidwalker"), nullptr), /*C*/ nullptr); } static ActionNode* summon_felguard([[maybe_unused]] PlayerbotAI* botAI) From 243a4df967570dc2a163589c9d57acfcfad292eb Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 8 Sep 2023 12:44:38 +0800 Subject: [PATCH 2/6] optimize class spell --- src/PlayerbotAI.cpp | 103 +++++++++--------- src/RandomPlayerbotFactory.cpp | 10 +- src/strategy/actions/GenericSpellActions.cpp | 16 +-- src/strategy/actions/GenericSpellActions.h | 4 +- src/strategy/deathknight/BloodDKStrategy.cpp | 10 +- src/strategy/deathknight/DKActions.h | 26 +++-- .../deathknight/DKAiObjectContext.cpp | 9 +- src/strategy/deathknight/DKTriggers.cpp | 5 + src/strategy/deathknight/DKTriggers.h | 33 +++++- src/strategy/deathknight/FrostDKStrategy.cpp | 4 + src/strategy/deathknight/UnholyDKStrategy.cpp | 10 +- src/strategy/druid/DruidActions.h | 1 + .../druid/GenericDruidNonCombatStrategy.cpp | 21 +++- src/strategy/hunter/HunterActions.h | 1 + src/strategy/mage/ArcaneMageStrategy.cpp | 2 +- src/strategy/mage/GenericMageStrategy.cpp | 6 +- src/strategy/mage/MageActions.h | 1 + src/strategy/rogue/RogueActions.h | 1 + src/strategy/triggers/GenericTriggers.h | 2 +- src/strategy/warlock/WarlockActions.h | 1 + 20 files changed, 169 insertions(+), 97 deletions(-) diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 82f2373a..3124c6d7 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -940,13 +940,13 @@ void PlayerbotAI::ChangeEngine(BotState type) switch (type) { case BOT_STATE_COMBAT: - LOG_DEBUG("playerbots", "=== {} COMBAT ===", bot->GetName().c_str()); + // LOG_DEBUG("playerbots", "=== {} COMBAT ===", bot->GetName().c_str()); break; case BOT_STATE_NON_COMBAT: - LOG_DEBUG("playerbots", "=== {} NON-COMBAT ===", bot->GetName().c_str()); + // LOG_DEBUG("playerbots", "=== {} NON-COMBAT ===", bot->GetName().c_str()); break; case BOT_STATE_DEAD: - LOG_DEBUG("playerbots", "=== {} DEAD ===", bot->GetName().c_str()); + // LOG_DEBUG("playerbots", "=== {} DEAD ===", bot->GetName().c_str()); break; } } @@ -2060,18 +2060,18 @@ bool PlayerbotAI::CanCastSpell(std::string const name, Unit* target, Item* itemT bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, Item* itemTarget) { if (!spellid) { - // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { - // LOG_DEBUG("playerbots", "Can cast spell failed. No spellid. - spellid: {}, bot name: {}", - // spellid, bot->GetName()); - // } + if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { + LOG_DEBUG("playerbots", "Can cast spell failed. No spellid. - spellid: {}, bot name: {}", + spellid, bot->GetName()); + } return false; } if (bot->HasUnitState(UNIT_STATE_LOST_CONTROL)) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { - // LOG_DEBUG("playerbots", "Can cast spell failed. Unit state lost control. - spellid: {}, bot name: {}", - // spellid, bot->GetName()); - // } + if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { + LOG_DEBUG("playerbots", "Can cast spell failed. Unit state lost control. - spellid: {}, bot name: {}", + spellid, bot->GetName()); + } return false; } @@ -2079,7 +2079,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, if (!target) target = bot; - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) + // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) // LOG_DEBUG("playerbots", "Can cast spell? - target name: {}, spellid: {}, bot name: {}", // target->GetName(), spellid, bot->GetName()); @@ -2088,42 +2088,42 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, return true; if (checkHasSpell && !bot->HasSpell(spellid)) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { - // LOG_DEBUG("playerbots", "Can cast spell failed. Bot not has spell. - target name: {}, spellid: {}, bot name: {}", - // target->GetName(), spellid, bot->GetName()); - // } + if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { + LOG_DEBUG("playerbots", "Can cast spell failed. Bot not has spell. - target name: {}, spellid: {}, bot name: {}", + target->GetName(), spellid, bot->GetName()); + } return false; } if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr) { - // LOG_DEBUG("playerbots", "CanCastSpell() target name: {}, spellid: {}, bot name: {}, failed because has current channeled spell", - // target->GetName(), spellid, bot->GetName()); + LOG_DEBUG("playerbots", "CanCastSpell() target name: {}, spellid: {}, bot name: {}, failed because has current channeled spell", + target->GetName(), spellid, bot->GetName()); return false; } if (bot->HasSpellCooldown(spellid)) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { - // LOG_DEBUG("playerbots", "Can cast spell failed. Spell not has cooldown. - target name: {}, spellid: {}, bot name: {}", - // target->GetName(), spellid, bot->GetName()); - // } + if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { + LOG_DEBUG("playerbots", "Can cast spell failed. Spell not has cooldown. - target name: {}, spellid: {}, bot name: {}", + target->GetName(), spellid, bot->GetName()); + } return false; } SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); if (!spellInfo) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { - // LOG_DEBUG("playerbots", "Can cast spell failed. No spellInfo. - target name: {}, spellid: {}, bot name: {}", - // target->GetName(), spellid, bot->GetName()); - // } + if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { + LOG_DEBUG("playerbots", "Can cast spell failed. No spellInfo. - target name: {}, spellid: {}, bot name: {}", + target->GetName(), spellid, bot->GetName()); + } return false; } uint32 CastingTime = !spellInfo->IsChanneled() ? spellInfo->CalcCastTime(bot) : spellInfo->GetDuration(); if (CastingTime && bot->isMoving()) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { - // LOG_DEBUG("playerbots", "Casting time and bot is moving - target name: {}, spellid: {}, bot name: {}", - // target->GetName(), spellid, bot->GetName()); - // } + if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { + LOG_DEBUG("playerbots", "Casting time and bot is moving - target name: {}, spellid: {}, bot name: {}", + target->GetName(), spellid, bot->GetName()); + } return false; } @@ -2147,10 +2147,10 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, // } if (target->IsImmunedToSpell(spellInfo)) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { - // LOG_DEBUG("playerbots", "target is immuned to spell - target name: {}, spellid: {}, bot name: {}", - // target->GetName(), spellid, bot->GetName()); - // } + if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { + LOG_DEBUG("playerbots", "target is immuned to spell - target name: {}, spellid: {}, bot name: {}", + target->GetName(), spellid, bot->GetName()); + } return false; } @@ -2159,7 +2159,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, // for (uint8 i = EFFECT_0; i <= EFFECT_2; i++) // { // if (target->IsImmunedToSpellEffect(spellInfo, i)) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { + // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { // LOG_DEBUG("playerbots", "target is immuned to spell effect - target name: {}, spellid: {}, bot name: {}", // target->GetName(), spellid, bot->GetName()); // } @@ -2169,10 +2169,10 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, // } if (bot != target && sServerFacade->GetDistance2d(bot, target) > sPlayerbotAIConfig->sightDistance) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { - // LOG_DEBUG("playerbots", "target is out of sight distance - target name: {}, spellid: {}, bot name: {}", - // target->GetName(), spellid, bot->GetName()); - // } + if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { + LOG_DEBUG("playerbots", "target is out of sight distance - target name: {}, spellid: {}, bot name: {}", + target->GetName(), spellid, bot->GetName()); + } return false; } } @@ -2188,7 +2188,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, SpellCastResult result = spell->CheckCast(true); delete spell; - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { + // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { // if (result != SPELL_FAILED_NOT_READY && result != SPELL_CAST_OK) { // LOG_DEBUG("playerbots", "CanCastSpell - target name: {}, spellid: {}, bot name: {}, result: {}", // target->GetName(), spellid, bot->GetName(), result); @@ -2209,12 +2209,11 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, case SPELL_FAILED_NOT_SHAPESHIFT: return true; default: - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { - // if (result != SPELL_FAILED_NOT_READY && result != SPELL_CAST_OK) { - // LOG_DEBUG("playerbots", "CanCastSpell Check Failed. - target name: {}, spellid: {}, bot name: {}, result: {}", - // target->GetName(), spellid, bot->GetName(), result); - // } - // } + if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { + // if (result != SPELL_FAILED_NOT_READY && result != SPELL_CAST_OK) { + LOG_DEBUG("playerbots", "CanCastSpell Check Failed. - target name: {}, spellid: {}, bot name: {}, result: {}", + target->GetName(), spellid, bot->GetName(), result); + } return false; } } @@ -2381,7 +2380,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) aiObjectContext->GetValue("stay time")->Set(0); if (bot->IsFlying() || bot->HasUnitState(UNIT_STATE_IN_FLIGHT)) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { + // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { // LOG_DEBUG("playerbots", "Spell cast is flying - target name: {}, spellid: {}, bot name: {}}", // target->GetName(), spellId, bot->GetName()); // } @@ -2411,7 +2410,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) if (failWithDelay) { SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { + // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { // LOG_DEBUG("playerbots", "Spell cast fail with delay - target name: {}, spellid: {}, bot name: {}", // target->GetName(), spellId, bot->GetName()); // } @@ -2430,7 +2429,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) { bot->GetTradeData()->SetSpell(spellId); delete spell; - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { + // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { // LOG_DEBUG("playerbots", "Spell cast no item - target name: {}, spellid: {}, bot name: {}", // target->GetName(), spellId, bot->GetName()); // } @@ -2485,7 +2484,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) // spell->m_targets.SetUnitTarget(target); // SpellCastResult spellSuccess = spell->CheckCast(true); - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { + // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { // LOG_DEBUG("playerbots", "Spell cast result - target name: {}, spellid: {}, bot name: {}, result: {}", // target->GetName(), spellId, bot->GetName(), spellSuccess); // } @@ -2495,7 +2494,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) SpellCastResult result = spell->prepare(&targets); if (result != SPELL_CAST_OK) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { + // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { // LOG_DEBUG("playerbots", "Spell cast failed. - target name: {}, spellid: {}, bot name: {}, result: {}", // target->GetName(), spellId, bot->GetName(), result); // } @@ -2508,7 +2507,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget) // { // spell->cancel(); // delete spell; - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { + // if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { // LOG_DEBUG("playerbots", "Spell cast loot - target name: {}, spellid: {}, bot name: {}", // target->GetName(), spellId, bot->GetName()); // } diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index 063b3089..e00eef84 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -206,11 +206,11 @@ Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls player->setCinematic(2); player->SetAtLoginFlag(AT_LOGIN_NONE); - // player->SaveToDB(true, false); - // if (player->getClass() == CLASS_DEATH_KNIGHT) - // { - // player->learnSpell(50977, false); - // } + player->SaveToDB(true, false); + if (player->getClass() == CLASS_DEATH_KNIGHT) + { + player->learnSpell(50977, false); + } // player->RewardQuest(const Quest *quest, uint32 reward, Object *questGiver) LOG_DEBUG("playerbots", "Random bot created for account {} - name: \"{}\"; race: {}; class: {}", accountId, name.c_str(), race, cls); diff --git a/src/strategy/actions/GenericSpellActions.cpp b/src/strategy/actions/GenericSpellActions.cpp index 377f29d9..aa51841a 100644 --- a/src/strategy/actions/GenericSpellActions.cpp +++ b/src/strategy/actions/GenericSpellActions.cpp @@ -63,10 +63,10 @@ bool CastSpellAction::Execute(Event event) bool CastSpellAction::isPossible() { if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true)) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { - // LOG_DEBUG("playerbots", "Can cast spell failed. Vehicle. - bot name: {}", - // bot->GetName()); - // } + if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && botAI->HasRealPlayerMaster())) { + LOG_DEBUG("playerbots", "Can cast spell failed. Vehicle. - bot name: {}", + bot->GetName()); + } return false; } @@ -75,10 +75,10 @@ bool CastSpellAction::isPossible() if (spell == "mount" && bot->IsInCombat()) { - // if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { - // LOG_DEBUG("playerbots", "Can cast spell failed. Mount. - bot name: {}", - // bot->GetName()); - // } + if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && botAI->HasRealPlayerMaster())) { + LOG_DEBUG("playerbots", "Can cast spell failed. Mount. - bot name: {}", + bot->GetName()); + } bot->Dismount(); return false; } diff --git a/src/strategy/actions/GenericSpellActions.h b/src/strategy/actions/GenericSpellActions.h index bbe1b480..cda5afc6 100644 --- a/src/strategy/actions/GenericSpellActions.h +++ b/src/strategy/actions/GenericSpellActions.h @@ -66,10 +66,10 @@ class CastDebuffSpellOnAttackerAction : public CastDebuffSpellAction // ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } }; -class CastDebuffSpellOnMeleeAttackerAction : public CastAuraSpellAction +class CastDebuffSpellOnMeleeAttackerAction : public CastDebuffSpellAction { public: - CastDebuffSpellOnMeleeAttackerAction(PlayerbotAI* botAI, std::string const spell, bool isOwner = true) : CastAuraSpellAction(botAI, spell, isOwner) { } + CastDebuffSpellOnMeleeAttackerAction(PlayerbotAI* botAI, std::string const spell, bool isOwner = true, float needLifeTime = 8.0f) : CastDebuffSpellAction(botAI, spell, isOwner, needLifeTime) { } Value* GetTargetValue() override; std::string const getName() override { return spell + " on attacker"; } diff --git a/src/strategy/deathknight/BloodDKStrategy.cpp b/src/strategy/deathknight/BloodDKStrategy.cpp index bc610dbf..079d4ad9 100644 --- a/src/strategy/deathknight/BloodDKStrategy.cpp +++ b/src/strategy/deathknight/BloodDKStrategy.cpp @@ -80,12 +80,14 @@ BloodDKStrategy::BloodDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI) NextAction** BloodDKStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("rune strike", ACTION_NORMAL + 7), - new NextAction("icy touch", ACTION_NORMAL + 6), - new NextAction("heart strike", ACTION_NORMAL + 5), - new NextAction("blood strike", ACTION_NORMAL + 4), + new NextAction("rune strike", ACTION_NORMAL + 8), + new NextAction("icy touch", ACTION_NORMAL + 7), + new NextAction("heart strike", ACTION_NORMAL + 6), + new NextAction("blood strike", ACTION_NORMAL + 5), + new NextAction("dancing rune weapon", ACTION_NORMAL + 4), new NextAction("death coil", ACTION_NORMAL + 3), new NextAction("plague strike", ACTION_NORMAL + 2), + new NextAction("horn of winter", ACTION_NORMAL + 1), new NextAction("melee", ACTION_NORMAL), NULL); } diff --git a/src/strategy/deathknight/DKActions.h b/src/strategy/deathknight/DKActions.h index 170bd0a2..2c6d384b 100644 --- a/src/strategy/deathknight/DKActions.h +++ b/src/strategy/deathknight/DKActions.h @@ -113,17 +113,23 @@ class CastIcyTouchAction : public CastSpellAction class CastIcyTouchOnAttackerAction : public CastDebuffSpellOnMeleeAttackerAction { public: - CastIcyTouchOnAttackerAction(PlayerbotAI* botAI) : CastDebuffSpellOnMeleeAttackerAction(botAI, "icy touch", true) { } + CastIcyTouchOnAttackerAction(PlayerbotAI* botAI) : CastDebuffSpellOnMeleeAttackerAction(botAI, "icy touch", true, .0f) { } }; //debuff ps -BEGIN_DEBUFF_ACTION(CastPlagueStrikeAction, "plague strike") -END_SPELL_ACTION() + +class CastPlagueStrikeAction : public CastSpellAction +{ + public: + CastPlagueStrikeAction(PlayerbotAI* ai) : CastSpellAction(ai, "plague strike") {} +}; +// BEGIN_DEBUFF_ACTION(CastPlagueStrikeAction, "plague strike") +// END_SPELL_ACTION() class CastPlagueStrikeOnAttackerAction : public CastDebuffSpellOnMeleeAttackerAction { public: - CastPlagueStrikeOnAttackerAction(PlayerbotAI* botAI) : CastDebuffSpellOnMeleeAttackerAction(botAI, "plague strike", true) { } + CastPlagueStrikeOnAttackerAction(PlayerbotAI* botAI) : CastDebuffSpellOnMeleeAttackerAction(botAI, "plague strike", true, .0f) { } }; //debuff @@ -142,10 +148,10 @@ class CastUnholyBlightAction : public CastBuffSpellAction CastUnholyBlightAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "unholy blight") { } }; -class CastSummonGargoyleAction : public CastBuffSpellAction +class CastSummonGargoyleAction : public CastSpellAction { public: - CastSummonGargoyleAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "summon gargoyle") { } + CastSummonGargoyleAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "summon gargoyle") { } }; class CastGhoulFrenzyAction : public CastBuffSpellAction @@ -230,10 +236,10 @@ class CastDeathAndDecayAction : public CastSpellAction CastDeathAndDecayAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "death and decay") { } }; -class CastHornOfWinterAction : public CastBuffSpellAction +class CastHornOfWinterAction : public CastSpellAction { public: - CastHornOfWinterAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "horn of winter") { } + CastHornOfWinterAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "horn of winter") { } }; class CastImprovedIcyTalonsAction : public CastBuffSpellAction @@ -260,10 +266,10 @@ class CastDeathRuneMasteryAction : public CastBuffSpellAction CastDeathRuneMasteryAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "death rune mastery") { } }; -class CastDancingWeaponAction : public CastBuffSpellAction +class CastDancingRuneWeaponAction : public CastSpellAction { public: - CastDancingWeaponAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "dancing weapon") { } + CastDancingRuneWeaponAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "dancing rune weapon") { } }; class CastEmpowerRuneWeaponAction : public CastBuffSpellAction diff --git a/src/strategy/deathknight/DKAiObjectContext.cpp b/src/strategy/deathknight/DKAiObjectContext.cpp index a6ffebd6..b01d8a6d 100644 --- a/src/strategy/deathknight/DKAiObjectContext.cpp +++ b/src/strategy/deathknight/DKAiObjectContext.cpp @@ -85,6 +85,8 @@ class DeathKnightTriggerFactoryInternal : public NamedObjectContext creators["raise dead"] = &DeathKnightTriggerFactoryInternal::raise_dead; creators["chains of ice"] = &DeathKnightTriggerFactoryInternal::chains_of_ice; creators["unbreakable armor"] = &DeathKnightTriggerFactoryInternal::unbreakable_armor; + creators["high blood rune"] = &DeathKnightTriggerFactoryInternal::high_blood_rune; + creators["freezing fog"] = &DeathKnightTriggerFactoryInternal::freezing_fog; } private: @@ -106,6 +108,9 @@ class DeathKnightTriggerFactoryInternal : public NamedObjectContext static Trigger* raise_dead(PlayerbotAI* botAI) { return new RaiseDeadTrigger(botAI); } static Trigger* chains_of_ice(PlayerbotAI* botAI) { return new ChainsOfIceSnareTrigger(botAI); } static Trigger* unbreakable_armor(PlayerbotAI* botAI) { return new UnbreakableArmorTrigger(botAI); } + static Trigger* high_blood_rune(PlayerbotAI* botAI) { return new HighBloodRuneTrigger(botAI); } + static Trigger* freezing_fog(PlayerbotAI* botAI) { return new FreezingFogTrigger(botAI); } + }; class DeathKnightAiObjectContextInternal : public NamedObjectContext @@ -164,7 +169,7 @@ class DeathKnightAiObjectContextInternal : public NamedObjectContext creators["death pact"] = &DeathKnightAiObjectContextInternal::death_pact; creators["death rune_mastery"] = &DeathKnightAiObjectContextInternal::death_rune_mastery; //creators["hysteria"] = &DeathKnightAiObjectContextInternal::hysteria; - creators["dancing weapon"] = &DeathKnightAiObjectContextInternal::dancing_weapon; + creators["dancing rune weapon"] = &DeathKnightAiObjectContextInternal::dancing_rune_weapon; creators["dark command"] = &DeathKnightAiObjectContextInternal::dark_command; } @@ -221,7 +226,7 @@ class DeathKnightAiObjectContextInternal : public NamedObjectContext static Action* death_pact(PlayerbotAI* botAI) { return new CastDeathPactAction(botAI); } static Action* death_rune_mastery(PlayerbotAI* botAI) { return new CastDeathRuneMasteryAction(botAI); } //static Action* hysteria(PlayerbotAI* botAI) { return new CastHysteriaAction(botAI); } - static Action* dancing_weapon(PlayerbotAI* botAI) { return new CastDancingWeaponAction(botAI); } + static Action* dancing_rune_weapon(PlayerbotAI* botAI) { return new CastDancingRuneWeaponAction(botAI); } static Action* dark_command(PlayerbotAI* botAI) { return new CastDarkCommandAction(botAI); } static Action* mind_freeze_on_enemy_healer(PlayerbotAI* botAI) { return new CastMindFreezeOnEnemyHealerAction(botAI); } }; diff --git a/src/strategy/deathknight/DKTriggers.cpp b/src/strategy/deathknight/DKTriggers.cpp index c9c6a17c..07cf2364 100644 --- a/src/strategy/deathknight/DKTriggers.cpp +++ b/src/strategy/deathknight/DKTriggers.cpp @@ -27,4 +27,9 @@ bool PestilenceTrigger::IsActive() { return true; } return false; +} + +bool HighBloodRuneTrigger::IsActive() { + // bot->Say(std::to_string(bot->GetBaseRune(0)) + "_" + std::to_string(bot->GetRuneCooldown(0)) + " " + std::to_string(bot->GetBaseRune(1)) + "_" + std::to_string(bot->GetRuneCooldown(1)), LANG_UNIVERSAL); + return !bot->GetRuneCooldown(0) && !bot->GetRuneCooldown(1); } \ No newline at end of file diff --git a/src/strategy/deathknight/DKTriggers.h b/src/strategy/deathknight/DKTriggers.h index 04600e9d..bcf138b7 100644 --- a/src/strategy/deathknight/DKTriggers.h +++ b/src/strategy/deathknight/DKTriggers.h @@ -12,19 +12,31 @@ class PlayerbotAI; BUFF_TRIGGER(HornOfWinterTrigger, "horn of winter"); BUFF_TRIGGER(BoneShieldTrigger, "bone shield"); BUFF_TRIGGER(ImprovedIcyTalonsTrigger, "improved icy talons"); -DEBUFF_CHECKISOWNER_TRIGGER(PlagueStrikeDebuffTrigger, "blood plague"); -DEBUFF_CHECKISOWNER_TRIGGER(IcyTouchDebuffTrigger, "frost fever"); +// DEBUFF_CHECKISOWNER_TRIGGER(PlagueStrikeDebuffTrigger, "blood plague"); +class PlagueStrikeDebuffTrigger : public DebuffTrigger +{ + public: + PlagueStrikeDebuffTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "blood plague", true, .0f) { } +}; + +// DEBUFF_CHECKISOWNER_TRIGGER(IcyTouchDebuffTrigger, "frost fever"); +class IcyTouchDebuffTrigger : public DebuffTrigger +{ + public: + IcyTouchDebuffTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "frost fever", true, .0f) { } +}; + BUFF_TRIGGER(UnbreakableArmorTrigger, "unbreakable armor"); class PlagueStrikeDebuffOnAttackerTrigger : public DebuffOnMeleeAttackerTrigger { public: - PlagueStrikeDebuffOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnMeleeAttackerTrigger(botAI, "blood plague", true) { } + PlagueStrikeDebuffOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnMeleeAttackerTrigger(botAI, "blood plague", true, .0f) { } }; class IcyTouchDebuffOnAttackerTrigger : public DebuffOnMeleeAttackerTrigger { public: - IcyTouchDebuffOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnMeleeAttackerTrigger(botAI, "frost fever", true) { } + IcyTouchDebuffOnAttackerTrigger(PlayerbotAI* botAI) : DebuffOnMeleeAttackerTrigger(botAI, "frost fever", true, .0f) { } }; class DKPresenceTrigger : public BuffTrigger @@ -114,4 +126,17 @@ class StrangulateOnEnemyHealerTrigger : public InterruptEnemyHealerTrigger StrangulateOnEnemyHealerTrigger(PlayerbotAI* botAI) : InterruptEnemyHealerTrigger(botAI, "strangulate") { } }; +class HighBloodRuneTrigger : public Trigger +{ + public: + HighBloodRuneTrigger(PlayerbotAI* botAI) : Trigger(botAI, "high blood rune") { } + bool IsActive() override; +}; + +class FreezingFogTrigger : public HasAuraTrigger +{ + public: + FreezingFogTrigger(PlayerbotAI* botAI) : HasAuraTrigger(botAI, "freezing fog") { } +}; + #endif diff --git a/src/strategy/deathknight/FrostDKStrategy.cpp b/src/strategy/deathknight/FrostDKStrategy.cpp index 307801db..1383a468 100644 --- a/src/strategy/deathknight/FrostDKStrategy.cpp +++ b/src/strategy/deathknight/FrostDKStrategy.cpp @@ -82,6 +82,7 @@ NextAction** FrostDKStrategy::getDefaultActions() new NextAction("frost strike", ACTION_NORMAL + 4), // new NextAction("death strike", ACTION_NORMAL + 3), new NextAction("empower rune weapon", ACTION_NORMAL + 2), + new NextAction("horn of winter", ACTION_NORMAL), new NextAction("melee", ACTION_NORMAL), NULL ); @@ -91,6 +92,9 @@ void FrostDKStrategy::InitTriggers(std::vector& triggers) { GenericDKStrategy::InitTriggers(triggers); triggers.push_back(new TriggerNode("unbreakable armor", NextAction::array(0, new NextAction("unbreakable armor", ACTION_NORMAL + 4), nullptr))); + triggers.push_back(new TriggerNode("high blood rune", NextAction::array(0, new NextAction("blood strike", ACTION_NORMAL + 1), nullptr))); + triggers.push_back(new TriggerNode("freezing fog", NextAction::array(0, new NextAction("howling blast", ACTION_HIGH + 1), nullptr))); + // triggers.push_back(new TriggerNode("empower rune weapon", NextAction::array(0, new NextAction("empower rune weapon", ACTION_NORMAL + 4), nullptr))); } diff --git a/src/strategy/deathknight/UnholyDKStrategy.cpp b/src/strategy/deathknight/UnholyDKStrategy.cpp index 107294a7..4369689f 100644 --- a/src/strategy/deathknight/UnholyDKStrategy.cpp +++ b/src/strategy/deathknight/UnholyDKStrategy.cpp @@ -72,12 +72,14 @@ UnholyDKStrategy::UnholyDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI NextAction** UnholyDKStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("scourge strike", ACTION_NORMAL + 6), - new NextAction("blood strike", ACTION_NORMAL + 5), - new NextAction("ghoul frenzy", ACTION_NORMAL + 4), + new NextAction("scourge strike", ACTION_NORMAL + 7), + new NextAction("blood strike", ACTION_NORMAL + 6), + new NextAction("ghoul frenzy", ACTION_NORMAL + 5), + new NextAction("summon gargoyle", ACTION_NORMAL + 4), new NextAction("death coil", ACTION_NORMAL + 3), new NextAction("plague strike", ACTION_NORMAL + 2), - new NextAction("icy touch", ACTION_NORMAL + 1), + new NextAction("icy touch", ACTION_NORMAL + 1), + new NextAction("horn of winter", ACTION_NORMAL), new NextAction("melee", ACTION_NORMAL), nullptr); } diff --git a/src/strategy/druid/DruidActions.h b/src/strategy/druid/DruidActions.h index afacddb1..1fea0640 100644 --- a/src/strategy/druid/DruidActions.h +++ b/src/strategy/druid/DruidActions.h @@ -136,6 +136,7 @@ class CastHurricaneAction : public CastSpellAction { public: CastHurricaneAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "hurricane") { } + ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } }; class CastMoonfireAction : public CastDebuffSpellAction diff --git a/src/strategy/druid/GenericDruidNonCombatStrategy.cpp b/src/strategy/druid/GenericDruidNonCombatStrategy.cpp index 495f6dc4..ef24811a 100644 --- a/src/strategy/druid/GenericDruidNonCombatStrategy.cpp +++ b/src/strategy/druid/GenericDruidNonCombatStrategy.cpp @@ -17,6 +17,8 @@ class GenericDruidNonCombatStrategyActionNodeFactory : public NamedObjectFactory // creators["innervate"] = &innervate; creators["regrowth_on_party"] = ®rowth_on_party; creators["rejuvenation on party"] = &rejuvenation_on_party; + creators["remove curse on party"] = &remove_curse_on_party; + creators["abolish poison on party"] = &abolish_poison_on_party; } private: @@ -65,6 +67,20 @@ class GenericDruidNonCombatStrategyActionNodeFactory : public NamedObjectFactory /*A*/ NULL, /*C*/ NULL); } + static ActionNode* remove_curse_on_party(PlayerbotAI* ai) + { + return new ActionNode ("remove curse on party", + /*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), + /*A*/ NULL, + /*C*/ NULL); + } + static ActionNode* abolish_poison_on_party(PlayerbotAI* ai) + { + return new ActionNode ("abolish poison on party", + /*P*/ NextAction::array(0, new NextAction("caster form"), nullptr), + /*A*/ NULL, + /*C*/ NULL); + } // static ActionNode* innervate([[maybe_unused]] PlayerbotAI* botAI) // { // return new ActionNode ("innervate", @@ -84,7 +100,7 @@ void GenericDruidNonCombatStrategy::InitTriggers(std::vector& trig NonCombatStrategy::InitTriggers(triggers); triggers.push_back(new TriggerNode("mark of the wild", NextAction::array(0, new NextAction("mark of the wild", 14.0f), nullptr))); - triggers.push_back(new TriggerNode("thorns", NextAction::array(0, new NextAction("thorns", 12.0f), nullptr))); + // triggers.push_back(new TriggerNode("thorns", NextAction::array(0, new NextAction("thorns", 12.0f), nullptr))); // triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", 21.0f), nullptr))); triggers.push_back(new TriggerNode("party member cure poison", NextAction::array(0, new NextAction("abolish poison on party", 20.0f), nullptr))); triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("revive", ACTION_CRITICAL_HEAL + 10), nullptr))); @@ -106,6 +122,9 @@ void GenericDruidNonCombatStrategy::InitTriggers(std::vector& trig triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0, new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), NULL))); + + triggers.push_back(new TriggerNode("party member remove curse", + NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), NULL))); } GenericDruidBuffStrategy::GenericDruidBuffStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) diff --git a/src/strategy/hunter/HunterActions.h b/src/strategy/hunter/HunterActions.h index 6ece5bae..4f570dbb 100644 --- a/src/strategy/hunter/HunterActions.h +++ b/src/strategy/hunter/HunterActions.h @@ -53,6 +53,7 @@ BEGIN_RANGED_SPELL_ACTION(CastMultiShotAction, "multi-shot") END_SPELL_ACTION() BEGIN_RANGED_SPELL_ACTION(CastVolleyAction, "volley") + ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } END_SPELL_ACTION() DEBUFF_CHECKISOWNER_ACTION(CastSerpentStingAction, "serpent sting"); diff --git a/src/strategy/mage/ArcaneMageStrategy.cpp b/src/strategy/mage/ArcaneMageStrategy.cpp index 4dce3368..c5c46aa4 100644 --- a/src/strategy/mage/ArcaneMageStrategy.cpp +++ b/src/strategy/mage/ArcaneMageStrategy.cpp @@ -37,7 +37,7 @@ class ArcaneMageStrategyActionNodeFactory : public NamedObjectFactory* GetTargetValue() override; std::string const getName() override { return spell + " on attacker"; } diff --git a/src/strategy/warlock/WarlockActions.h b/src/strategy/warlock/WarlockActions.h index 3b5f177e..0ec8cfbb 100644 --- a/src/strategy/warlock/WarlockActions.h +++ b/src/strategy/warlock/WarlockActions.h @@ -148,6 +148,7 @@ class CastRainOfFireAction : public CastSpellAction { public: CastRainOfFireAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "rain of fire") { } + ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } }; class CastShadowfuryAction : public CastSpellAction From 0343ac5714d11ca5f9473c20cda8751a1fcae5ea Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 8 Sep 2023 12:47:44 +0800 Subject: [PATCH 3/6] mage fireball --- src/strategy/mage/GenericMageStrategy.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strategy/mage/GenericMageStrategy.cpp b/src/strategy/mage/GenericMageStrategy.cpp index 82cf152e..e238e703 100644 --- a/src/strategy/mage/GenericMageStrategy.cpp +++ b/src/strategy/mage/GenericMageStrategy.cpp @@ -25,9 +25,9 @@ class GenericMageStrategyActionNodeFactory : public NamedObjectFactory Date: Thu, 14 Sep 2023 23:29:09 +0800 Subject: [PATCH 4/6] facing to & reach party member to resurrect --- conf/playerbots.conf.dist | 2 +- src/strategy/actions/ActionContext.h | 2 ++ src/strategy/actions/AttackAction.cpp | 10 ++++++++-- src/strategy/actions/CastCustomSpellAction.cpp | 3 ++- src/strategy/actions/GenericSpellActions.cpp | 4 ++-- src/strategy/actions/GenericSpellActions.h | 9 ++++++++- src/strategy/actions/NonCombatActions.cpp | 8 ++++---- src/strategy/actions/ReachTargetActions.cpp | 9 +++++++++ src/strategy/actions/ReachTargetActions.h | 9 +++++++++ src/strategy/actions/UseMeetingStoneAction.cpp | 6 ++++++ src/strategy/deathknight/FrostDKStrategy.cpp | 2 +- src/strategy/druid/DruidActions.cpp | 2 +- src/strategy/triggers/GenericTriggers.h | 12 ++++++------ src/strategy/triggers/HealthTriggers.h | 2 +- 14 files changed, 60 insertions(+), 20 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index bf20e63a..44ac72c1 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -504,7 +504,7 @@ AiPlayerbot.TooCloseDistance = 5.0 AiPlayerbot.MeleeDistance = 0.01 AiPlayerbot.FollowDistance = 1.5 AiPlayerbot.WhisperDistance = 6000.0 -AiPlayerbot.ContactDistance = 0.01 +AiPlayerbot.ContactDistance = 0.45 AiPlayerbot.AoeRadius = 10 AiPlayerbot.RpgDistance = 200 AiPlayerbot.AggroDistance = 22 diff --git a/src/strategy/actions/ActionContext.h b/src/strategy/actions/ActionContext.h index 4d77159c..7573225e 100644 --- a/src/strategy/actions/ActionContext.h +++ b/src/strategy/actions/ActionContext.h @@ -85,6 +85,7 @@ class ActionContext : public NamedObjectContext creators["reach spell"] = &ActionContext::ReachSpell; creators["reach melee"] = &ActionContext::ReachMelee; creators["reach party member to heal"] = &ActionContext::reach_party_member_to_heal; + 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["gift of the naaru"] = &ActionContext::gift_of_the_naaru; @@ -259,6 +260,7 @@ class ActionContext : public NamedObjectContext static Action* ReachSpell(PlayerbotAI* botAI) { return new ReachSpellAction(botAI); } static Action* ReachMelee(PlayerbotAI* botAI) { return new ReachMeleeAction(botAI); } static Action* reach_party_member_to_heal(PlayerbotAI* botAI) { return new ReachPartyMemberToHealAction(botAI); } + static Action* reach_party_member_to_resurrect(PlayerbotAI* botAI) { return new ReachPartyMemberToResurrectAction(botAI); } static Action* flee(PlayerbotAI* botAI) { return new FleeAction(botAI); } static Action* flee_with_pet(PlayerbotAI* botAI) { return new FleeWithPetAction(botAI); } static Action* gift_of_the_naaru(PlayerbotAI* botAI) { return new CastGiftOfTheNaaruAction(botAI); } diff --git a/src/strategy/actions/AttackAction.cpp b/src/strategy/actions/AttackAction.cpp index 3034c7a7..9c905f17 100644 --- a/src/strategy/actions/AttackAction.cpp +++ b/src/strategy/actions/AttackAction.cpp @@ -102,6 +102,10 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/) context->GetValue("current target")->Set(target); context->GetValue("available loot")->Get()->Add(guid); + /* prevent pet dead immediately in group */ + if (bot->GetGroup() && !target->IsInCombat()) { + with_pet = false; + } if (Pet* pet = bot->GetPet()) { if (with_pet) { @@ -118,8 +122,10 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/) } } - if (IsMovingAllowed() && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target)) - bot->SetFacingToObject(target); + if (IsMovingAllowed() && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target)) { + sServerFacade->SetFacingTo(bot, target); + } + // bot->SetFacingToObject(target); bool attacked = bot->Attack(target, true); botAI->ChangeEngine(BOT_STATE_COMBAT); diff --git a/src/strategy/actions/CastCustomSpellAction.cpp b/src/strategy/actions/CastCustomSpellAction.cpp index 3dbeeced..9f674c6c 100644 --- a/src/strategy/actions/CastCustomSpellAction.cpp +++ b/src/strategy/actions/CastCustomSpellAction.cpp @@ -7,6 +7,7 @@ #include "Event.h" #include "ItemUsageValue.h" #include "Playerbots.h" +#include "ServerFacade.h" uint32 FindLastSeparator(std::string const text, std::string const sep) { @@ -99,7 +100,7 @@ bool CastCustomSpellAction::Execute(Event event) if (target != bot && !bot->HasInArc(CAST_ANGLE_IN_FRONT, target, sPlayerbotAIConfig->sightDistance)) { - bot->SetFacingToObject(target); + sServerFacade->SetFacingTo(bot, target); botAI->SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); msg << "cast " << text; diff --git a/src/strategy/actions/GenericSpellActions.cpp b/src/strategy/actions/GenericSpellActions.cpp index aa51841a..c5223882 100644 --- a/src/strategy/actions/GenericSpellActions.cpp +++ b/src/strategy/actions/GenericSpellActions.cpp @@ -153,7 +153,7 @@ bool CastEnchantItemAction::isPossible() CastHealingSpellAction::CastHealingSpellAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount) : CastAuraSpellAction(botAI, spell, true), estAmount(estAmount) { - range = botAI->GetRange("spell"); + range = botAI->GetRange("heal"); } bool CastHealingSpellAction::isUseful() @@ -168,7 +168,7 @@ bool CastAoeHealSpellAction::isUseful() CastCureSpellAction::CastCureSpellAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell) { - range = botAI->GetRange("spell"); + range = botAI->GetRange("heal"); } Value* CurePartyMemberAction::GetTargetValue() diff --git a/src/strategy/actions/GenericSpellActions.h b/src/strategy/actions/GenericSpellActions.h index cda5afc6..3d8e887e 100644 --- a/src/strategy/actions/GenericSpellActions.h +++ b/src/strategy/actions/GenericSpellActions.h @@ -6,6 +6,8 @@ #define _PLAYERBOT_GENERICSPELLACTIONS_H #include "Action.h" +#include "PlayerbotAI.h" +#include "PlayerbotAIConfig.h" #include "Value.h" class PlayerbotAI; @@ -150,9 +152,14 @@ class HealPartyMemberAction : public CastHealingSpellAction, public PartyMemberA class ResurrectPartyMemberAction : public CastSpellAction { public: - ResurrectPartyMemberAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell) { } + ResurrectPartyMemberAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell) { + } std::string const GetTargetName() override { return "party member to resurrect"; } + NextAction** getPrerequisites() override + { + return NextAction::merge( NextAction::array(0, new NextAction("reach party member to resurrect"), NULL), Action::getPrerequisites()); + } }; class CurePartyMemberAction : public CastSpellAction, public PartyMemberActionNameSupport diff --git a/src/strategy/actions/NonCombatActions.cpp b/src/strategy/actions/NonCombatActions.cpp index ab0882d2..d94a8adc 100644 --- a/src/strategy/actions/NonCombatActions.cpp +++ b/src/strategy/actions/NonCombatActions.cpp @@ -26,8 +26,8 @@ bool DrinkAction::Execute(Event event) if (bot->isMoving()) { - bot->StopMoving(); - botAI->SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); + // bot->StopMoving(); + // botAI->SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); return false; } bot->SetStandState(UNIT_STAND_STATE_SIT); @@ -78,8 +78,8 @@ bool EatAction::Execute(Event event) if (bot->isMoving()) { - bot->StopMoving(); - botAI->SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); + // bot->StopMoving(); + // botAI->SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown); return false; } diff --git a/src/strategy/actions/ReachTargetActions.cpp b/src/strategy/actions/ReachTargetActions.cpp index 77cc17a4..919cbff8 100644 --- a/src/strategy/actions/ReachTargetActions.cpp +++ b/src/strategy/actions/ReachTargetActions.cpp @@ -45,3 +45,12 @@ std::string const ReachPartyMemberToHealAction::GetTargetName() { return "party member to heal"; } + +ReachPartyMemberToResurrectAction::ReachPartyMemberToResurrectAction(PlayerbotAI* botAI) : ReachTargetAction(botAI, "reach party member to resurrect", botAI->GetRange("spell")) +{ +} + +std::string const ReachPartyMemberToResurrectAction::GetTargetName() +{ + return "party member to resurrect"; +} diff --git a/src/strategy/actions/ReachTargetActions.h b/src/strategy/actions/ReachTargetActions.h index 9d42f256..372aa8ba 100644 --- a/src/strategy/actions/ReachTargetActions.h +++ b/src/strategy/actions/ReachTargetActions.h @@ -54,4 +54,13 @@ class ReachPartyMemberToHealAction : public ReachTargetAction std::string const GetTargetName() override; }; +class ReachPartyMemberToResurrectAction : public ReachTargetAction +{ + public: + ReachPartyMemberToResurrectAction(PlayerbotAI* botAI); + + std::string const GetTargetName() override; +}; + + #endif diff --git a/src/strategy/actions/UseMeetingStoneAction.cpp b/src/strategy/actions/UseMeetingStoneAction.cpp index 5406e93e..c00fd503 100644 --- a/src/strategy/actions/UseMeetingStoneAction.cpp +++ b/src/strategy/actions/UseMeetingStoneAction.cpp @@ -73,6 +73,12 @@ bool SummonAction::Execute(Event event) Player* master = GetMaster(); if (!master) return false; + + if (Pet* pet = bot->GetPet()) { + pet->SetReactState(REACT_PASSIVE); + pet->GetCharmInfo()->SetIsCommandFollow(true); + pet->GetCharmInfo()->IsReturning(); + } if (master->GetSession()->GetSecurity() >= SEC_PLAYER) return Teleport(master, bot); diff --git a/src/strategy/deathknight/FrostDKStrategy.cpp b/src/strategy/deathknight/FrostDKStrategy.cpp index 1383a468..8966fa69 100644 --- a/src/strategy/deathknight/FrostDKStrategy.cpp +++ b/src/strategy/deathknight/FrostDKStrategy.cpp @@ -100,5 +100,5 @@ void FrostDKStrategy::InitTriggers(std::vector& triggers) void FrostDKAoeStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("howling blast", ACTION_NORMAL + 4), nullptr))); + triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("howling blast", ACTION_HIGH + 4), nullptr))); } diff --git a/src/strategy/druid/DruidActions.cpp b/src/strategy/druid/DruidActions.cpp index d379cf1a..aee2a145 100644 --- a/src/strategy/druid/DruidActions.cpp +++ b/src/strategy/druid/DruidActions.cpp @@ -48,5 +48,5 @@ NextAction** CastRebirthAction::getPrerequisites() bool CastRebirthAction::isUseful() { - return AI_VALUE2(float, "distance", GetTargetName()) <= sPlayerbotAIConfig->spellDistance; + return CastSpellAction::isUseful() && AI_VALUE2(float, "distance", GetTargetName()) <= sPlayerbotAIConfig->spellDistance; } \ No newline at end of file diff --git a/src/strategy/triggers/GenericTriggers.h b/src/strategy/triggers/GenericTriggers.h index f46a3c35..a6377e0b 100644 --- a/src/strategy/triggers/GenericTriggers.h +++ b/src/strategy/triggers/GenericTriggers.h @@ -234,19 +234,19 @@ class NoDrinkTrigger : public Trigger class LightAoeTrigger : public AoeTrigger { public: - LightAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 2, 10.0f) { } + LightAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 2, 8.0f) { } }; class MediumAoeTrigger : public AoeTrigger { public: - MediumAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 3, 10.0f) { } + MediumAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 3, 8.0f) { } }; class HighAoeTrigger : public AoeTrigger { public: - HighAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 4, 10.0f) { } + HighAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 4, 8.0f) { } }; class BuffTrigger : public SpellTrigger @@ -523,7 +523,7 @@ class TankAssistTrigger : public NoAttackersTrigger class IsBehindTargetTrigger : public Trigger { public: - IsBehindTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI) { } + IsBehindTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "behind target") { } bool IsActive() override; }; @@ -531,7 +531,7 @@ class IsBehindTargetTrigger : public Trigger class IsNotBehindTargetTrigger : public Trigger { public: - IsNotBehindTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI) { } + IsNotBehindTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "is not behind target") { } bool IsActive() override; }; @@ -539,7 +539,7 @@ class IsNotBehindTargetTrigger : public Trigger class IsNotFacingTargetTrigger : public Trigger { public: - IsNotFacingTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI) { } + IsNotFacingTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "not facing target") { } bool IsActive() override; }; diff --git a/src/strategy/triggers/HealthTriggers.h b/src/strategy/triggers/HealthTriggers.h index 54c7956c..3c6549e8 100644 --- a/src/strategy/triggers/HealthTriggers.h +++ b/src/strategy/triggers/HealthTriggers.h @@ -107,7 +107,7 @@ class TargetCriticalHealthTrigger : public TargetLowHealthTrigger class PartyMemberDeadTrigger : public Trigger { public: - PartyMemberDeadTrigger(PlayerbotAI* botAI) : Trigger(botAI, "resurrect", 3) { } + PartyMemberDeadTrigger(PlayerbotAI* botAI) : Trigger(botAI, "resurrect", 1 * 1000) { } std::string const GetTargetName() override { return "party member to resurrect"; } bool IsActive() override; From 0ea649340e4168c35d43302dd511334cc3fbfb35 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 14 Sep 2023 23:43:17 +0800 Subject: [PATCH 5/6] CanCastSpell --- src/PlayerbotAI.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 3124c6d7..dd7c318a 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -2207,6 +2207,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, case SPELL_FAILED_TRY_AGAIN: case SPELL_CAST_OK: case SPELL_FAILED_NOT_SHAPESHIFT: + case SPELL_FAILED_OUT_OF_RANGE: return true; default: if (!sPlayerbotAIConfig->logInGroupOnly || (bot->GetGroup() && HasRealPlayerMaster())) { From be13e0e189e5fda47f53bb1a0c697db219d8677c Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 15 Sep 2023 00:06:45 +0800 Subject: [PATCH 6/6] equipmentPersistence --- conf/playerbots.conf.dist | 7 +++++++ src/PlayerbotAIConfig.cpp | 2 ++ src/PlayerbotAIConfig.h | 2 ++ src/PlayerbotFactory.cpp | 16 ++++++++++------ .../actions/AutoTeleportForLevelAction.cpp | 4 +++- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 44ac72c1..efce23da 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -623,6 +623,13 @@ AiPlayerbot.RandomBotRandomPassword = 0 # Set RandomBotMaxLevel bots to RandomBotMinLevel or not AiPlayerbot.DowngradeMaxLevelBot = 0 +# Enable/Disable bot equipments persistence (stop random initialization) after certain level (EquipmentPersistenceLevel) +# default: 0 (disable) +AiPlayerbot.EquipmentPersistence = 0 + +# default: 80 +AiPlayerbot.EquipmentPersistenceLevel = 80 + ################################################################################## # # # Database Stuff # diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 0ccf397c..cc30d8f5 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -296,6 +296,8 @@ bool PlayerbotAIConfig::Initialize() disableRandomLevels = sConfigMgr->GetOption("AiPlayerbot.DisableRandomLevels", false); randomBotRandomPassword = sConfigMgr->GetOption("AiPlayerbot.RandomBotRandomPassword", true); downgradeMaxLevelBot = sConfigMgr->GetOption("AiPlayerbot.DowngradeMaxLevelBot", true); + equipmentPersistence = sConfigMgr->GetOption("AiPlayerbot.EquipmentPersistence", false); + equipmentPersistenceLevel = sConfigMgr->GetOption("AiPlayerbot.EquipmentPersistenceLevel", 80); playerbotsXPrate = sConfigMgr->GetOption("AiPlayerbot.KillXPRate", 1); botActiveAlone = sConfigMgr->GetOption("AiPlayerbot.BotActiveAlone", 10); randombotsWalkingRPG = sConfigMgr->GetOption("AiPlayerbot.RandombotsWalkingRPG", false); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index c7f04606..92368088 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -167,6 +167,8 @@ class PlayerbotAIConfig uint32 selfBotLevel; bool downgradeMaxLevelBot; + bool equipmentPersistence; + int32 equipmentPersistenceLevel; std::string const GetTimestampStr(); bool hasLog(std::string const fileName) { return std::find(allowedLogFiles.begin(), allowedLogFiles.end(), fileName) != allowedLogFiles.end(); }; bool openLog(std::string const fileName, char const* mode = "a"); diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index 8424e3eb..689dbd15 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -130,7 +130,9 @@ void PlayerbotFactory::Randomize(bool incremental) { ResetQuests(); } - ClearAllItems(); + if (!sPlayerbotAIConfig->equipmentPersistence || level < sPlayerbotAIConfig->equipmentPersistenceLevel) { + ClearAllItems(); + } bot->SaveToDB(false, false); bot->GiveLevel(level); @@ -222,7 +224,9 @@ void PlayerbotFactory::Randomize(bool incremental) pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Equip"); LOG_INFO("playerbots", "Initializing equipmemt..."); - InitEquipment(incremental); + if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) { + InitEquipment(incremental); + } // bot->SaveToDB(false, false); if (pmo) pmo->finish(); @@ -342,7 +346,9 @@ void PlayerbotFactory::Randomize(bool incremental) void PlayerbotFactory::Refresh() { // Prepare(); - InitEquipment(true); + if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) { + InitEquipment(true); + } ClearInventory(); InitAmmo(); InitFood(); @@ -1153,9 +1159,7 @@ void Shuffle(std::vector& items) void PlayerbotFactory::InitEquipment(bool incremental) { - - // todo(yunfan): to be refactored, too much time overhead - std::map > items; + std::unordered_map > items; int tab = AiFactory::GetPlayerSpecTab(bot); uint32 blevel = bot->getLevel(); diff --git a/src/strategy/actions/AutoTeleportForLevelAction.cpp b/src/strategy/actions/AutoTeleportForLevelAction.cpp index a4ddad56..7ed7a832 100644 --- a/src/strategy/actions/AutoTeleportForLevelAction.cpp +++ b/src/strategy/actions/AutoTeleportForLevelAction.cpp @@ -20,6 +20,8 @@ void AutoTeleportForLevelAction::AutoUpgradeEquip() { return; } PlayerbotFactory factory(bot, bot->GetLevel(), ITEM_QUALITY_RARE); - factory.InitEquipment(true); + if (!sPlayerbotAIConfig->equipmentPersistence || bot->GetLevel() < sPlayerbotAIConfig->equipmentPersistenceLevel) { + factory.InitEquipment(true); + } factory.InitAmmo(); } \ No newline at end of file