From 5c8283d40a421d765860d59e7330cbbb4fd3728a Mon Sep 17 00:00:00 2001 From: avirar Date: Mon, 30 Dec 2024 07:47:22 +1100 Subject: [PATCH] Prot warriors cast vigilance when in a group (#825) * Add Vigilance * Vigilance * Update WarriorTriggers.h * Update TankWarriorStrategy.cpp * Update WarriorAiObjectContext.cpp * Update WarriorTriggers.cpp * Update WarriorTriggers.h * Update WarriorTriggers.cpp Check for existence of Vigilance in raid already * Update WarriorActions.cpp Check for existence of Vigilance in raid already Apply to tanks, then highest gearscore DPS. * Update WarriorActions.cpp * Update WarriorActions.cpp * Update WarriorActions.cpp * Update WarriorActions.cpp * Added logout Bots keep assigning it to me and not maintank? Added logging to clarify * Update WarriorActions.cpp * Update WarriorActions.cpp * Update WarriorActions.cpp * Update WarriorActions.cpp * Update WarriorTriggers.cpp * Update WarriorTriggers.cpp * Update WarriorTriggers.cpp * Update WarriorActions.cpp * Update WarriorActions.cpp * Update WarriorTriggers.cpp * Update WarriorActions.cpp * Update WarriorActions.cpp * Removed Logs * Removed logs * Added check for spell in trigger * Update WarriorTriggers.cpp * !member->IsAlive() * !member->IsAlive() --- src/strategy/warrior/TankWarriorStrategy.cpp | 12 +++ src/strategy/warrior/WarriorActions.cpp | 89 +++++++++++++++++++ src/strategy/warrior/WarriorActions.h | 9 ++ .../warrior/WarriorAiObjectContext.cpp | 6 ++ src/strategy/warrior/WarriorTriggers.cpp | 72 +++++++++++++++ src/strategy/warrior/WarriorTriggers.h | 8 ++ 6 files changed, 196 insertions(+) diff --git a/src/strategy/warrior/TankWarriorStrategy.cpp b/src/strategy/warrior/TankWarriorStrategy.cpp index d7e47f6b..5f228b09 100644 --- a/src/strategy/warrior/TankWarriorStrategy.cpp +++ b/src/strategy/warrior/TankWarriorStrategy.cpp @@ -22,6 +22,7 @@ public: creators["heroic throw taunt"] = &heroic_throw_taunt; creators["taunt"] = &taunt; creators["taunt spell"] = &taunt; + creators["vigilance"] = &vigilance; } private: @@ -41,6 +42,14 @@ private: /*A*/ NextAction::array(0, new NextAction("heroic throw taunt"), nullptr), /*C*/ nullptr); } + + static ActionNode* vigilance(PlayerbotAI* botAI) + { + return new ActionNode("vigilance", + /*P*/ nullptr, + /*A*/ nullptr, + /*C*/ nullptr); + } }; TankWarriorStrategy::TankWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStrategy(botAI) @@ -59,6 +68,9 @@ void TankWarriorStrategy::InitTriggers(std::vector& triggers) { GenericWarriorStrategy::InitTriggers(triggers); + triggers.push_back(new TriggerNode( + "vigilance", + NextAction::array(0, new NextAction("vigilance", ACTION_HIGH + 7), nullptr))); triggers.push_back( new TriggerNode("enemy out of melee", NextAction::array(0, new NextAction("heroic throw", ACTION_MOVE + 11), new NextAction("charge", ACTION_MOVE + 10), nullptr))); diff --git a/src/strategy/warrior/WarriorActions.cpp b/src/strategy/warrior/WarriorActions.cpp index eaf8f9a5..662bcc2d 100644 --- a/src/strategy/warrior/WarriorActions.cpp +++ b/src/strategy/warrior/WarriorActions.cpp @@ -12,3 +12,92 @@ bool CastSunderArmorAction::isUseful() Aura* aura = botAI->GetAura("sunder armor", GetTarget(), false, true); return !aura || aura->GetStackAmount() < 5 || aura->GetDuration() <= 6000; } + +Value* CastVigilanceAction::GetTargetValue() +{ + Group* group = bot->GetGroup(); + if (!group) + { + return new ManualSetValue(botAI, nullptr); + } + + Player* currentVigilanceTarget = nullptr; + Player* mainTank = nullptr; + Player* assistTank1 = nullptr; + Player* assistTank2 = nullptr; + Player* highestGearScorePlayer = nullptr; + uint32 highestGearScore = 0; + + // Iterate once through the group to gather all necessary information + for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) + { + Player* member = ref->GetSource(); + if (!member || member == bot || !member->IsAlive()) + continue; + + // Check if member has Vigilance applied by the bot + if (!currentVigilanceTarget && botAI->HasAura("vigilance", member, false, true)) + { + currentVigilanceTarget = member; + } + + // Identify Main Tank + if (!mainTank && botAI->IsMainTank(member)) + { + mainTank = member; + } + + // Identify Assist Tanks + if (assistTank1 == nullptr && botAI->IsAssistTankOfIndex(member, 0)) + { + assistTank1 = member; + } + else if (assistTank2 == nullptr && botAI->IsAssistTankOfIndex(member, 1)) + { + assistTank2 = member; + } + + // Determine Highest Gear Score + uint32 gearScore = botAI->GetEquipGearScore(member, false, false); + if (gearScore > highestGearScore) + { + highestGearScore = gearScore; + highestGearScorePlayer = member; + } + } + + // Determine the highest-priority target + Player* highestPriorityTarget = mainTank ? mainTank : + (assistTank1 ? assistTank1 : + (assistTank2 ? assistTank2 : highestGearScorePlayer)); + + // If no valid target, return nullptr + if (!highestPriorityTarget) + { + return new ManualSetValue(botAI, nullptr); + } + + // If the current target is already the highest-priority target, do nothing + if (currentVigilanceTarget == highestPriorityTarget) + { + return new ManualSetValue(botAI, nullptr); + } + + // Assign the new target + Unit* targetUnit = highestPriorityTarget->ToUnit(); + if (targetUnit) + { + return new ManualSetValue(botAI, targetUnit); + } + + return new ManualSetValue(botAI, nullptr); +} + +bool CastVigilanceAction::Execute(Event event) +{ + Unit* target = GetTarget(); + if (!target || target == bot) + return false; + + return botAI->CastSpell("vigilance", target); +} diff --git a/src/strategy/warrior/WarriorActions.h b/src/strategy/warrior/WarriorActions.h index 05505da0..38e14f89 100644 --- a/src/strategy/warrior/WarriorActions.h +++ b/src/strategy/warrior/WarriorActions.h @@ -135,4 +135,13 @@ public: bool isUseful() override; }; +class CastVigilanceAction : public BuffOnPartyAction +{ +public: + CastVigilanceAction(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, "vigilance") {} + + Value* GetTargetValue() override; + bool Execute(Event event) override; +}; + #endif diff --git a/src/strategy/warrior/WarriorAiObjectContext.cpp b/src/strategy/warrior/WarriorAiObjectContext.cpp index 71be13bf..365fe756 100644 --- a/src/strategy/warrior/WarriorAiObjectContext.cpp +++ b/src/strategy/warrior/WarriorAiObjectContext.cpp @@ -98,6 +98,8 @@ public: creators["intercept and far enemy"] = &WarriorTriggerFactoryInternal::intercept_and_far_enemy; creators["intercept and rage"] = &WarriorTriggerFactoryInternal::intercept_and_rage; // creators["slam"] = &WarriorTriggerFactoryInternal::slam; + + creators["vigilance"] = &WarriorTriggerFactoryInternal::vigilance; } private: @@ -166,6 +168,8 @@ private: static Trigger* revenge(PlayerbotAI* botAI) { return new RevengeAvailableTrigger(botAI); } static Trigger* sunder_armor(PlayerbotAI* botAI) { return new SunderArmorDebuffTrigger(botAI); } // static Trigger* slam(PlayerbotAI* ai) { return new SlamTrigger(ai); } + + static Trigger* vigilance(PlayerbotAI* botAI) { return new VigilanceTrigger(botAI); } }; class WarriorAiObjectContextInternal : public NamedObjectContext @@ -235,6 +239,7 @@ public: creators["heroic throw"] = &WarriorAiObjectContextInternal::heroic_throw; creators["heroic throw on snare target"] = &WarriorAiObjectContextInternal::heroic_throw_on_snare_target; creators["shattering throw"] = &WarriorAiObjectContextInternal::shattering_throw; + creators["vigilance"] = &WarriorAiObjectContextInternal::vigilance; } private: @@ -304,6 +309,7 @@ private: static Action* heroic_throw_on_snare_target(PlayerbotAI* botAI) { return new CastHeroicThrowSnareAction(botAI); } static Action* heroic_throw(PlayerbotAI* botAI) { return new CastHeroicThrowAction(botAI); } static Action* bladestorm(PlayerbotAI* botAI) { return new CastBladestormAction(botAI); } + static Action* vigilance(PlayerbotAI* botAI) { return new CastVigilanceAction(botAI); } }; WarriorAiObjectContext::WarriorAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) diff --git a/src/strategy/warrior/WarriorTriggers.cpp b/src/strategy/warrior/WarriorTriggers.cpp index f2ea13da..8a608690 100644 --- a/src/strategy/warrior/WarriorTriggers.cpp +++ b/src/strategy/warrior/WarriorTriggers.cpp @@ -12,3 +12,75 @@ bool BloodrageBuffTrigger::IsActive() return AI_VALUE2(uint8, "health", "self target") >= sPlayerbotAIConfig->mediumHealth && AI_VALUE2(uint8, "rage", "self target") < 20; } + +bool VigilanceTrigger::IsActive() +{ + if (!bot->HasSpell(50720)) + { + return false; + } + + Group* group = bot->GetGroup(); + if (!group) + { + return false; + } + + Player* currentVigilanceTarget = nullptr; + Player* mainTank = nullptr; + Player* assistTank1 = nullptr; + Player* assistTank2 = nullptr; + Player* highestGearScorePlayer = nullptr; + uint32 highestGearScore = 0; + + // Iterate once through the group to gather all necessary information + for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) + { + Player* member = ref->GetSource(); + if (!member || member == bot || !member->IsAlive()) + continue; + + // Check if member has Vigilance applied by the bot + if (!currentVigilanceTarget && botAI->HasAura("vigilance", member, false, true)) + { + currentVigilanceTarget = member; + } + + // Identify Main Tank + if (!mainTank && botAI->IsMainTank(member)) + { + mainTank = member; + } + + // Identify Assist Tanks + if (assistTank1 == nullptr && botAI->IsAssistTankOfIndex(member, 0)) + { + assistTank1 = member; + } + else if (assistTank2 == nullptr && botAI->IsAssistTankOfIndex(member, 1)) + { + assistTank2 = member; + } + + // Determine Highest Gear Score + uint32 gearScore = botAI->GetEquipGearScore(member, false, false); + if (gearScore > highestGearScore) + { + highestGearScore = gearScore; + highestGearScorePlayer = member; + } + } + + // Determine the highest-priority target + Player* highestPriorityTarget = mainTank ? mainTank : + (assistTank1 ? assistTank1 : + (assistTank2 ? assistTank2 : highestGearScorePlayer)); + + // Trigger if no Vigilance is active or the current target is not the highest-priority target + if (!currentVigilanceTarget || currentVigilanceTarget != highestPriorityTarget) + { + return true; + } + + return false; // No need to reassign Vigilance +} diff --git a/src/strategy/warrior/WarriorTriggers.h b/src/strategy/warrior/WarriorTriggers.h index 223e0049..3509ead7 100644 --- a/src/strategy/warrior/WarriorTriggers.h +++ b/src/strategy/warrior/WarriorTriggers.h @@ -63,6 +63,14 @@ public: RendDebuffTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "rend", 1, true) {} }; +class VigilanceTrigger : public BuffOnPartyTrigger +{ +public: + VigilanceTrigger(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, "vigilance") {} + + bool IsActive() override; +}; + // class SlamTrigger : public HasAuraTrigger // { // public: