mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Merge pull request #849 from liyunfan1223/revert-844-paladin_blessings2
Revert "Paladins use Greater Blessings"
This commit is contained in:
@@ -530,7 +530,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const
|
||||
else
|
||||
nonCombatEngine->addStrategiesNoInit("dps assist", "bdps", "baoe", nullptr);
|
||||
|
||||
nonCombatEngine->addStrategiesNoInit("cure", "bgreater", nullptr);
|
||||
nonCombatEngine->addStrategiesNoInit("cure", nullptr);
|
||||
break;
|
||||
case CLASS_HUNTER:
|
||||
nonCombatEngine->addStrategiesNoInit("bdps", "dps assist", "pet", nullptr);
|
||||
|
||||
@@ -78,25 +78,4 @@ Unit* CastRejuvenationOnNotFullAction::GetTarget()
|
||||
bool CastRejuvenationOnNotFullAction::isUseful()
|
||||
{
|
||||
return GetTarget();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -95,9 +95,7 @@ public:
|
||||
class CastMarkOfTheWildOnPartyAction : public BuffOnPartyAction
|
||||
{
|
||||
public:
|
||||
CastMarkOfTheWildOnPartyAction(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, "gift of the wild") {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
CastMarkOfTheWildOnPartyAction(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, "mark of the wild") {}
|
||||
};
|
||||
|
||||
class CastSurvivalInstinctsAction : public CastBuffSpellAction
|
||||
|
||||
@@ -9,16 +9,12 @@
|
||||
|
||||
bool MarkOfTheWildOnPartyTrigger::IsActive()
|
||||
{
|
||||
// Check both Gift & Mark auras
|
||||
return BuffOnPartyTrigger::IsActive() &&
|
||||
!botAI->HasAnyAuraOf(GetTarget(), "gift of the wild", "mark of the wild", nullptr);
|
||||
return BuffOnPartyTrigger::IsActive() && !botAI->HasAura("gift of the wild", GetTarget());
|
||||
}
|
||||
|
||||
bool MarkOfTheWildTrigger::IsActive()
|
||||
{
|
||||
// Same check for single-target scenario
|
||||
return BuffTrigger::IsActive() &&
|
||||
!botAI->HasAnyAuraOf(GetTarget(), "gift of the wild", "mark of the wild", nullptr);
|
||||
return BuffTrigger::IsActive() && !botAI->HasAura("gift of the wild", GetTarget());
|
||||
}
|
||||
|
||||
bool ThornsOnPartyTrigger::IsActive()
|
||||
|
||||
@@ -21,24 +21,3 @@ 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);
|
||||
}
|
||||
|
||||
@@ -120,7 +120,6 @@ class CastArcaneIntellectOnPartyAction : public BuffOnPartyAction
|
||||
{
|
||||
public:
|
||||
CastArcaneIntellectOnPartyAction(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, "arcane intellect") {}
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class CastRemoveCurseAction : public CastCureSpellAction
|
||||
|
||||
@@ -10,16 +10,12 @@
|
||||
|
||||
bool ArcaneIntellectOnPartyTrigger::IsActive()
|
||||
{
|
||||
return BuffOnPartyTrigger::IsActive() &&
|
||||
!botAI->HasAnyAuraOf(GetTarget(), "arcane brilliance", "arcane intellect", "dalaran brilliance",
|
||||
"dalaran intellect", nullptr);
|
||||
return BuffOnPartyTrigger::IsActive() && !botAI->HasAura("arcane brilliance", GetTarget());
|
||||
}
|
||||
|
||||
bool ArcaneIntellectTrigger::IsActive()
|
||||
{
|
||||
return BuffTrigger::IsActive() &&
|
||||
!botAI->HasAnyAuraOf(GetTarget(), "arcane brilliance", "arcane intellect", "dalaran brilliance",
|
||||
"dalaran intellect", nullptr);
|
||||
return BuffTrigger::IsActive() && !botAI->HasAura("arcane brilliance", GetTarget());
|
||||
}
|
||||
|
||||
bool MageArmorTrigger::IsActive()
|
||||
|
||||
@@ -1,332 +0,0 @@
|
||||
#include "PlayerbotAI.h"
|
||||
#include "Group.h"
|
||||
#include "Player.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
// 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<int, std::map<uint8 /*classId*/, std::vector<GreaterBlessingType>>> 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<Player*> GetPaladinsInGroup(PlayerbotAI* botAI)
|
||||
{
|
||||
std::vector<Player*> 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<Player*, std::map<uint8, GreaterBlessingType>> AssignBlessingsForGroup(PlayerbotAI* botAI)
|
||||
{
|
||||
std::map<Player*, std::map<uint8, GreaterBlessingType>> results;
|
||||
|
||||
// Get relevant Paladins
|
||||
std::vector<Player*> paladins = GetPaladinsInGroup(botAI);
|
||||
int numPaladins = std::min(static_cast<int>(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<Player*> paladinsWithSanctuary;
|
||||
std::vector<Player*> paladinsWithMight;
|
||||
std::vector<Player*> paladinsWithWisdom;
|
||||
std::vector<Player*> 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<Player*, std::set<uint8>> 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
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
#ifndef _BLESSING_ASSIGNMENT_H_
|
||||
#define _BLESSING_ASSIGNMENT_H_
|
||||
|
||||
#include "PlayerbotAI.h"
|
||||
#include "Group.h"
|
||||
#include "Player.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 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<int, std::map<uint8 /*classId*/, std::vector<GreaterBlessingType>>> 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<Player*> GetPaladinsInGroup(PlayerbotAI* botAI);
|
||||
|
||||
// Main function to assign blessings for the current group/raid.
|
||||
// Returns a map of (Paladin pointer) -> (classId -> assigned blessing).
|
||||
std::map<Player*, std::map<uint8, GreaterBlessingType>> AssignBlessingsForGroup(PlayerbotAI* botAI);
|
||||
|
||||
#endif // _BLESSING_ASSIGNMENT_H_
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
#include "PaladinActions.h"
|
||||
#include "BlessingManager.h"
|
||||
|
||||
#include "AiFactory.h"
|
||||
#include "Event.h"
|
||||
@@ -170,73 +169,4 @@ bool CastCancelDivineSacrificeAction::Execute(Event event)
|
||||
bool CastCancelDivineSacrificeAction::isUseful()
|
||||
{
|
||||
return botAI->HasAura("divine sacrifice", GetTarget(), false, true, -1, true);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -424,13 +424,4 @@ public:
|
||||
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
|
||||
|
||||
@@ -68,7 +68,6 @@ public:
|
||||
creators["bmana"] = &PaladinBuffStrategyFactoryInternal::bmana;
|
||||
creators["bdps"] = &PaladinBuffStrategyFactoryInternal::bdps;
|
||||
creators["bstats"] = &PaladinBuffStrategyFactoryInternal::bstats;
|
||||
creators["bgreater"] = &PaladinBuffStrategyFactoryInternal::bgreater;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -76,8 +75,6 @@ private:
|
||||
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<Strategy>
|
||||
@@ -145,8 +142,6 @@ public:
|
||||
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:
|
||||
@@ -213,8 +208,6 @@ private:
|
||||
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<Action>
|
||||
@@ -301,7 +294,6 @@ public:
|
||||
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:
|
||||
@@ -403,7 +395,6 @@ private:
|
||||
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)
|
||||
|
||||
@@ -86,18 +86,3 @@ void PaladinBuffStatsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// triggers.push_back(new TriggerNode("blessing", NextAction::array(0, new NextAction("blessing of kings",
|
||||
// ACTION_HIGH + 8), nullptr)));
|
||||
}
|
||||
|
||||
void PaladinBuffGreaterBlessingStrategy::InitTriggers(std::vector<TriggerNode*>& 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)));
|
||||
}
|
||||
|
||||
@@ -109,13 +109,4 @@ public:
|
||||
std::string const getName() override { return "rfire"; }
|
||||
};
|
||||
|
||||
class PaladinBuffGreaterBlessingStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
PaladinBuffGreaterBlessingStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "bgreater"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*/
|
||||
|
||||
#include "PaladinTriggers.h"
|
||||
#include "BlessingManager.h"
|
||||
|
||||
#include "PaladinActions.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
@@ -31,71 +30,3 @@ 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;
|
||||
}
|
||||
|
||||
@@ -239,12 +239,4 @@ 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
|
||||
|
||||
@@ -105,21 +105,4 @@ Unit* CastPowerWordShieldOnNotFullAction::GetTarget()
|
||||
bool CastPowerWordShieldOnNotFullAction::isUseful()
|
||||
{
|
||||
return GetTarget();
|
||||
}
|
||||
|
||||
bool CastPowerWordFortitudeOnPartyAction::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);
|
||||
}
|
||||
}
|
||||
@@ -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,11 +210,4 @@ public:
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user