From 7895e2ebf3b77b832d878da602641782d90dc9ba Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 14:37:19 +1100 Subject: [PATCH 01/20] Create BlessingManager.cpp --- src/strategy/paladin/BlessingManager.cpp | 332 +++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 src/strategy/paladin/BlessingManager.cpp diff --git a/src/strategy/paladin/BlessingManager.cpp b/src/strategy/paladin/BlessingManager.cpp new file mode 100644 index 000000000..d27c0c384 --- /dev/null +++ b/src/strategy/paladin/BlessingManager.cpp @@ -0,0 +1,332 @@ +#include "PlayerbotAI.h" +#include "Group.h" +#include "Player.h" +#include +#include +#include +#include + +// Minimal Blessing Type enum +enum GreaterBlessingType +{ + GREATER_BLESSING_OF_WISDOM, + GREATER_BLESSING_OF_MIGHT, + GREATER_BLESSING_OF_KINGS, + GREATER_BLESSING_OF_SANCTUARY +}; + +// A simple structure to hold which blessings each class should get, +// depending on how many Paladins are in the group. +static std::map>> BlessingTemplates = +{ + // 1 Paladin: everyone just gets Kings + { + 1, + { + { CLASS_WARRIOR, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_PALADIN, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_HUNTER, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_ROGUE, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_PRIEST, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_DEATH_KNIGHT, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_SHAMAN, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_MAGE, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_WARLOCK, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_DRUID, { GREATER_BLESSING_OF_KINGS } } + } + }, + // 2 Paladins: physical classes prefer Might, casters prefer Wisdom, all get Kings + { + 2, + { + { CLASS_WARRIOR, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PALADIN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_HUNTER, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_ROGUE, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PRIEST, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DEATH_KNIGHT, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_SHAMAN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_MAGE, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_WARLOCK, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DRUID, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + } + }, + // 3 Paladins: might see some Sanctuary usage as well + { + 3, + { + { CLASS_WARRIOR, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PALADIN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_HUNTER, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_ROGUE, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PRIEST, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DEATH_KNIGHT, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_SHAMAN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_MAGE, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_WARLOCK, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DRUID, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + } + }, + // 4 Paladins: basically everything is on the table + { + 4, + { + { CLASS_WARRIOR, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PALADIN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_HUNTER, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_ROGUE, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PRIEST, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DEATH_KNIGHT, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_SHAMAN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_MAGE, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_WARLOCK, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DRUID, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } } + } + } +}; + +// ------------------------------------------------------------------------- +// Simple helper to check if a Paladin has the required talent for the blessing +// (In your environment, replace HasTalent(SpellID, Spec) with the actual logic.) +// ------------------------------------------------------------------------- +static bool PaladinHasTalentForBlessing(Player* paladin, GreaterBlessingType blessing) +{ + switch (blessing) + { + case GREATER_BLESSING_OF_WISDOM: + // Improved Blessing of Wisdom (e.g., talent ID 20245) + return paladin->HasTalent(20245, paladin->GetActiveSpec()); + case GREATER_BLESSING_OF_MIGHT: + // Improved Blessing of Might (e.g., talent ID 20045) + return paladin->HasTalent(20045, paladin->GetActiveSpec()); + case GREATER_BLESSING_OF_SANCTUARY: + // Must have the Sanctuary talent (e.g., talent ID 20911) + return paladin->HasTalent(20911, paladin->GetActiveSpec()); + case GREATER_BLESSING_OF_KINGS: + // No talent required + return true; + default: + return false; + } +} + +// ------------------------------------------------------------------------- +// Gather all Paladins in the group/raid +// ------------------------------------------------------------------------- +static std::vector GetPaladinsInGroup(PlayerbotAI* botAI) +{ + std::vector paladins; + Player* bot = botAI->GetBot(); + + if (!bot) + return paladins; + + Group* group = bot->GetGroup(); + if (!group) + return paladins; + + for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) + { + Player* member = ref->GetSource(); + if (member && member->IsInWorld() && member->getClass() == CLASS_PALADIN) + paladins.push_back(member); + } + + return paladins; +} + +// ------------------------------------------------------------------------- +// Core function: AssignBlessingsForGroup +// Returns a map from (Paladin Player*) -> (set of (classId -> assigned blessing)). +// The logic is “one greater blessing per class per paladin,” assigned in order +// of talent preference. +// ------------------------------------------------------------------------- +std::map> AssignBlessingsForGroup(PlayerbotAI* botAI) +{ + std::map> results; + + // Get relevant Paladins + std::vector paladins = GetPaladinsInGroup(botAI); + int numPaladins = std::min(static_cast(paladins.size()), 4); + if (numPaladins == 0) + { + // No paladins -> empty map + return results; + } + + // Find which template we’ll use + auto templIt = BlessingTemplates.find(numPaladins); + if (templIt == BlessingTemplates.end()) + { + // If no valid template, return empty + return results; + } + + auto& classToBlessings = templIt->second; + + // Categorize Paladins by which improved blessings they can cast + std::vector paladinsWithSanctuary; + std::vector paladinsWithMight; + std::vector paladinsWithWisdom; + std::vector paladinsWithoutImprovements; // can only cast Kings or unimproved Might/Wisdom + + for (Player* pal : paladins) + { + bool canSanctuary = PaladinHasTalentForBlessing(pal, GREATER_BLESSING_OF_SANCTUARY); + bool canMight = PaladinHasTalentForBlessing(pal, GREATER_BLESSING_OF_MIGHT); + bool canWisdom = PaladinHasTalentForBlessing(pal, GREATER_BLESSING_OF_WISDOM); + + if (canSanctuary) paladinsWithSanctuary.push_back(pal); + if (canMight) paladinsWithMight.push_back(pal); + if (canWisdom) paladinsWithWisdom.push_back(pal); + + if (!canSanctuary && !canMight && !canWisdom) + paladinsWithoutImprovements.push_back(pal); + } + + // Keep track of which class each Paladin has already assigned + // so we don't assign multiple blessings from the same Paladin to the same class. + std::map> paladinAssignedClasses; + + // Go through each class in the template, then each desired blessing, in order + for (auto& [classId, blessingsVec] : classToBlessings) + { + for (GreaterBlessingType b : blessingsVec) + { + Player* assignedPaladin = nullptr; + + // Attempt assignment depending on talent priority + switch (b) + { + case GREATER_BLESSING_OF_SANCTUARY: + { + // Try paladins with the Sanctuary talent + for (Player* pal : paladinsWithSanctuary) + { + if (!paladinAssignedClasses[pal].count(classId)) + { + assignedPaladin = pal; + paladinAssignedClasses[pal].insert(classId); + break; + } + } + break; + } + case GREATER_BLESSING_OF_MIGHT: + { + // First try paladins with Improved Might + for (Player* pal : paladinsWithMight) + { + if (!paladinAssignedClasses[pal].count(classId)) + { + assignedPaladin = pal; + paladinAssignedClasses[pal].insert(classId); + break; + } + } + // Otherwise, try “no improvement” paladins + if (!assignedPaladin) + { + for (Player* pal : paladinsWithoutImprovements) + { + if (!paladinAssignedClasses[pal].count(classId)) + { + assignedPaladin = pal; + paladinAssignedClasses[pal].insert(classId); + break; + } + } + } + // Lastly, if still unassigned, pick any Paladin + if (!assignedPaladin) + { + for (Player* pal : paladins) + { + if (!paladinAssignedClasses[pal].count(classId)) + { + assignedPaladin = pal; + paladinAssignedClasses[pal].insert(classId); + break; + } + } + } + break; + } + case GREATER_BLESSING_OF_WISDOM: + { + // First try paladins with Improved Wisdom + for (Player* pal : paladinsWithWisdom) + { + if (!paladinAssignedClasses[pal].count(classId)) + { + assignedPaladin = pal; + paladinAssignedClasses[pal].insert(classId); + break; + } + } + // Otherwise, try “no improvement” paladins + if (!assignedPaladin) + { + for (Player* pal : paladinsWithoutImprovements) + { + if (!paladinAssignedClasses[pal].count(classId)) + { + assignedPaladin = pal; + paladinAssignedClasses[pal].insert(classId); + break; + } + } + } + // Lastly, if still unassigned, pick any Paladin + if (!assignedPaladin) + { + for (Player* pal : paladins) + { + if (!paladinAssignedClasses[pal].count(classId)) + { + assignedPaladin = pal; + paladinAssignedClasses[pal].insert(classId); + break; + } + } + } + break; + } + case GREATER_BLESSING_OF_KINGS: + { + // Anyone can cast Kings, so pick a paladin who hasn’t assigned that class yet + // Try “no improvement” paladins first if you want them to focus on Kings + for (Player* pal : paladinsWithoutImprovements) + { + if (!paladinAssignedClasses[pal].count(classId)) + { + assignedPaladin = pal; + paladinAssignedClasses[pal].insert(classId); + break; + } + } + // If not found, pick any paladin + if (!assignedPaladin) + { + for (Player* pal : paladins) + { + if (!paladinAssignedClasses[pal].count(classId)) + { + assignedPaladin = pal; + paladinAssignedClasses[pal].insert(classId); + break; + } + } + } + break; + } + } + + // If we found a Paladin, record it in the results + if (assignedPaladin) + results[assignedPaladin][classId] = b; + } + } + + return results; // (Paladin -> (classId -> Blessing)) for the entire group +} From c0132f75519e7d915dbeccf5efac7908edc8022c Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 14:59:51 +1100 Subject: [PATCH 02/20] Create BlessingManager.h --- src/strategy/paladin/BlessingManager.h | 111 +++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 src/strategy/paladin/BlessingManager.h diff --git a/src/strategy/paladin/BlessingManager.h b/src/strategy/paladin/BlessingManager.h new file mode 100644 index 000000000..5f8a2567d --- /dev/null +++ b/src/strategy/paladin/BlessingManager.h @@ -0,0 +1,111 @@ +#ifndef _BLESSING_ASSIGNMENT_H_ +#define _BLESSING_ASSIGNMENT_H_ + +#include "PlayerbotAI.h" +#include "Group.h" +#include "Player.h" + +#include +#include +#include +#include + +// ----------------------------------------------------------------------------- +// Minimal Blessing Type enum +// ----------------------------------------------------------------------------- +enum GreaterBlessingType +{ + GREATER_BLESSING_OF_WISDOM, + GREATER_BLESSING_OF_MIGHT, + GREATER_BLESSING_OF_KINGS, + GREATER_BLESSING_OF_SANCTUARY +}; + +// ----------------------------------------------------------------------------- +// A simple structure to hold which blessings each class should get, +// depending on how many Paladins are in the group. +// Using 'inline static' ensures there's exactly one definition in the program. +// ----------------------------------------------------------------------------- +inline static std::map>> BlessingTemplates = +{ + // 1 Paladin: everyone just gets Kings + { + 1, + { + { CLASS_WARRIOR, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_PALADIN, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_HUNTER, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_ROGUE, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_PRIEST, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_DEATH_KNIGHT, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_SHAMAN, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_MAGE, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_WARLOCK, { GREATER_BLESSING_OF_KINGS } }, + { CLASS_DRUID, { GREATER_BLESSING_OF_KINGS } } + } + }, + // 2 Paladins: physical classes prefer Might, casters prefer Wisdom, all get Kings + { + 2, + { + { CLASS_WARRIOR, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PALADIN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_HUNTER, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_ROGUE, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PRIEST, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DEATH_KNIGHT, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_SHAMAN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_MAGE, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_WARLOCK, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DRUID, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } } + } + }, + // 3 Paladins: might see some Sanctuary usage as well + { + 3, + { + { CLASS_WARRIOR, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PALADIN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_HUNTER, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_KINGS } }, + { CLASS_ROGUE, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PRIEST, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DEATH_KNIGHT, { GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_SHAMAN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } }, + { CLASS_MAGE, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_WARLOCK, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DRUID, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_KINGS } } + } + }, + // 4 Paladins: basically everything is on the table + { + 4, + { + { CLASS_WARRIOR, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PALADIN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_HUNTER, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_ROGUE, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_PRIEST, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DEATH_KNIGHT, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_SHAMAN, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_MAGE, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_WARLOCK, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } }, + { CLASS_DRUID, { GREATER_BLESSING_OF_WISDOM, GREATER_BLESSING_OF_MIGHT, GREATER_BLESSING_OF_SANCTUARY, GREATER_BLESSING_OF_KINGS } } + } + } +}; + +// ----------------------------------------------------------------------------- +// Function Prototypes +// ----------------------------------------------------------------------------- + +// Checks if a Paladin has the talent required to cast the given blessing. +bool PaladinHasTalentForBlessing(Player* paladin, GreaterBlessingType blessing); + +// Returns all Paladins (Player*) in the same group/raid as the bot. +std::vector GetPaladinsInGroup(PlayerbotAI* botAI); + +// Main function to assign blessings for the current group/raid. +// Returns a map of (Paladin pointer) -> (classId -> assigned blessing). +std::map> AssignBlessingsForGroup(PlayerbotAI* botAI); + +#endif // _BLESSING_ASSIGNMENT_H_ From 104f486630e73c5aa1bb5603dc9c22cc7b3869dc Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 15:34:17 +1100 Subject: [PATCH 03/20] Create CastGreaterBlessingTrigger --- src/strategy/paladin/PaladinTriggers.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/strategy/paladin/PaladinTriggers.h b/src/strategy/paladin/PaladinTriggers.h index 37ba64706..31cc2f55a 100644 --- a/src/strategy/paladin/PaladinTriggers.h +++ b/src/strategy/paladin/PaladinTriggers.h @@ -239,4 +239,12 @@ class AvengingWrathTrigger : public BoostTrigger public: AvengingWrathTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "avenging wrath") {} }; + +class CastGreaterBlessingTrigger : public Trigger +{ +public: + CastGreaterBlessingTrigger(PlayerbotAI* botAI) : Trigger(botAI, "cast greater blessing") { } + + bool IsActive() override; +}; #endif From 8f71551fb77aa365366622df45bff3293db206ad Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 15:34:30 +1100 Subject: [PATCH 04/20] Create CastGreaterBlessingTrigger --- src/strategy/paladin/PaladinTriggers.cpp | 69 ++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/strategy/paladin/PaladinTriggers.cpp b/src/strategy/paladin/PaladinTriggers.cpp index 14cd3b2bd..afd95c766 100644 --- a/src/strategy/paladin/PaladinTriggers.cpp +++ b/src/strategy/paladin/PaladinTriggers.cpp @@ -4,6 +4,7 @@ */ #include "PaladinTriggers.h" +#include "BlessingManager.h" #include "PaladinActions.h" #include "PlayerbotAIConfig.h" @@ -30,3 +31,71 @@ bool BlessingTrigger::IsActive() return SpellTrigger::IsActive() && !botAI->HasAnyAuraOf(target, "blessing of might", "blessing of wisdom", "blessing of kings", "blessing of sanctuary", nullptr); } + +bool CastGreaterBlessingTrigger::IsActive() +{ + Player* bot = botAI->GetBot(); + if (!bot) + return false; + + Group* group = bot->GetGroup(); + if (!group) + return false; + + // Require at least 6 total members (the bot plus 5 others), or an explicit raid check + if (group->GetMembersCount() <= 5 && !group->isRaidGroup()) + return false; + + // Get the blessing distribution for all Paladins + auto assignment = AssignBlessingsForGroup(botAI); + + // Find the assigned blessings for *this* Paladin + auto palIt = assignment.find(bot); + if (palIt == assignment.end()) + return false; // This Paladin has no assigned blessings + + // For each (class -> blessing) assigned to our bot, + // see if at least one raid member of that class is missing the aura + for (auto& kv : palIt->second) + { + uint8 classId = kv.first; + GreaterBlessingType gBlessing = kv.second; + + // Convert that blessing to a relevant aura name + std::string auraName; + switch (gBlessing) + { + case GREATER_BLESSING_OF_MIGHT: + auraName = "greater blessing of might"; + break; + case GREATER_BLESSING_OF_WISDOM: + auraName = "greater blessing of wisdom"; + break; + case GREATER_BLESSING_OF_KINGS: + auraName = "greater blessing of kings"; + break; + case GREATER_BLESSING_OF_SANCTUARY: + auraName = "greater blessing of sanctuary"; + break; + } + + // Scan raid members + for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) + { + Player* member = ref->GetSource(); + if (!member || !member->IsInWorld()) + continue; + + // Check if the member's class matches the assigned class + if (member->getClass() == classId) + { + // Check if the member *lacks* the aura + if (!botAI->HasAura(auraName, member)) + return true; // Found a target missing the assigned Greater Blessing + } + } + } + + // No missing blessings found + return false; +} From 2951e76052593e4d5a4195d005e85fd02d93b874 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 15:34:45 +1100 Subject: [PATCH 05/20] Create CastGreaterBlessingAction --- src/strategy/paladin/PaladinActions.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/strategy/paladin/PaladinActions.h b/src/strategy/paladin/PaladinActions.h index 17fe052b3..7a4afaa60 100644 --- a/src/strategy/paladin/PaladinActions.h +++ b/src/strategy/paladin/PaladinActions.h @@ -424,4 +424,13 @@ class CastCancelDivineSacrificeAction : public Action bool Execute(Event event) override; bool isUseful() override; }; + +class CastGreaterBlessingAction : public Action +{ +public: + CastGreaterBlessingAction(PlayerbotAI* botAI) : Action(botAI, "cast greater blessing") { } + + bool Execute(Event event) override; +}; + #endif From 951b246970b4c101d7f4fb946d270fad64bc8bc6 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 15:34:54 +1100 Subject: [PATCH 06/20] Create CastGreaterBlessingAction --- src/strategy/paladin/PaladinActions.cpp | 72 ++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/src/strategy/paladin/PaladinActions.cpp b/src/strategy/paladin/PaladinActions.cpp index 1b5e46c0a..c0c16d859 100644 --- a/src/strategy/paladin/PaladinActions.cpp +++ b/src/strategy/paladin/PaladinActions.cpp @@ -4,6 +4,7 @@ */ #include "PaladinActions.h" +#include "BlessingManager.h" #include "AiFactory.h" #include "Event.h" @@ -169,4 +170,73 @@ bool CastCancelDivineSacrificeAction::Execute(Event event) bool CastCancelDivineSacrificeAction::isUseful() { return botAI->HasAura("divine sacrifice", GetTarget(), false, true, -1, true); -} \ No newline at end of file +} + +bool CastGreaterBlessingAction::Execute(Event event) +{ + Player* bot = botAI->GetBot(); + if (!bot) + return false; + + Group* group = bot->GetGroup(); + if (!group) + return false; + + // Gather assignments + auto assignment = AssignBlessingsForGroup(botAI); + + // Find what is assigned to *this* Paladin + auto paladinIt = assignment.find(bot); + if (paladinIt == assignment.end()) + return false; // No blessings assigned + + // For each (class -> blessing) assigned, search for a player missing it + for (auto& kv : paladinIt->second) + { + uint8 classId = kv.first; + GreaterBlessingType gBlessing = kv.second; + + // Convert the blessing to a spell name + std::string spellName; + std::string auraName; + switch (gBlessing) + { + case GREATER_BLESSING_OF_MIGHT: + spellName = "greater blessing of might"; + auraName = "greater blessing of might"; + break; + case GREATER_BLESSING_OF_WISDOM: + spellName = "greater blessing of wisdom"; + auraName = "greater blessing of wisdom"; + break; + case GREATER_BLESSING_OF_KINGS: + spellName = "greater blessing of kings"; + auraName = "greater blessing of kings"; + break; + case GREATER_BLESSING_OF_SANCTUARY: + spellName = "greater blessing of sanctuary"; + auraName = "greater blessing of sanctuary"; + break; + } + + // Find the first raid member of that class who lacks the aura + for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) + { + Player* member = ref->GetSource(); + if (!member || !member->IsInWorld()) + continue; + + if (member->getClass() == classId && !botAI->HasAura(auraName, member)) + { + // Found a target + botAI->TellMaster("Casting " + spellName + " on " + member->GetName()); + bool casted = botAI->CastSpell(spellName, member); + // Return true as soon as we cast a single Greater Blessing + return casted; + } + } + } + + // If we reach here, we didn't find any missing aura + return false; +} From b24fa24c7bb1e53207dea35f34302e73f1935043 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 15:35:10 +1100 Subject: [PATCH 07/20] Create PaladinBuffGreaterBlessingStrategy --- src/strategy/paladin/PaladinBuffStrategies.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/strategy/paladin/PaladinBuffStrategies.h b/src/strategy/paladin/PaladinBuffStrategies.h index f16707cf8..fa7da8c68 100644 --- a/src/strategy/paladin/PaladinBuffStrategies.h +++ b/src/strategy/paladin/PaladinBuffStrategies.h @@ -109,4 +109,13 @@ class PaladinFireResistanceStrategy : public Strategy std::string const getName() override { return "rfire"; } }; +class PaladinBuffGreaterBlessingStrategy : public Strategy +{ +public: + PaladinBuffGreaterBlessingStrategy(PlayerbotAI* botAI) : Strategy(botAI) {} + + void InitTriggers(std::vector& triggers) override; + std::string const getName() override { return "bgreater"; } +}; + #endif From f1282cfbe7031b8a74636270275fefa16bb1e189 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 15:35:23 +1100 Subject: [PATCH 08/20] Create PaladinBuffGreaterBlessingStrategy --- src/strategy/paladin/PaladinBuffStrategies.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/strategy/paladin/PaladinBuffStrategies.cpp b/src/strategy/paladin/PaladinBuffStrategies.cpp index 01aa6ffcf..5f53e570d 100644 --- a/src/strategy/paladin/PaladinBuffStrategies.cpp +++ b/src/strategy/paladin/PaladinBuffStrategies.cpp @@ -86,3 +86,18 @@ void PaladinBuffStatsStrategy::InitTriggers(std::vector& triggers) // triggers.push_back(new TriggerNode("blessing", NextAction::array(0, new NextAction("blessing of kings", // ACTION_HIGH + 8), nullptr))); } + +void PaladinBuffGreaterBlessingStrategy::InitTriggers(std::vector& triggers) +{ + // The "cast greater blessing" trigger is the one you wrote that checks: + // - Are we in a large group/raid? + // - Do we have any assigned Greater Blessings that are missing on a raid member? + // If so, it returns true (active). + // Then the action is "cast greater blessing," which attempts to find a target and cast. + + triggers.push_back(new TriggerNode( + "cast greater blessing", // The name you gave to your custom trigger + NextAction::array(0, + new NextAction("cast greater blessing", 10.0f), // 10.0f = priority, tweak as you like + nullptr))); +} From 91712de394df355d3a37f058e34d7a81b7ef1d95 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 15:36:16 +1100 Subject: [PATCH 09/20] Created bgreater strat and trigger/action contexts --- src/strategy/paladin/PaladinAiObjectContext.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/strategy/paladin/PaladinAiObjectContext.cpp b/src/strategy/paladin/PaladinAiObjectContext.cpp index 42e89a8a3..a0f82331e 100644 --- a/src/strategy/paladin/PaladinAiObjectContext.cpp +++ b/src/strategy/paladin/PaladinAiObjectContext.cpp @@ -68,6 +68,7 @@ class PaladinBuffStrategyFactoryInternal : public NamedObjectContext creators["bmana"] = &PaladinBuffStrategyFactoryInternal::bmana; creators["bdps"] = &PaladinBuffStrategyFactoryInternal::bdps; creators["bstats"] = &PaladinBuffStrategyFactoryInternal::bstats; + creators["bgreater"] = &PaladinBuffStrategyFactoryInternal::bgreater; } private: @@ -75,6 +76,8 @@ class PaladinBuffStrategyFactoryInternal : public NamedObjectContext static Strategy* bmana(PlayerbotAI* botAI) { return new PaladinBuffManaStrategy(botAI); } static Strategy* bdps(PlayerbotAI* botAI) { return new PaladinBuffDpsStrategy(botAI); } static Strategy* bstats(PlayerbotAI* botAI) { return new PaladinBuffStatsStrategy(botAI); } + + static Strategy* bgreater(PlayerbotAI* botAI) { return new PaladinBuffGreaterBlessingStrategy(botAI); } }; class PaladinCombatStrategyFactoryInternal : public NamedObjectContext @@ -142,6 +145,8 @@ class PaladinTriggerFactoryInternal : public NamedObjectContext creators["blessing of might on party"] = &PaladinTriggerFactoryInternal::blessing_of_might_on_party; creators["avenging wrath"] = &PaladinTriggerFactoryInternal::avenging_wrath; + creators["cast greater blessing"] = &PaladinTriggerFactoryInternal::cast_greater_blessing; + } private: @@ -208,6 +213,8 @@ class PaladinTriggerFactoryInternal : public NamedObjectContext static Trigger* blessing_of_might_on_party(PlayerbotAI* botAI) { return new BlessingOfMightOnPartyTrigger(botAI); } static Trigger* avenging_wrath(PlayerbotAI* botAI) { return new AvengingWrathTrigger(botAI); } + static Trigger* cast_greater_blessing(PlayerbotAI* botAI) { return new CastGreaterBlessingTrigger(botAI); } + }; class PaladinAiObjectContextInternal : public NamedObjectContext @@ -294,6 +301,7 @@ class PaladinAiObjectContextInternal : public NamedObjectContext creators["divine illumination"] = &PaladinAiObjectContextInternal::divine_illumination; creators["divine sacrifice"] = &PaladinAiObjectContextInternal::divine_sacrifice; creators["cancel divine sacrifice"] = &PaladinAiObjectContextInternal::cancel_divine_sacrifice; + creators["cast greater blessing"] = &PaladinAiObjectContextInternal::cast_greater_blessing; } private: @@ -395,6 +403,7 @@ class PaladinAiObjectContextInternal : public NamedObjectContext static Action* divine_illumination(PlayerbotAI* ai) { return new CastDivineIlluminationAction(ai); } static Action* divine_sacrifice(PlayerbotAI* ai) { return new CastDivineSacrificeAction(ai); } static Action* cancel_divine_sacrifice(PlayerbotAI* ai) { return new CastCancelDivineSacrificeAction(ai); } + static Action* cast_greater_blessing(PlayerbotAI* ai) { return new CastGreaterBlessingAction(ai); } }; PaladinAiObjectContext::PaladinAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) From 2679b851d4b22a644e222250d4515c010a7c3f20 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 16:16:42 +1100 Subject: [PATCH 10/20] Add to Paladin default strats --- src/AiFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index 57b4068c7..c07cd1b13 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -530,7 +530,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const else nonCombatEngine->addStrategiesNoInit("dps assist", "bdps", "baoe", nullptr); - nonCombatEngine->addStrategiesNoInit("cure", nullptr); + nonCombatEngine->addStrategiesNoInit("cure", "bgreater", nullptr); break; case CLASS_HUNTER: nonCombatEngine->addStrategiesNoInit("bdps", "dps assist", "pet", nullptr); From 2461cb3742337a059521d165b40381d10cc76bc6 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 17:32:46 +1100 Subject: [PATCH 11/20] Gift/Mark of the Wild --- src/strategy/druid/DruidActions.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/strategy/druid/DruidActions.cpp b/src/strategy/druid/DruidActions.cpp index 1743a3395..9466071b0 100644 --- a/src/strategy/druid/DruidActions.cpp +++ b/src/strategy/druid/DruidActions.cpp @@ -78,4 +78,25 @@ Unit* CastRejuvenationOnNotFullAction::GetTarget() bool CastRejuvenationOnNotFullAction::isUseful() { return GetTarget(); -} \ No newline at end of file +} + +bool CastMarkOfTheWildOnPartyAction::Execute(Event event) +{ + Unit* target = GetTarget(); + if (!target) + return false; + + // Is the bot in a group? + Group* group = botAI->GetBot()->GetGroup(); + if (group) + { + // If the bot can cast "gift of the wild" on this target, do so + if (botAI->CanCastSpell("gift of the wild", target)) + { + return botAI->CastSpell("gift of the wild", target); + } + } + + // Otherwise, fall back to single-target "mark of the wild" + return botAI->CastSpell("mark of the wild", target); +} From 058a34e2163e9e4b7d8ab29f98fdc122f7e09a87 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 17:32:50 +1100 Subject: [PATCH 12/20] Gift/Mark of the Wild --- src/strategy/druid/DruidActions.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/strategy/druid/DruidActions.h b/src/strategy/druid/DruidActions.h index ee90788a0..1a08dd67d 100644 --- a/src/strategy/druid/DruidActions.h +++ b/src/strategy/druid/DruidActions.h @@ -95,7 +95,9 @@ class CastMarkOfTheWildAction : public CastBuffSpellAction class CastMarkOfTheWildOnPartyAction : public BuffOnPartyAction { public: - CastMarkOfTheWildOnPartyAction(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, "mark of the wild") {} + CastMarkOfTheWildOnPartyAction(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, "gift of the wild") {} + + bool Execute(Event event) override; }; class CastSurvivalInstinctsAction : public CastBuffSpellAction From 9acf1635649242646212419e0a4be8ef4eb4fb77 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 17:32:53 +1100 Subject: [PATCH 13/20] Gift/Mark of the Wild --- src/strategy/druid/DruidTriggers.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/strategy/druid/DruidTriggers.cpp b/src/strategy/druid/DruidTriggers.cpp index a083ade15..69865770e 100644 --- a/src/strategy/druid/DruidTriggers.cpp +++ b/src/strategy/druid/DruidTriggers.cpp @@ -9,12 +9,16 @@ bool MarkOfTheWildOnPartyTrigger::IsActive() { - return BuffOnPartyTrigger::IsActive() && !botAI->HasAura("gift of the wild", GetTarget()); + // Check both Gift & Mark auras + return BuffOnPartyTrigger::IsActive() && + !botAI->HasAnyAuraOf(GetTarget(), "gift of the wild", "mark of the wild", nullptr); } bool MarkOfTheWildTrigger::IsActive() { - return BuffTrigger::IsActive() && !botAI->HasAura("gift of the wild", GetTarget()); + // Same check for single-target scenario + return BuffTrigger::IsActive() && + !botAI->HasAnyAuraOf(GetTarget(), "gift of the wild", "mark of the wild", nullptr); } bool ThornsOnPartyTrigger::IsActive() From 4eb302b95e60e8cd11817dbbee0a0e47f523e835 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 18:16:24 +1100 Subject: [PATCH 14/20] Prayer of Fortitude --- src/strategy/priest/PriestActions.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/strategy/priest/PriestActions.cpp b/src/strategy/priest/PriestActions.cpp index 2364a5e2d..33b3842a0 100644 --- a/src/strategy/priest/PriestActions.cpp +++ b/src/strategy/priest/PriestActions.cpp @@ -105,4 +105,21 @@ Unit* CastPowerWordShieldOnNotFullAction::GetTarget() bool CastPowerWordShieldOnNotFullAction::isUseful() { return GetTarget(); -} \ No newline at end of file +} + +bool CastPowerWordFortitudeAction::Execute(Event event) +{ + Unit* target = GetTarget(); + if (!target) + return false; + + // If in a group, try Prayer first + Group* group = botAI->GetBot()->GetGroup(); + if (group && botAI->CanCastSpell("prayer of fortitude", target)) + { + return botAI->CastSpell("prayer of fortitude", target); + } + + // Otherwise do normal single-target + return botAI->CastSpell("power word: fortitude", target); +} From 34210e0508d7c30b8bab477d98ddaa872791a5b8 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 18:16:33 +1100 Subject: [PATCH 15/20] Prayer of Fortitude --- src/strategy/priest/PriestActions.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/strategy/priest/PriestActions.h b/src/strategy/priest/PriestActions.h index c84bfc7df..400e9b0b4 100644 --- a/src/strategy/priest/PriestActions.h +++ b/src/strategy/priest/PriestActions.h @@ -14,7 +14,7 @@ class PlayerbotAI; // disc BUFF_ACTION(CastPowerWordFortitudeAction, "power word: fortitude"); -BUFF_PARTY_ACTION(CastPowerWordFortitudeOnPartyAction, "power word: fortitude"); +// BUFF_PARTY_ACTION(CastPowerWordFortitudeOnPartyAction, "power word: fortitude"); BUFF_PARTY_ACTION(CastPrayerOfFortitudeOnPartyAction, "prayer of fortitude"); BUFF_ACTION(CastPowerWordShieldAction, "power word: shield"); @@ -210,4 +210,11 @@ class CastGuardianSpiritOnPartyAction : public HealPartyMemberAction CastGuardianSpiritOnPartyAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "guardian spirit", 40.0f, HealingManaEfficiency::MEDIUM) {} }; +class CastPowerWordFortitudeOnPartyAction : public BuffOnPartyAction +{ +public: + CastPowerWordFortitudeOnPartyAction(PlayerbotAI* ai) : BuffOnPartyAction(ai, "power word: fortitude") {} + bool Execute(Event event) override; +}; + #endif From 626cf44ad52c8fe0dde77b0e9ecca37934035962 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 18:18:37 +1100 Subject: [PATCH 16/20] OnParty --- src/strategy/priest/PriestActions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/strategy/priest/PriestActions.cpp b/src/strategy/priest/PriestActions.cpp index 33b3842a0..89d4ebb19 100644 --- a/src/strategy/priest/PriestActions.cpp +++ b/src/strategy/priest/PriestActions.cpp @@ -107,7 +107,7 @@ bool CastPowerWordShieldOnNotFullAction::isUseful() return GetTarget(); } -bool CastPowerWordFortitudeAction::Execute(Event event) +bool CastPowerWordFortitudeOnPartyAction::Execute(Event event) { Unit* target = GetTarget(); if (!target) From 3899ebd4a927b1fe8e35a3c40b3502d7a0fbd7c7 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 18:45:12 +1100 Subject: [PATCH 17/20] Arcane Brilliance --- src/strategy/mage/MageActions.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/strategy/mage/MageActions.cpp b/src/strategy/mage/MageActions.cpp index beb826368..e12305d0a 100644 --- a/src/strategy/mage/MageActions.cpp +++ b/src/strategy/mage/MageActions.cpp @@ -21,3 +21,24 @@ bool CastConeOfColdAction::isUseful() bool targetClose = sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", GetTargetName()), 10.f); return facingTarget && targetClose; } + +bool CastArcaneIntellectOnPartyAction::Execute(Event event) +{ + Unit* target = GetTarget(); + if (!target) + return false; + + Group* group = botAI->GetBot()->GetGroup(); + + if (group) + { + if (botAI->CanCastSpell("dalaran brilliance", target)) + return botAI->CastSpell("dalaran brilliance", target); + + if (botAI->CanCastSpell("arcane brilliance", target)) + return botAI->CastSpell("arcane brilliance", target); + } + + // If not in a group or we cannot cast brilliance, fall back to arcane intellect + return botAI->CastSpell("arcane intellect", target); +} From bc4842d9b24b99af1bd191c8bcab58f1fcf09301 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 18:45:23 +1100 Subject: [PATCH 18/20] Arcane Brilliance --- src/strategy/mage/MageActions.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/strategy/mage/MageActions.h b/src/strategy/mage/MageActions.h index 844bea670..0fa907603 100644 --- a/src/strategy/mage/MageActions.h +++ b/src/strategy/mage/MageActions.h @@ -120,6 +120,7 @@ class CastArcaneIntellectOnPartyAction : public BuffOnPartyAction { public: CastArcaneIntellectOnPartyAction(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, "arcane intellect") {} + bool Execute(Event event) override; }; class CastRemoveCurseAction : public CastCureSpellAction From 39a1fd25d2f968558c3425b57145ea50487487a1 Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 18:45:38 +1100 Subject: [PATCH 19/20] Arcane Brilliance --- src/strategy/mage/MageTriggers.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/strategy/mage/MageTriggers.cpp b/src/strategy/mage/MageTriggers.cpp index 95c22e4df..6513c6bda 100644 --- a/src/strategy/mage/MageTriggers.cpp +++ b/src/strategy/mage/MageTriggers.cpp @@ -10,12 +10,14 @@ bool ArcaneIntellectOnPartyTrigger::IsActive() { - return BuffOnPartyTrigger::IsActive() && !botAI->HasAura("arcane brilliance", GetTarget()); + return BuffOnPartyTrigger::IsActive() && + !botAI->HasAnyAuraOf(GetTarget(), "arcane brilliance", "arcane intellect", "dalaran brilliance", nullptr); } bool ArcaneIntellectTrigger::IsActive() { - return BuffTrigger::IsActive() && !botAI->HasAura("arcane brilliance", GetTarget()); + return BuffOnPartyTrigger::IsActive() && + !botAI->HasAnyAuraOf(GetTarget(), "arcane brilliance", "arcane intellect", "dalaran brilliance", nullptr); } bool MageArmorTrigger::IsActive() From 7392c5551a5e728baf0ad58026365e9722ce9a0c Mon Sep 17 00:00:00 2001 From: avirar Date: Sat, 4 Jan 2025 18:51:23 +1100 Subject: [PATCH 20/20] BuffTrigger instead of OnParty --- src/strategy/mage/MageTriggers.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/strategy/mage/MageTriggers.cpp b/src/strategy/mage/MageTriggers.cpp index 6513c6bda..85afe9578 100644 --- a/src/strategy/mage/MageTriggers.cpp +++ b/src/strategy/mage/MageTriggers.cpp @@ -11,13 +11,15 @@ bool ArcaneIntellectOnPartyTrigger::IsActive() { return BuffOnPartyTrigger::IsActive() && - !botAI->HasAnyAuraOf(GetTarget(), "arcane brilliance", "arcane intellect", "dalaran brilliance", nullptr); + !botAI->HasAnyAuraOf(GetTarget(), "arcane brilliance", "arcane intellect", "dalaran brilliance", + "dalaran intellect", nullptr); } bool ArcaneIntellectTrigger::IsActive() { - return BuffOnPartyTrigger::IsActive() && - !botAI->HasAnyAuraOf(GetTarget(), "arcane brilliance", "arcane intellect", "dalaran brilliance", nullptr); + return BuffTrigger::IsActive() && + !botAI->HasAnyAuraOf(GetTarget(), "arcane brilliance", "arcane intellect", "dalaran brilliance", + "dalaran intellect", nullptr); } bool MageArmorTrigger::IsActive()