diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index ce3fc272..c03cd615 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -484,8 +484,8 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa engine->removeStrategy("threat", false); engine->addStrategy("boost", false); - if ((player->getClass() == CLASS_DRUID && tab == 2) || (player->getClass() == CLASS_SHAMAN && tab == 2)) - engine->addStrategiesNoInit("caster", "caster aoe", nullptr); + // if ((player->getClass() == CLASS_DRUID && tab == 2) || (player->getClass() == CLASS_SHAMAN && tab == 2)) + // engine->addStrategiesNoInit("caster", "caster aoe", nullptr); // if (player->getClass() == CLASS_DRUID && tab == 1) // engine->addStrategiesNoInit(/*"behind",*/ "dps", nullptr); diff --git a/src/strategy/druid/CasterDruidStrategy.cpp b/src/strategy/druid/CasterDruidStrategy.cpp index 61e7ab3d..27080efe 100644 --- a/src/strategy/druid/CasterDruidStrategy.cpp +++ b/src/strategy/druid/CasterDruidStrategy.cpp @@ -150,7 +150,7 @@ void CasterDruidStrategy::InitTriggers(std::vector& triggers) void CasterDruidAoeStrategy::InitTriggers(std::vector& triggers) { triggers.push_back( - new TriggerNode("high aoe", NextAction::array(0, new NextAction("hurricane", ACTION_HIGH + 1), nullptr))); + new TriggerNode("medium aoe", NextAction::array(0, new NextAction("hurricane", ACTION_HIGH + 1), nullptr))); triggers.push_back(new TriggerNode( "light aoe", NextAction::array(0, new NextAction("starfall", ACTION_NORMAL + 5), new NextAction("insect swarm on attacker", ACTION_NORMAL + 3), diff --git a/src/strategy/druid/DruidAiObjectContext.cpp b/src/strategy/druid/DruidAiObjectContext.cpp index fabd491b..a39fbc5b 100644 --- a/src/strategy/druid/DruidAiObjectContext.cpp +++ b/src/strategy/druid/DruidAiObjectContext.cpp @@ -164,6 +164,7 @@ public: creators["travel form"] = &DruidAiObjectContextInternal::travel_form; creators["aquatic form"] = &DruidAiObjectContextInternal::aquatic_form; creators["caster form"] = &DruidAiObjectContextInternal::caster_form; + creators["cancel tree form"] = &DruidAiObjectContextInternal::cancel_tree_form; creators["mangle (bear)"] = &DruidAiObjectContextInternal::mangle_bear; creators["maul"] = &DruidAiObjectContextInternal::maul; creators["bash"] = &DruidAiObjectContextInternal::bash; @@ -249,6 +250,7 @@ private: static Action* travel_form(PlayerbotAI* botAI) { return new CastTravelFormAction(botAI); } static Action* aquatic_form(PlayerbotAI* botAI) { return new CastAquaticFormAction(botAI); } static Action* caster_form(PlayerbotAI* botAI) { return new CastCasterFormAction(botAI); } + static Action* cancel_tree_form(PlayerbotAI* botAI) { return new CastCancelTreeFormAction(botAI); } static Action* mangle_bear(PlayerbotAI* botAI) { return new CastMangleBearAction(botAI); } static Action* maul(PlayerbotAI* botAI) { return new CastMaulAction(botAI); } static Action* bash(PlayerbotAI* botAI) { return new CastBashAction(botAI); } diff --git a/src/strategy/druid/DruidShapeshiftActions.cpp b/src/strategy/druid/DruidShapeshiftActions.cpp index 9894b1f5..4354328e 100644 --- a/src/strategy/druid/DruidShapeshiftActions.cpp +++ b/src/strategy/druid/DruidShapeshiftActions.cpp @@ -45,6 +45,17 @@ bool CastCasterFormAction::Execute(Event event) return true; } +bool CastCancelTreeFormAction::isUseful() +{ + return botAI->HasAura(33891, bot); +} + +bool CastCancelTreeFormAction::Execute(Event event) +{ + botAI->RemoveAura("tree of life"); + return true; +} + bool CastTreeFormAction::isUseful() { return GetTarget() && CastSpellAction::isUseful() && !botAI->HasAura(33891, bot); diff --git a/src/strategy/druid/DruidShapeshiftActions.h b/src/strategy/druid/DruidShapeshiftActions.h index 1f8fc082..6b24208b 100644 --- a/src/strategy/druid/DruidShapeshiftActions.h +++ b/src/strategy/druid/DruidShapeshiftActions.h @@ -70,4 +70,14 @@ public: bool Execute(Event event) override; }; +class CastCancelTreeFormAction : public CastBuffSpellAction +{ +public: + CastCancelTreeFormAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "cancel tree form") {} + + bool isUseful() override; + bool isPossible() override { return true; } + bool Execute(Event event) override; +}; + #endif diff --git a/src/strategy/druid/GenericDruidNonCombatStrategy.cpp b/src/strategy/druid/GenericDruidNonCombatStrategy.cpp index 398ba274..be5e822f 100644 --- a/src/strategy/druid/GenericDruidNonCombatStrategy.cpp +++ b/src/strategy/druid/GenericDruidNonCombatStrategy.cpp @@ -125,26 +125,34 @@ void GenericDruidNonCombatStrategy::InitTriggers(std::vector& trig triggers.push_back( new TriggerNode("party member critical health", - NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5), - new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6), NULL))); + NextAction::array(0, + new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 7), + new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6), + new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5), + nullptr))); triggers.push_back( new TriggerNode("party member low health", - NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3), - new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4), NULL))); + NextAction::array(0, + new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 5), + new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4), + new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3), + nullptr))); triggers.push_back( new TriggerNode("party member medium health", - NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1), - new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), NULL))); + NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 3), + new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), + new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1), + nullptr))); triggers.push_back( new TriggerNode("party member almost full health", - NextAction::array(0, new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), NULL))); + NextAction::array(0, new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3), 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))); + NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), nullptr))); } GenericDruidBuffStrategy::GenericDruidBuffStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI) diff --git a/src/strategy/druid/GenericDruidStrategy.cpp b/src/strategy/druid/GenericDruidStrategy.cpp index ccd3be5e..c3dacdb3 100644 --- a/src/strategy/druid/GenericDruidStrategy.cpp +++ b/src/strategy/druid/GenericDruidStrategy.cpp @@ -158,7 +158,15 @@ void DruidAssistDpsStrategy::InitTriggers(std::vector& triggers) triggers.push_back( new TriggerNode("healer should attack", NextAction::array(0, + new NextAction("cancel tree form", ACTION_DEFAULT + 0.3f), new NextAction("moonfire", ACTION_DEFAULT + 0.2f), new NextAction("wrath", ACTION_DEFAULT + 0.1f), + new NextAction("starfire", ACTION_DEFAULT), + nullptr))); + + triggers.push_back( + new TriggerNode("medium aoe and healer should attack", + NextAction::array(0, + new NextAction("hurricane", ACTION_DEFAULT + 0.7f), nullptr))); } diff --git a/src/strategy/druid/HealDruidStrategy.cpp b/src/strategy/druid/HealDruidStrategy.cpp index 8fb17f2c..b1a28c6e 100644 --- a/src/strategy/druid/HealDruidStrategy.cpp +++ b/src/strategy/druid/HealDruidStrategy.cpp @@ -12,9 +12,9 @@ class HealDruidStrategyActionNodeFactory : public NamedObjectFactory public: HealDruidStrategyActionNodeFactory() { creators["nourish on party"] = &nourtish_on_party; - creators["wild growth on party"] = &wild_growth_on_party; - creators["rejuvenation on party"] = &rejuvenation_on_party; - creators["regrowth on party"] = ®rowth_on_party; + // creators["wild growth on party"] = &wild_growth_on_party; + // creators["rejuvenation on party"] = &rejuvenation_on_party; + // creators["regrowth on party"] = ®rowth_on_party; } private: @@ -25,27 +25,27 @@ private: /*A*/ NextAction::array(0, new NextAction("healing touch on party"), nullptr), /*C*/ nullptr); } - static ActionNode* wild_growth_on_party([[maybe_unused]] PlayerbotAI* botAI) - { - return new ActionNode("wild growth on party", - /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr), - /*A*/ nullptr, - /*C*/ nullptr); - } - static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI) - { - return new ActionNode("rejuvenation on party", - /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr), - /*A*/ nullptr, - /*C*/ nullptr); - } - static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI) - { - return new ActionNode("regrowth on party", - /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr), - /*A*/ nullptr, - /*C*/ nullptr); - } + // static ActionNode* wild_growth_on_party([[maybe_unused]] PlayerbotAI* botAI) + // { + // return new ActionNode("wild growth on party", + // /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr), + // /*A*/ nullptr, + // /*C*/ nullptr); + // } + // static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI) + // { + // return new ActionNode("rejuvenation on party", + // /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr), + // /*A*/ nullptr, + // /*C*/ nullptr); + // } + // static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI) + // { + // return new ActionNode("regrowth on party", + // /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr), + // /*A*/ nullptr, + // /*C*/ nullptr); + // } }; HealDruidStrategy::HealDruidStrategy(PlayerbotAI* botAI) : GenericDruidStrategy(botAI) @@ -57,8 +57,6 @@ void HealDruidStrategy::InitTriggers(std::vector& triggers) { GenericDruidStrategy::InitTriggers(triggers); - // triggers.push_back(new TriggerNode("enemy out of spell", NextAction::array(0, new NextAction("reach spell", - // ACTION_NORMAL + 9), nullptr))); // triggers.push_back( // new TriggerNode("tree form", NextAction::array(0, new NextAction("tree form", ACTION_HIGH + 1), nullptr))); @@ -69,12 +67,14 @@ void HealDruidStrategy::InitTriggers(std::vector& triggers) // CRITICAL triggers.push_back( new TriggerNode("party member critical health", - NextAction::array(0, new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 4), + NextAction::array(0, + new NextAction("tree form", ACTION_CRITICAL_HEAL + 4.1f), + new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 4), new NextAction("wild growth on party", ACTION_CRITICAL_HEAL + 3), new NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 2), new NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1), // new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 0), - NULL))); + nullptr))); triggers.push_back( new TriggerNode("party member critical health", @@ -87,29 +87,32 @@ void HealDruidStrategy::InitTriggers(std::vector& triggers) // LOW triggers.push_back( new TriggerNode("party member low health", - NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 9), + NextAction::array(0, new NextAction("tree form", ACTION_MEDIUM_HEAL + 9.1f), + new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 9), new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 8), new NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 7), new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 6), - NULL))); + nullptr))); // MEDIUM triggers.push_back( new TriggerNode("party member medium health", - NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 4), + NextAction::array(0, + new NextAction("tree form", ACTION_MEDIUM_HEAL + 4.1f), + new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 4), new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3), new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), - new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 1), NULL))); + new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 1), nullptr))); // almost full triggers.push_back( new TriggerNode("party member almost full health", NextAction::array(0, new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3), new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), - new NextAction("regrowth on party", ACTION_LIGHT_HEAL + 1), NULL))); + new NextAction("regrowth on party", ACTION_LIGHT_HEAL + 1), nullptr))); triggers.push_back( - new TriggerNode("medium mana", NextAction::array(0, new NextAction("innervate", ACTION_HIGH + 5), NULL))); + new TriggerNode("medium mana", NextAction::array(0, new NextAction("innervate", ACTION_HIGH + 5), nullptr))); triggers.push_back(new TriggerNode("enemy too close for spell", NextAction::array(0, new NextAction("flee", ACTION_MOVE + 9), nullptr))); diff --git a/src/strategy/paladin/GenericPaladinNonCombatStrategy.cpp b/src/strategy/paladin/GenericPaladinNonCombatStrategy.cpp index 80e23cd3..d19320bd 100644 --- a/src/strategy/paladin/GenericPaladinNonCombatStrategy.cpp +++ b/src/strategy/paladin/GenericPaladinNonCombatStrategy.cpp @@ -22,7 +22,7 @@ void GenericPaladinNonCombatStrategy::InitTriggers(std::vector& tr triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0, new NextAction("flash of light on party", 25.0f), NULL))); triggers.push_back(new TriggerNode("party member medium health", - NextAction::array(0, new NextAction("holy light on party", 26.0f), NULL))); + NextAction::array(0, new NextAction("flash of light on party", 26.0f), NULL))); triggers.push_back(new TriggerNode("party member low health", NextAction::array(0, new NextAction("holy light on party", 27.0f), NULL))); triggers.push_back(new TriggerNode("party member critical health", diff --git a/src/strategy/paladin/GenericPaladinStrategy.cpp b/src/strategy/paladin/GenericPaladinStrategy.cpp index 791b5cff..09eb2074 100644 --- a/src/strategy/paladin/GenericPaladinStrategy.cpp +++ b/src/strategy/paladin/GenericPaladinStrategy.cpp @@ -77,10 +77,11 @@ void PaladinAssistDpsStrategy::InitTriggers(std::vector& triggers) triggers.push_back( new TriggerNode("healer should attack", NextAction::array(0, - new NextAction("hammer of wrath", ACTION_DEFAULT + 0.5f), - new NextAction("holy shock", ACTION_DEFAULT + 0.4f), - new NextAction("shield of righteousness", ACTION_DEFAULT + 0.3f), - new NextAction("judgement of light", ACTION_DEFAULT + 0.2f), - new NextAction("exorcism", ACTION_DEFAULT + 0.1f), + new NextAction("hammer of wrath", ACTION_DEFAULT + 0.6f), + new NextAction("holy shock", ACTION_DEFAULT + 0.5f), + new NextAction("shield of righteousness", ACTION_DEFAULT + 0.4f), + new NextAction("judgement of light", ACTION_DEFAULT + 0.3f), + new NextAction("consecration", ACTION_DEFAULT + 0.2f), + new NextAction("exorcism", ACTION_DEFAULT+ 0.1f), nullptr))); } diff --git a/src/strategy/priest/GenericPriestStrategy.cpp b/src/strategy/priest/GenericPriestStrategy.cpp index 42826fcd..fa680424 100644 --- a/src/strategy/priest/GenericPriestStrategy.cpp +++ b/src/strategy/priest/GenericPriestStrategy.cpp @@ -95,8 +95,8 @@ void PriestAssistDpsStrategy::InitTriggers(std::vector& triggers) NextAction::array(0, new NextAction("shadow word: pain", ACTION_DEFAULT + 0.5f), new NextAction("holy fire", ACTION_DEFAULT + 0.4f), - // new NextAction("mind blast", ACTION_DEFAULT + 0.3f), - new NextAction("smite", ACTION_DEFAULT + 0.1f), + new NextAction("smite", ACTION_DEFAULT + 0.3f), + new NextAction("mind blast", ACTION_DEFAULT + 0.2f), new NextAction("shoot", ACTION_DEFAULT), nullptr))); diff --git a/src/strategy/triggers/GenericTriggers.cpp b/src/strategy/triggers/GenericTriggers.cpp index 0adbc077..26572394 100644 --- a/src/strategy/triggers/GenericTriggers.cpp +++ b/src/strategy/triggers/GenericTriggers.cpp @@ -9,6 +9,8 @@ #include "BattlegroundWS.h" #include "CreatureAI.h" +#include "GameTime.h" +#include "LastSpellCastValue.h" #include "ObjectGuid.h" #include "PlayerbotAIConfig.h" #include "Playerbots.h" @@ -372,23 +374,28 @@ bool HealerShouldAttackTrigger::IsActive() if (botAI->GetNearGroupMemberCount(sPlayerbotAIConfig->sightDistance) <= 1) return true; - bool almostFullMana = AI_VALUE2(bool, "has mana", "self target") && - AI_VALUE2(uint8, "mana", "self target") < 85; - - // high pressure - if (AI_VALUE(uint8, "balance") <= 50 && almostFullMana) + if (AI_VALUE2(uint8, "health", "party member to heal") < sPlayerbotAIConfig->almostFullHealth) return false; - bool highMana = AI_VALUE2(bool, "has mana", "self target") && - AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->highMana; + // special check for resto druid (dont remove tree of life frequently) + if (bot->GetAura(33891)) + { + LastSpellCast& lastSpell = botAI->GetAiObjectContext()->GetValue("last spell cast")->Get(); + if (lastSpell.timer + 5 > time(nullptr)) + return false; + } - if (AI_VALUE(uint8, "balance") <= 100 && highMana) - return false; - - bool mediumMana = AI_VALUE2(bool, "has mana", "self target") && - AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->mediumMana; + int manaThreshold; + int balance = AI_VALUE(uint8, "balance"); + // higher threshold in higher pressure + if (balance <= 50) + manaThreshold = 85; + else if (balance <= 100) + manaThreshold = sPlayerbotAIConfig->highMana; + else + manaThreshold = sPlayerbotAIConfig->mediumMana; - if (mediumMana) + if (AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < manaThreshold) return false; return true; diff --git a/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp b/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp index 7ed900cf..a46346fe 100644 --- a/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp +++ b/src/strategy/warlock/GenericWarlockNonCombatStrategy.cpp @@ -55,7 +55,7 @@ private: { return new ActionNode("summon felhunter", /*P*/ nullptr, - /*A*/ NextAction::array(0, new NextAction("summon voidwalker"), nullptr), + /*A*/ NextAction::array(0, new NextAction("summon succubus"), nullptr), /*C*/ nullptr); } static ActionNode* summon_felguard([[maybe_unused]] PlayerbotAI* botAI)