Shaman Overhaul (#1566)

* Shaman Overhaul

Hello everyone,

I bring to you the Shaman Overhaul. This was the most fun project I've had so far.
Here is a simplified list of the changes this brings:

1. Added Call of the Elements - making the shaman able to set 4 totems down simultaneously! This saves them multiple global cooldowns in combat.

2. Totems are now selected based on their combat strategies. These strategies set totems on the Call of the Elements bar, as well as change what totem is summoned if a single totem is missing. NOTE: Only one strategy of each elemental type (earth, fire, water, air) can be active at a time.
Earth - strength of earth, stoneskin, tremor, earthbind
Fire - searing, magma, flametongue, wrath, frost resistance
Water - healing stream, mana spring, cleansing, fire resistance
Air - wrath of air, windfury, nature resistance, grounding

There are a few exceptions to totems without strategies: Stoneclaw Totem, Fire Elemental Totem, and Mana Tide Totem. These each have triggers that fire under certain conditions:
Stoneclaw Totem: Resto/Ele shaman has low health and isn't in a group
Fire Elemental Totem: Boost trigger for Ele/Enhance
Mana Tide Totem: Resto Shaman medium mana

3. Added Totemic Recall - a spell that picks up the totems outside of combat to regain 25% of the mana spent. Useful to avoid patrols.

4. Changed the config slightly - Enhance uses Fire Nova Glyph for crazy AoE damage, and enhance pve spec uses both clearcasting and improved shock talent now.

5. Enhancement Shamans will use their Spirit Wolves' Spirit Walk ability - this helps them close the gap and improves their DPS on fights that require movement.

6. Boost Strategy - Moved Bloodlust/Heroism/Fire Elemental Totem from the generic strategy triggers to a new Boost strategy. Now you can control their uses with Boost! (co +boost or co -boost. Enabled by default.)

7. AoE Strategy - Unified both of the AoE strategies for Ele/Enhance to "aoe", rather than "caster aoe" and "melee aoe". NOTE: Healers will still aoe under "healer dps". (co +aoe or co -aoe. Enabled by default.)

8. Moved the weapon imbue strategies from combat to non-combat. I noticed that they were only casting their weapon imbues during combat - this fixes that.

9. Added logic for only using Lava Burst on targets with Flame Shock active, ensuring that it's as close to 100% crit chance as possible. I did notice on a sample size of 112 lava bursts in testing that it still fails to crit around 3 percent of the time - that is because the lava burst starts to cast while flame shock is on the target, but by the time the projectile lands, flame shock has worn off.

10. Added Earth Shock as an execute ability for elemental shamans only. This helps their DPS tremendously at low levels, as well as in PVP. There is logic in place to prevent the use of Earth Shock as elemental entirely on bosses (it's garbage on bosses), as it will only be used as an execute if the target has less than 1500 hp and it's at 25% hp or less.

10. Added chain lightning as an AoE option for enhancement shamans while maelstrom weapon is at 4 or 5 stacks. This continues to push the AoE dps on enhance higher!

Here is a file-by-file list of the changes:

conf\playerbots.conf.dist - Enhancement shamans use Fire Nova Glyph as early as level 15, they also use the clearcasting talent in elemental and improved shocks in enhance. It really helps their mana usage. Also swapped the position of two glyphs in resto.

src\AiFactory.cpp - Set the default spec that new altbot shamans start as to Elemental. Put Arcane, Fire, and Frost comments on the mage specs. Set the strategies of the shaman specs to "ele, resto, and enh", as well as added the default totem strategies for each spec. Also added in the aoe strategy. Removed bmana/bdps, as those were set for lightning/mana sheld - those have been moved to both the non-combat strategy, as well as to each spec combat strategy. Enhancement will use Lightning Shield, and Elemental and Resto will use Water Shield both in and out of combat.

src\strategy\shaman\CasterShamanStrategy.cpp/CasterShamanStrategy.h - Renamed to Elemental.

src\strategy\shaman\ElementalShamanStrategy.cpp/ElementalShamanStrategy.h - Renamed from CasterShamanStrategy, most logic is the same. Moved the totem of wrath passthrough to the GenericShamanStrategy. Moved the Weapon Imbue to the NonCombatShamanStrategy. Moved the AoE spells to GenericShamanStrategy, under the AoE strategy there. Added the use of Stoneclaw totem, as well as Earth Shock Execute. Changed the use of Thunderstorm from medium mana to high mana, so it can be used more often in longer fights. Moved the individual casting of totems to the totem strategies. Added the use of Call of the Elements.

src\strategy\shaman\EnhancementShamanStrategy.cpp/EnhancementShamanStrategy.h - Renamed from MeleeShamanStrategy. Moved the totem passthroughs to GenericShamanStrategy. Refined the priorities in the default actions and triggers to closer match guides online. Moved the weapon imbues to the non-combat strategy. Moved the individual casting of totems to the totem strategies. Moved the AoE spells to the AoE strategy in GenericShamanStrategy. Added the use of Call of the Elements (while in melee range) and Spirit Walk.

src\strategy\shaman\GenericShamanStrategy.cpp/GenericShamanStrategy.h - Moved weapon imbue passthroughs to non-combat. Set up all totem passthroughs here so lower level shamans could function well. Set up a boost strategy for heroism/bloodlust/fire elemental totem. Set up an AoE strategy for Elemental/Enhancement. Cleaned up tablature of the code. Moved the Healer DPS strategy to the RestoShamanStrategy. Added a medium mana trigger so they can use more mana potions in longer fights.

src\strategy\shaman\HealShamanStrategy.cpp/HealShamanStrategy.h - Renamed to RestoShamanStrategy.

src\strategy\shaman\MeleeShamanStrategy.cpp/MeleeShamanStrategy.h - Renamed to EnhancementShamanStrategy.

src\strategy\shaman\RestoShamanStrategy.cpp/RestoShamanStrategy.h - Renamed from  HealShamanStrategy. Moved weapon imbue to non-combat strategy. Moved the individual casting of totems to the totem strategies (except mana tide totem). Added in Healer DPS from genericshamanstrategy. Added in use of Stoneclaw totem and Call of the Elements.

src\strategy\shaman\ShamanActions.cpp/ShamanActions.h - Organized the actions by type. Removed the TTL check in the totem action and Flame Shock. Added logic in the Stoneclaw totem to only be used when not in a group. Added logic on LavaBurst Action to only be used when the target has flame shock debuff from the caster. Added custom logic for casting Spirit Walk (no code exists in AC/Playerbots to make a guardian cast a spell). Added in the "SetXTotemAction"s, which set a totem to the highest rank of the spell in the totem bar.

src\strategy\shaman\ShamanAiObjectContext.cpp/ShamanAiObjectContext.h - Cleaned up strategies, triggers, and actions as a whole. Renamed melee, heal, and caster to ele, enh, and resto. Changed the "totems" strategy to individualized elemental totem strategies.

src\strategy\shaman\ShamanNonCombatStrategy.cpp/ShamanNonCombatStrategy.cpp - Moved weapon imbues here. Cleaned up tablature. Added the Totemic Recall spell.

src\strategy\shaman\ShamanTriggers.cpp/ShamanTriggers.h - Removed the commented out section. Added triggers + logic for:
EarthShockExecute
Call of the Elements
Totemic Recall
"SetXTotemTrigger"
Spirit Walk
Elemental Mastery
No Earth/Fire/Water/Air Totem

src\strategy\shaman\TotemsShamanStrategy.h - Master hub for all defined constants and arrays used in other files, as well as names all of the totem strategy types.

src\strategy\shaman\TotemsShamanStrategy.cpp - Each strategy has a "set x totem" to change the bar totem, as well as a "no x totem" trigger with a corresponding "cast x totem". NOTE: some totems aren't learned by level 30 when a shaman learns call of the elements, so I had to set an alternative for those (Totem of Wrath, Wrath of Air, Cleansing Totem, and Windfury). Testing showed me that this is necessary - without this, the trigger would just fire over and over, and the shaman would recast the same totem over and over.

Scope of Testing:

8/5/25 (2 hours): Began work on the Shaman class. Cleaned up actions and triggers.
8/6/25 (3.5 hours): Tried what felt like everything to get the totem bar changed. Seems impossible to change a client-side thing with cpp.

8/9/25(3 hours): Initial totem strategies created. Through the help of Revision, I was able make a functioning action that would change the totem bar's spell. The spells are stored in the database! I was able to get a strategy of each type working, and Call of the Elements was casting the correct totems.

8/10/25 (3.5 hours): Testing on Noth the Plaguebringer. The elemental shaman's dps was low - I noticed that the shaman was casting lava burst regardless of if the target had flame shock. I fixed this. I also noticed that the enhancement shaman was casting call of the elements at max range, resulting in the magma totem never doing damage. Changed so enhance would only cast  Call of the Elements in melee range. Also, had to add "cast x totem" spells to each strategy, so magma totem would recast once expired (as well as other totems).

8/11/25 - (2.5 hours)Did a full run of Naxxramas. Enhancement did crazy dps for the gear it had. Elemental was consistently placing between 14-18th place of 18 dps. I noticed that totemic recall was messing up with the KT encounter, and had to look in the AC repo for logic to check if a boss encounter is active. Fixed it, and shamans weren't spamming totemic recall between packs. I wonder what I can do to fix elemental?

8/12/25 (1.5 hours) - Added a check in lava burst's isuseful to ensure flame shock was on the target. DPS went up a little bit. Also, made chain lightning the highest spell priority - DPS went up quite a bit after that. It is quite costly, but it is worth it - even on one target, but especially 3. Added spirit walk for enhancement.

8/13/25 - (5 hours) Tested on level 1-10 level, 15, 25, 35, 45, and 55 instances: I had a ton of bugs at level 35. Essentially, the shaman was standing there casting the totems it didn't know (wrath, cleansing, wrath of air). I had to add some checks and passthroughs for it to run smoothly again. Elemental was still doing just okay dps at lower levels, while enhancement was CRUSHING it. The fact that enhancement has the fire glyph from 15 on now is crazy.

8/14/2025 (2 hours) - Tested in 65/75 instances, as well as little bit of ulduar. I am pretty happy with the state of shamans now, they are consistently performing highly (enhance top 5, elemental top 8 in ulduar). Tweaked elemental mastery to cause lava burst to be instant cast, not chain lightning. This improved the DPS of elemental shamans right out of the gate.

Total testing - 23 hours

If y'all have any questions or comments, please let me know either here or on discord!

* Fixed the Bracket so the code will compile

Fixed the Bracket so the code will compile

* - Code refactoring

* - Non windows compilation error fixes

---------

Co-authored-by: kadeshar <kadeshar@gmail.com>
This commit is contained in:
ThePenguinMan96
2025-09-16 11:09:00 -07:00
committed by GitHub
parent 2c383339d8
commit b388657bf6
24 changed files with 2661 additions and 1304 deletions

View File

@@ -9,21 +9,35 @@
#include "CureTriggers.h"
#include "GenericTriggers.h"
#include "SharedDefines.h"
#include "Trigger.h"
#include <set>
#include "TotemsShamanStrategy.h"
#include "Player.h"
#include "PlayerbotAI.h"
#include <ctime>
class PlayerbotAI;
/*
class ShamanWeaponTrigger : public BuffTrigger
{
public:
ShamanWeaponTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "rockbiter weapon", 2 * 2000) { }
// Buff and Out of Combat Triggers
bool IsActive() override;
private:
static std::vector<std::string> spells;
};
*/
const uint32 SPELL_EARTHBIND_TOTEM_RANK_1 = 2484;
const uint32 SPELL_SEARING_TOTEM_RANK_1 = 3599;
const uint32 SPELL_WRATH_OF_AIR_TOTEM_RANK_1 = 3738;
const uint32 SPELL_HEALING_STREAM_TOTEM_RANK_1 = 5394;
const uint32 SPELL_MANA_SPRING_TOTEM_RANK_1 = 5675;
const uint32 SPELL_STONESKIN_TOTEM_RANK_1 = 8071;
const uint32 SPELL_STRENGTH_OF_EARTH_TOTEM_RANK_1 = 8075;
const uint32 SPELL_TREMOR_TOTEM_RANK_1 = 8143;
const uint32 SPELL_CLEANSING_TOTEM_RANK_1 = 8170;
const uint32 SPELL_GROUNDING_TOTEM_RANK_1 = 8177;
const uint32 SPELL_FROST_RESISTANCE_TOTEM_RANK_1 = 8181;
const uint32 SPELL_FIRE_RESISTANCE_TOTEM_RANK_1 = 8184;
const uint32 SPELL_MAGMA_TOTEM_RANK_1 = 8190;
const uint32 SPELL_FLAMETONGUE_TOTEM_RANK_1 = 8227;
const uint32 SPELL_WINDFURY_TOTEM_RANK_1 = 8512;
const uint32 SPELL_NATURE_RESISTANCE_TOTEM_RANK_1 = 10595;
const uint32 SPELL_TOTEM_OF_WRATH_RANK_1 = 30706;
const uint32 SPELL_TOTEMIC_RECALL = 36936;
class MainHandWeaponNoImbueTrigger : public BuffTrigger
{
@@ -39,76 +53,6 @@ public:
virtual bool IsActive();
};
class TotemTrigger : public Trigger
{
public:
TotemTrigger(PlayerbotAI* botAI, std::string const spell, uint32 attackerCount = 0)
: Trigger(botAI, spell), attackerCount(attackerCount)
{
}
bool IsActive() override;
protected:
uint32 attackerCount;
};
class WindfuryTotemTrigger : public TotemTrigger
{
public:
WindfuryTotemTrigger(PlayerbotAI* botAI) : TotemTrigger(botAI, "windfury totem") {}
};
class GraceOfAirTotemTrigger : public TotemTrigger
{
public:
GraceOfAirTotemTrigger(PlayerbotAI* botAI) : TotemTrigger(botAI, "grace of air totem") {}
};
class ManaSpringTotemTrigger : public TotemTrigger
{
public:
ManaSpringTotemTrigger(PlayerbotAI* botAI) : TotemTrigger(botAI, "mana spring totem") {}
bool IsActive() override;
};
class FlametongueTotemTrigger : public TotemTrigger
{
public:
FlametongueTotemTrigger(PlayerbotAI* botAI) : TotemTrigger(botAI, "flametongue totem") {}
};
class StrengthOfEarthTotemTrigger : public TotemTrigger
{
public:
StrengthOfEarthTotemTrigger(PlayerbotAI* botAI) : TotemTrigger(botAI, "strength of earth totem") {}
};
class FireElementalTotemTrigger : public BoostTrigger
{
public:
FireElementalTotemTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "fire elemental totem") {}
};
class MagmaTotemTrigger : public TotemTrigger
{
public:
MagmaTotemTrigger(PlayerbotAI* botAI) : TotemTrigger(botAI, "magma totem", 3) {}
};
class SearingTotemTrigger : public TotemTrigger
{
public:
SearingTotemTrigger(PlayerbotAI* botAI) : TotemTrigger(botAI, "searing totem", 1) {}
};
class WindShearInterruptSpellTrigger : public InterruptSpellTrigger
{
public:
WindShearInterruptSpellTrigger(PlayerbotAI* botAI) : InterruptSpellTrigger(botAI, "wind shear") {}
};
class WaterShieldTrigger : public BuffTrigger
{
public:
@@ -121,12 +65,6 @@ public:
LightningShieldTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "lightning shield") {}
};
class PurgeTrigger : public TargetAuraDispelTrigger
{
public:
PurgeTrigger(PlayerbotAI* botAI) : TargetAuraDispelTrigger(botAI, "purge", DISPEL_MAGIC) {}
};
class WaterWalkingTrigger : public BuffTrigger
{
public:
@@ -154,13 +92,70 @@ public:
class WaterBreathingOnPartyTrigger : public BuffOnPartyTrigger
{
public:
WaterBreathingOnPartyTrigger(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, "water breathing on party", 2 * 2000)
{
}
WaterBreathingOnPartyTrigger(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, "water breathing on party", 2 * 2000) {}
bool IsActive() override;
};
// Boost Triggers
class HeroismTrigger : public BoostTrigger
{
public:
HeroismTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "heroism") {}
};
class BloodlustTrigger : public BoostTrigger
{
public:
BloodlustTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "bloodlust") {}
};
class ElementalMasteryTrigger : public BuffTrigger
{
public:
ElementalMasteryTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "elemental mastery") {}
bool IsActive() override;
};
class SpiritWalkTrigger : public Trigger
{
public:
SpiritWalkTrigger(PlayerbotAI* ai) : Trigger(ai, "spirit walk ready") {}
bool IsActive() override;
private:
time_t lastSpiritWalkTime = 0;
};
class FireElementalTotemTrigger : public BoostTrigger
{
public:
FireElementalTotemTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "fire elemental totem") {}
};
// CC, Interrupt, and Dispel Triggers
class WindShearInterruptSpellTrigger : public InterruptSpellTrigger
{
public:
WindShearInterruptSpellTrigger(PlayerbotAI* botAI) : InterruptSpellTrigger(botAI, "wind shear") {}
};
class WindShearInterruptEnemyHealerSpellTrigger : public InterruptEnemyHealerTrigger
{
public:
WindShearInterruptEnemyHealerSpellTrigger(PlayerbotAI* botAI) : InterruptEnemyHealerTrigger(botAI, "wind shear") {}
};
class PurgeTrigger : public TargetAuraDispelTrigger
{
public:
PurgeTrigger(PlayerbotAI* botAI) : TargetAuraDispelTrigger(botAI, "purge", DISPEL_MAGIC) {}
};
class CleanseSpiritPoisonTrigger : public NeedCureTrigger
{
public:
@@ -206,6 +201,33 @@ public:
}
};
class CurePoisonTrigger : public NeedCureTrigger
{
public:
CurePoisonTrigger(PlayerbotAI* botAI) : NeedCureTrigger(botAI, "cure poison", DISPEL_POISON) {}
};
class PartyMemberCurePoisonTrigger : public PartyMemberNeedCureTrigger
{
public:
PartyMemberCurePoisonTrigger(PlayerbotAI* botAI) : PartyMemberNeedCureTrigger(botAI, "cure poison", DISPEL_POISON) {}
};
class CureDiseaseTrigger : public NeedCureTrigger
{
public:
CureDiseaseTrigger(PlayerbotAI* botAI) : NeedCureTrigger(botAI, "cure disease", DISPEL_DISEASE) {}
};
class PartyMemberCureDiseaseTrigger : public PartyMemberNeedCureTrigger
{
public:
PartyMemberCureDiseaseTrigger(PlayerbotAI* botAI)
: PartyMemberNeedCureTrigger(botAI, "cure disease", DISPEL_DISEASE) {}
};
// Damage and Debuff Triggers
class ShockTrigger : public DebuffTrigger
{
public:
@@ -220,63 +242,88 @@ public:
FrostShockSnareTrigger(PlayerbotAI* botAI) : SnareTargetTrigger(botAI, "frost shock") {}
};
class HeroismTrigger : public BoostTrigger
{
public:
HeroismTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "heroism") {}
};
class BloodlustTrigger : public BoostTrigger
{
public:
BloodlustTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "bloodlust") {}
};
class ElementalMasteryTrigger : public BoostTrigger
{
public:
ElementalMasteryTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "elemental mastery") {}
};
class MaelstromWeaponTrigger : public HasAuraStackTrigger
{
public:
MaelstromWeaponTrigger(PlayerbotAI* botAI, int stack = 5) : HasAuraStackTrigger(botAI, "maelstrom weapon", stack) {}
};
class WindShearInterruptEnemyHealerSpellTrigger : public InterruptEnemyHealerTrigger
class FlameShockTrigger : public DebuffTrigger
{
public:
WindShearInterruptEnemyHealerSpellTrigger(PlayerbotAI* botAI) : InterruptEnemyHealerTrigger(botAI, "wind shear") {}
FlameShockTrigger(PlayerbotAI* ai) : DebuffTrigger(ai, "flame shock", 1, true, 6.0f) {}
bool IsActive() override { return BuffTrigger::IsActive(); }
};
class CurePoisonTrigger : public NeedCureTrigger
class EarthShockExecuteTrigger : public Trigger
{
public:
CurePoisonTrigger(PlayerbotAI* botAI) : NeedCureTrigger(botAI, "cure poison", DISPEL_POISON) {}
EarthShockExecuteTrigger(PlayerbotAI* botAI) : Trigger(botAI, "earth shock execute") {}
bool IsActive() override;
};
class PartyMemberCurePoisonTrigger : public PartyMemberNeedCureTrigger
class MaelstromWeapon5AndMediumAoeTrigger : public TwoTriggers
{
public:
PartyMemberCurePoisonTrigger(PlayerbotAI* botAI) : PartyMemberNeedCureTrigger(botAI, "cure poison", DISPEL_POISON)
MaelstromWeapon5AndMediumAoeTrigger(PlayerbotAI* ai) : TwoTriggers(ai, "maelstrom weapon 5", "medium aoe") {}
};
class MaelstromWeapon4AndMediumAoeTrigger : public TwoTriggers
{
public:
MaelstromWeapon4AndMediumAoeTrigger(PlayerbotAI* ai) : TwoTriggers(ai, "maelstrom weapon 4", "medium aoe") {}
};
class ChainLightningNoCdTrigger : public SpellNoCooldownTrigger
{
public:
ChainLightningNoCdTrigger(PlayerbotAI* ai) : SpellNoCooldownTrigger(ai, "chain lightning") {}
};
// Healing Triggers
class EarthShieldOnMainTankTrigger : public BuffOnMainTankTrigger
{
public:
EarthShieldOnMainTankTrigger(PlayerbotAI* botAI) : BuffOnMainTankTrigger(botAI, "earth shield", false) {}
};
// Totem Triggers
class TotemTrigger : public Trigger
{
public:
TotemTrigger(PlayerbotAI* botAI, std::string const spell, uint32 attackerCount = 0)
: Trigger(botAI, spell), attackerCount(attackerCount)
{
}
bool IsActive() override;
protected:
uint32 attackerCount;
};
class CureDiseaseTrigger : public NeedCureTrigger
class CallOfTheElementsTrigger : public Trigger
{
public:
CureDiseaseTrigger(PlayerbotAI* botAI) : NeedCureTrigger(botAI, "cure disease", DISPEL_DISEASE) {}
CallOfTheElementsTrigger(PlayerbotAI* ai) : Trigger(ai, "call of the elements") {}
bool IsActive() override;
};
class PartyMemberCureDiseaseTrigger : public PartyMemberNeedCureTrigger
class TotemicRecallTrigger : public Trigger
{
public:
PartyMemberCureDiseaseTrigger(PlayerbotAI* botAI)
: PartyMemberNeedCureTrigger(botAI, "cure disease", DISPEL_DISEASE)
{
}
TotemicRecallTrigger(PlayerbotAI* ai) : Trigger(ai, "totemic recall") {}
bool IsActive() override;
};
class NoEarthTotemTrigger : public Trigger
{
public:
NoEarthTotemTrigger(PlayerbotAI* ai) : Trigger(ai, "no earth totem") {}
bool IsActive() override;
};
class NoFireTotemTrigger : public Trigger
@@ -293,28 +340,155 @@ public:
bool IsActive() override;
};
class EarthShieldOnMainTankTrigger : public BuffOnMainTankTrigger
class NoAirTotemTrigger : public Trigger
{
public:
EarthShieldOnMainTankTrigger(PlayerbotAI* botAI) : BuffOnMainTankTrigger(botAI, "earth shield", false) {}
};
class FlameShockTrigger : public DebuffTrigger
{
public:
FlameShockTrigger(PlayerbotAI* ai) : DebuffTrigger(ai, "flame shock", 1, true, 6.0f) {}
};
class WrathOfAirTotemTrigger : public TotemTrigger
{
public:
WrathOfAirTotemTrigger(PlayerbotAI* ai) : TotemTrigger(ai, "wrath of air totem") {}
};
class NoAirTotemTrigger : public TotemTrigger
{
public:
NoAirTotemTrigger(PlayerbotAI* ai) : TotemTrigger(ai, "no air totem") {}
NoAirTotemTrigger(PlayerbotAI* ai) : Trigger(ai, "no air totem") {}
bool IsActive() override;
};
class CallOfTheElementsAndEnemyWithinMeleeTrigger : public TwoTriggers
{
public:
CallOfTheElementsAndEnemyWithinMeleeTrigger(PlayerbotAI* ai) : TwoTriggers(ai, "call of the elements", "enemy within melee") {}
};
// Set Strategy Assigned Totems
class SetTotemTrigger : public Trigger
{
public:
SetTotemTrigger(PlayerbotAI* ai, std::string const spellName, const uint32 requiredSpellId,
const uint32 totemSpellIds[], int actionButtonId)
: Trigger(ai, "set " + spellName),
requiredSpellId(requiredSpellId),
totemSpellIds(totemSpellIds),
actionButtonId(actionButtonId) {}
bool IsActive() override;
private:
uint32 requiredSpellId;
uint32 const* totemSpellIds;
int actionButtonId;
};
class SetStrengthOfEarthTotemTrigger : public SetTotemTrigger
{
public:
SetStrengthOfEarthTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "strength of earth totem", SPELL_STRENGTH_OF_EARTH_TOTEM_RANK_1, STRENGTH_OF_EARTH_TOTEM, TOTEM_BAR_SLOT_EARTH) {}
};
class SetStoneskinTotemTrigger : public SetTotemTrigger
{
public:
SetStoneskinTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "stoneskin totem", SPELL_STONESKIN_TOTEM_RANK_1, STONESKIN_TOTEM, TOTEM_BAR_SLOT_EARTH) {}
};
class SetTremorTotemTrigger : public SetTotemTrigger
{
public:
SetTremorTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "tremor totem", SPELL_TREMOR_TOTEM_RANK_1, TREMOR_TOTEM, TOTEM_BAR_SLOT_EARTH) {}
};
class SetEarthbindTotemTrigger : public SetTotemTrigger
{
public:
SetEarthbindTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "earthbind totem", SPELL_EARTHBIND_TOTEM_RANK_1, EARTHBIND_TOTEM, TOTEM_BAR_SLOT_EARTH) {}
};
class SetSearingTotemTrigger : public SetTotemTrigger
{
public:
SetSearingTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "searing totem", SPELL_SEARING_TOTEM_RANK_1, SEARING_TOTEM, TOTEM_BAR_SLOT_FIRE) {}
};
class SetMagmaTotemTrigger : public SetTotemTrigger
{
public:
SetMagmaTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "magma totem", SPELL_MAGMA_TOTEM_RANK_1, MAGMA_TOTEM, TOTEM_BAR_SLOT_FIRE) {}
};
class SetFlametongueTotemTrigger : public SetTotemTrigger
{
public:
SetFlametongueTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "flametongue totem", SPELL_FLAMETONGUE_TOTEM_RANK_1, FLAMETONGUE_TOTEM, TOTEM_BAR_SLOT_FIRE) {}
};
class SetTotemOfWrathTrigger : public SetTotemTrigger
{
public:
SetTotemOfWrathTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "totem of wrath", SPELL_TOTEM_OF_WRATH_RANK_1, TOTEM_OF_WRATH, TOTEM_BAR_SLOT_FIRE) {}
};
class SetFrostResistanceTotemTrigger : public SetTotemTrigger
{
public:
SetFrostResistanceTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "frost resistance totem", SPELL_FROST_RESISTANCE_TOTEM_RANK_1, FROST_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_FIRE) {}
};
class SetHealingStreamTotemTrigger : public SetTotemTrigger
{
public:
SetHealingStreamTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "healing stream totem", SPELL_HEALING_STREAM_TOTEM_RANK_1, HEALING_STREAM_TOTEM, TOTEM_BAR_SLOT_WATER) {}
};
class SetManaSpringTotemTrigger : public SetTotemTrigger
{
public:
SetManaSpringTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "mana spring totem", SPELL_MANA_SPRING_TOTEM_RANK_1, MANA_SPRING_TOTEM, TOTEM_BAR_SLOT_WATER) {}
};
class SetCleansingTotemTrigger : public SetTotemTrigger
{
public:
SetCleansingTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "cleansing totem", SPELL_CLEANSING_TOTEM_RANK_1, CLEANSING_TOTEM, TOTEM_BAR_SLOT_WATER) {}
};
class SetFireResistanceTotemTrigger : public SetTotemTrigger
{
public:
SetFireResistanceTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "fire resistance totem", SPELL_FIRE_RESISTANCE_TOTEM_RANK_1, FIRE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_WATER) {}
};
class SetWrathOfAirTotemTrigger : public SetTotemTrigger
{
public:
SetWrathOfAirTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "wrath of air totem", SPELL_WRATH_OF_AIR_TOTEM_RANK_1, WRATH_OF_AIR_TOTEM, TOTEM_BAR_SLOT_AIR) {}
};
class SetWindfuryTotemTrigger : public SetTotemTrigger
{
public:
SetWindfuryTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "windfury totem", SPELL_WINDFURY_TOTEM_RANK_1, WINDFURY_TOTEM, TOTEM_BAR_SLOT_AIR) {}
};
class SetNatureResistanceTotemTrigger : public SetTotemTrigger
{
public:
SetNatureResistanceTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "nature resistance totem", SPELL_NATURE_RESISTANCE_TOTEM_RANK_1, NATURE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_AIR) {}
};
class SetGroundingTotemTrigger : public SetTotemTrigger
{
public:
SetGroundingTotemTrigger(PlayerbotAI* ai)
: SetTotemTrigger(ai, "grounding totem", SPELL_GROUNDING_TOTEM_RANK_1, GROUNDING_TOTEM, TOTEM_BAR_SLOT_AIR) {}
};
#endif