mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
<!-- Thank you for contributing to mod-playerbots, please make sure that you... 1. Submit your PR to the test-staging branch, not master. 2. Read the guidelines below before submitting. 3. Don't delete parts of this template. DESIGN PHILOSOPHY: We prioritize STABILITY, PERFORMANCE, AND PREDICTABILITY over behavioral realism. Every action and decision executes PER BOT AND PER TRIGGER. Small increases in logic complexity scale poorly across thousands of bots and negatively affect all. We prioritize a stable system over a smarter one. Bots don't need to behave perfectly; believable behavior is the goal, not human simulation. Default behavior must be cheap in processing; expensive behavior must be opt-in. Before submitting, make sure your changes aligns with these principles. --> ## Pull Request Description <!-- Describe what this change does and why it is needed --> 1. I've been having persistent issues with Enhancement Shamans sometimes applying Rockbiter to both weapons instead of MH Windfury and OH Flametongue. Rockbiter is the alternative for Flametongue and, through Flametongue, the alternative for Windfury. But there seemed to be no obvious reason why a Shaman that had all three abilities would ever use Rockbiter, which costs more mana than Windfury and Flametongue. Claude's take on it is that there is instability from ItemForSpellValue related to its poor way of distinguishing handedness, in addition to it having a 1-second cache, which can cause in some scenarios stale caches for the action running on each hand back-to-back. I still can't say I fully understand why the issue exists, but the most straightforward fix that should prevent this from happening is to just have separate mainhand and offhand actions for each enchant. So that's what this PR does. The relevant ActionNodes are now: - The MH-specific chain for Enhancement is WF -> FT -> RB. In practice, Enhancement should never apply RB because all Shamans under level 10 (when FT is learned) are considered Elemental. The FT -> RB node is just for Elemental. - The MH-specific Resto chain (not that Resto can dual-wield) is EL -> FT -> RB. Againt, FT -> RB is just for Elemental. - OH for Enhancement is only FT. You cannot be Enhancement before level 10, nor can Enhancement dual-wield before level 40, so no alternative is needed. 3. I commented out Frostbrand Weapon actions/triggers because the ability is not included in any strategy. I didn't delete the code because in the future somebody might want to implement it as I understand it can be useful for Enhancement Shamans in PvP. 4. Shamans are coded to use "cure poison" and "cure disease", which do not exist in WotLK, having been combined into Cure Toxins. Wishmaster has PR #1844 that has been open on this for a long time, but I decided to correct the abilities here anyway as he was going for a more limited approach, and I decided to rename all the actions and redo the structure to rely on ActionNode alternatives, which is pretty much the exact framework that should be used for this type of situation w/r/t bots. Now, Shamans prefer Cleanse Spirit (Resto talent, which costs the same as Cure Toxins and also dispels curses), with an alternative of Cure Toxins (for poisons and disease only). I tested this and it seems to work well. 5. I deleted empty ActionNodes. 6. I did some cleanup of formatting and such, but this is not intended to be a comprehensive refactor. ## Feature Evaluation <!-- If your PR is very minimal (comment typo, wrong ID reference, etc), and it is very obvious it will not have any impact on performance, you may skip these question. If necessary, a maintainer may ask you for them later. --> <!-- Please answer the following: --> - Describe the **minimum logic** required to achieve the intended behavior. - Describe the **processing cost** when this logic executes across many bots. I've followed the general intended structure of class strategies with triggers and actions. The same triggers exist, just different actions are called based on the trigger that fires, so I don't think there should be any impact on performance. ## How to Test the Changes <!-- - Step-by-step instructions to test the change. - Any required setup (e.g. multiple players, number of bots, specific configuration). - Expected behavior and how to verify it. --> The best way to get a grasp on if things work is probably to just do group play for a while with Shamans and make sure they apply the right enchants and properly cast Cleanse Spirit and Cure Toxins. ## Impact Assessment <!-- As a generic test, before and after measure of pmon (playerbot pmon tick) can help you here. --> - Does this change increase per-bot/per-tick processing or risk scaling poorly with thousands of bots? - - [x] No, not at all - - [ ] Minimal impact (**explain below**) - - [ ] Moderate impact (**explain below**) - Does this change modify default bot behavior? - - [ ] No - - [x] Yes (**explain why**) Shamans previously did not cure poisons or disease at all, and now they do with the default "cure" strategy applied. - Does this change add new decision branches or increase maintenance complexity? - - [ ] No - - [x] Yes (**explain below**) One might say having separate actions per hand for enchants is somewhat more complex, but ultimately I think it is less confusing to keep those paths separate. ## Messages to Translate <!-- Bot messages have to be translatable, but you don't need to do the translations here. You only need to make sure the message is in a translatable format, and list in the table the message_key and the default English message. Search for GetBotTextOrDefault in the codebase for examples. --> Does this change add bot messages to translate? - - [x] No - - [ ] Yes (**list messages in the table**) | Message key | Default message | | --------------- | ------------------ | | | | | | | ## AI Assistance <!-- AI assistance is allowed, but all submitted code must be fully understood, reviewed, and owned by the contributor. We expect contributors to be honest about what they do and do not understand. --> Was AI assistance used while working on this change? - - [ ] No - - [x] Yes (**explain below**) <!-- If yes, please specify: - Purpose of usage (e.g. brainstorming, refactoring, documentation, code generation). - Which parts of the change were influenced or generated, and whether it was thoroughly reviewed. --> I had Claude try to diagnose the weapon enchant issue. It proposed and provided the separate MH/OH WF/FT actions. The other things were easy enough for me to do. ## Final Checklist - - [x] Stability is not compromised. - - [x] Performance impact is understood, tested, and acceptable. - - [x] Added logic complexity is justified and explained. - - [x] Documentation updated if needed (Conf comments, WiKi commands). ## Notes for Reviewers <!-- Anything else that's helpful to review or test your pull request. --> --------- Co-authored-by: Keleborn <22352763+Celandriel@users.noreply.github.com> Co-authored-by: bash <hermensb@gmail.com> Co-authored-by: Revision <tkn963@gmail.com> Co-authored-by: kadeshar <kadeshar@gmail.com>
465 lines
13 KiB
C++
465 lines
13 KiB
C++
/*
|
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
|
|
* and/or modify it under version 3 of the License, or (at your option), any later version.
|
|
*/
|
|
|
|
#ifndef _PLAYERBOT_SHAMANTRIGGERS_H
|
|
#define _PLAYERBOT_SHAMANTRIGGERS_H
|
|
|
|
#include "CureTriggers.h"
|
|
#include "GenericTriggers.h"
|
|
#include "SharedDefines.h"
|
|
#include "Trigger.h"
|
|
#include "TotemsShamanStrategy.h"
|
|
#include "PlayerbotAI.h"
|
|
#include <ctime>
|
|
|
|
class PlayerbotAI;
|
|
|
|
// Buff and Out of Combat Triggers
|
|
|
|
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;
|
|
const uint32 SPELL_CALL_OF_THE_ELEMENTS = 66842;
|
|
|
|
class MainHandWeaponNoImbueTrigger : public BuffTrigger
|
|
{
|
|
public:
|
|
MainHandWeaponNoImbueTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "main hand", 1) {}
|
|
virtual bool IsActive();
|
|
};
|
|
|
|
class OffHandWeaponNoImbueTrigger : public BuffTrigger
|
|
{
|
|
public:
|
|
OffHandWeaponNoImbueTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "off hand", 1) {}
|
|
virtual bool IsActive();
|
|
};
|
|
|
|
class WaterShieldTrigger : public BuffTrigger
|
|
{
|
|
public:
|
|
WaterShieldTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "water shield") {}
|
|
};
|
|
|
|
class LightningShieldTrigger : public BuffTrigger
|
|
{
|
|
public:
|
|
LightningShieldTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "lightning shield") {}
|
|
};
|
|
|
|
class WaterWalkingTrigger : public BuffTrigger
|
|
{
|
|
public:
|
|
WaterWalkingTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "water walking", 7) {}
|
|
|
|
bool IsActive() override;
|
|
};
|
|
|
|
class WaterBreathingTrigger : public BuffTrigger
|
|
{
|
|
public:
|
|
WaterBreathingTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "water breathing", 5 * 2000) {}
|
|
|
|
bool IsActive() override;
|
|
};
|
|
|
|
class WaterWalkingOnPartyTrigger : public BuffOnPartyTrigger
|
|
{
|
|
public:
|
|
WaterWalkingOnPartyTrigger(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, "water walking on party", 2 * 2000) {}
|
|
|
|
bool IsActive() override;
|
|
};
|
|
|
|
class WaterBreathingOnPartyTrigger : public BuffOnPartyTrigger
|
|
{
|
|
public:
|
|
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* botAI) : Trigger(botAI, "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:
|
|
CleanseSpiritPoisonTrigger(PlayerbotAI* botAI) : NeedCureTrigger(botAI, "cleanse spirit", DISPEL_POISON) {}
|
|
};
|
|
|
|
class PartyMemberCleanseSpiritPoisonTrigger : public PartyMemberNeedCureTrigger
|
|
{
|
|
public:
|
|
PartyMemberCleanseSpiritPoisonTrigger(PlayerbotAI* botAI)
|
|
: PartyMemberNeedCureTrigger(botAI, "cleanse spirit", DISPEL_POISON) {}
|
|
};
|
|
|
|
class CleanseSpiritCurseTrigger : public NeedCureTrigger
|
|
{
|
|
public:
|
|
CleanseSpiritCurseTrigger(PlayerbotAI* botAI) : NeedCureTrigger(botAI, "cleanse spirit", DISPEL_CURSE) {}
|
|
};
|
|
|
|
class PartyMemberCleanseSpiritCurseTrigger : public PartyMemberNeedCureTrigger
|
|
{
|
|
public:
|
|
PartyMemberCleanseSpiritCurseTrigger(PlayerbotAI* botAI)
|
|
: PartyMemberNeedCureTrigger(botAI, "cleanse spirit", DISPEL_CURSE) {}
|
|
};
|
|
|
|
class CleanseSpiritDiseaseTrigger : public NeedCureTrigger
|
|
{
|
|
public:
|
|
CleanseSpiritDiseaseTrigger(PlayerbotAI* botAI) : NeedCureTrigger(botAI, "cleanse spirit", DISPEL_DISEASE) {}
|
|
};
|
|
|
|
class PartyMemberCleanseSpiritDiseaseTrigger : public PartyMemberNeedCureTrigger
|
|
{
|
|
public:
|
|
PartyMemberCleanseSpiritDiseaseTrigger(PlayerbotAI* botAI)
|
|
: PartyMemberNeedCureTrigger(botAI, "cleanse spirit", DISPEL_DISEASE) {}
|
|
};
|
|
|
|
// Damage and Debuff Triggers
|
|
|
|
class ShockTrigger : public DebuffTrigger
|
|
{
|
|
public:
|
|
ShockTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "earth shock", 1, true) {}
|
|
|
|
bool IsActive() override;
|
|
};
|
|
|
|
class FrostShockSnareTrigger : public SnareTargetTrigger
|
|
{
|
|
public:
|
|
FrostShockSnareTrigger(PlayerbotAI* botAI) : SnareTargetTrigger(botAI, "frost shock") {}
|
|
};
|
|
|
|
class MaelstromWeaponTrigger : public HasAuraStackTrigger
|
|
{
|
|
public:
|
|
MaelstromWeaponTrigger(PlayerbotAI* botAI, int stack = 5) : HasAuraStackTrigger(botAI, "maelstrom weapon", stack) {}
|
|
};
|
|
|
|
class FlameShockTrigger : public DebuffTrigger
|
|
{
|
|
public:
|
|
FlameShockTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "flame shock", 1, true, 6.0f) {}
|
|
bool IsActive() override { return BuffTrigger::IsActive(); }
|
|
};
|
|
|
|
class EarthShockExecuteTrigger : public Trigger
|
|
{
|
|
public:
|
|
EarthShockExecuteTrigger(PlayerbotAI* botAI) : Trigger(botAI, "earth shock execute") {}
|
|
|
|
bool IsActive() override;
|
|
};
|
|
|
|
class MaelstromWeapon5AndMediumAoeTrigger : public TwoTriggers
|
|
{
|
|
public:
|
|
MaelstromWeapon5AndMediumAoeTrigger(PlayerbotAI* botAI) : TwoTriggers(botAI, "maelstrom weapon 5", "medium aoe") {}
|
|
};
|
|
|
|
class MaelstromWeapon4AndMediumAoeTrigger : public TwoTriggers
|
|
{
|
|
public:
|
|
MaelstromWeapon4AndMediumAoeTrigger(PlayerbotAI* botAI) : TwoTriggers(botAI, "maelstrom weapon 4", "medium aoe") {}
|
|
};
|
|
|
|
class ChainLightningNoCdTrigger : public SpellNoCooldownTrigger
|
|
{
|
|
public:
|
|
ChainLightningNoCdTrigger(PlayerbotAI* botAI) : SpellNoCooldownTrigger(botAI, "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 CallOfTheElementsTrigger : public Trigger
|
|
{
|
|
public:
|
|
CallOfTheElementsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "call of the elements") {}
|
|
bool IsActive() override;
|
|
};
|
|
|
|
class TotemicRecallTrigger : public Trigger
|
|
{
|
|
public:
|
|
TotemicRecallTrigger(PlayerbotAI* botAI) : Trigger(botAI, "totemic recall") {}
|
|
bool IsActive() override;
|
|
};
|
|
|
|
class NoEarthTotemTrigger : public Trigger
|
|
{
|
|
public:
|
|
NoEarthTotemTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no earth totem") {}
|
|
bool IsActive() override;
|
|
};
|
|
|
|
class NoFireTotemTrigger : public Trigger
|
|
{
|
|
public:
|
|
NoFireTotemTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no fire totem") {}
|
|
bool IsActive() override;
|
|
};
|
|
|
|
class NoWaterTotemTrigger : public Trigger
|
|
{
|
|
public:
|
|
NoWaterTotemTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no water totem") {}
|
|
bool IsActive() override;
|
|
};
|
|
|
|
class NoAirTotemTrigger : public Trigger
|
|
{
|
|
public:
|
|
NoAirTotemTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no air totem") {}
|
|
bool IsActive() override;
|
|
};
|
|
|
|
class CallOfTheElementsAndEnemyWithinMeleeTrigger : public TwoTriggers
|
|
{
|
|
public:
|
|
CallOfTheElementsAndEnemyWithinMeleeTrigger(PlayerbotAI* botAI) : TwoTriggers(botAI, "call of the elements", "enemy within melee") {}
|
|
};
|
|
|
|
// Set Strategy Assigned Totems
|
|
|
|
class SetTotemTrigger : public Trigger
|
|
{
|
|
public:
|
|
// Template constructor: infers N (size of the id array) at compile time
|
|
template <size_t N>
|
|
SetTotemTrigger(PlayerbotAI* botAI, std::string const& spellName, const uint32 (&ids)[N], int actionButtonId)
|
|
: Trigger(botAI, "set " + spellName)
|
|
, totemSpellIds(ids)
|
|
, totemSpellIdsCount(N)
|
|
, actionButtonId(actionButtonId)
|
|
{}
|
|
bool IsActive() override;
|
|
|
|
private:
|
|
uint32 const* totemSpellIds;
|
|
size_t totemSpellIdsCount;
|
|
int actionButtonId;
|
|
};
|
|
|
|
class SetStrengthOfEarthTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetStrengthOfEarthTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "strength of earth totem", STRENGTH_OF_EARTH_TOTEM, TOTEM_BAR_SLOT_EARTH) {}
|
|
};
|
|
|
|
class SetStoneskinTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetStoneskinTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "stoneskin totem", STONESKIN_TOTEM, TOTEM_BAR_SLOT_EARTH) {}
|
|
};
|
|
|
|
class SetTremorTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetTremorTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "tremor totem", TREMOR_TOTEM, TOTEM_BAR_SLOT_EARTH) {}
|
|
};
|
|
|
|
class SetEarthbindTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetEarthbindTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "earthbind totem", EARTHBIND_TOTEM, TOTEM_BAR_SLOT_EARTH) {}
|
|
};
|
|
|
|
class SetSearingTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetSearingTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "searing totem", SEARING_TOTEM, TOTEM_BAR_SLOT_FIRE) {}
|
|
};
|
|
|
|
class SetMagmaTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetMagmaTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "magma totem", MAGMA_TOTEM, TOTEM_BAR_SLOT_FIRE) {}
|
|
};
|
|
|
|
class SetFlametongueTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetFlametongueTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "flametongue totem", FLAMETONGUE_TOTEM, TOTEM_BAR_SLOT_FIRE) {}
|
|
};
|
|
|
|
class SetTotemOfWrathTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetTotemOfWrathTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "totem of wrath", TOTEM_OF_WRATH, TOTEM_BAR_SLOT_FIRE) {}
|
|
};
|
|
|
|
class SetFrostResistanceTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetFrostResistanceTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "frost resistance totem", FROST_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_FIRE) {}
|
|
};
|
|
|
|
class SetHealingStreamTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetHealingStreamTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "healing stream totem", HEALING_STREAM_TOTEM, TOTEM_BAR_SLOT_WATER) {}
|
|
};
|
|
|
|
class SetManaSpringTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetManaSpringTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "mana spring totem", MANA_SPRING_TOTEM, TOTEM_BAR_SLOT_WATER) {}
|
|
};
|
|
|
|
class SetCleansingTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetCleansingTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "cleansing totem", CLEANSING_TOTEM, TOTEM_BAR_SLOT_WATER) {}
|
|
};
|
|
|
|
class SetFireResistanceTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetFireResistanceTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "fire resistance totem", FIRE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_WATER) {}
|
|
};
|
|
|
|
class SetWrathOfAirTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetWrathOfAirTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "wrath of air totem", WRATH_OF_AIR_TOTEM, TOTEM_BAR_SLOT_AIR) {}
|
|
};
|
|
|
|
class SetWindfuryTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetWindfuryTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "windfury totem", WINDFURY_TOTEM, TOTEM_BAR_SLOT_AIR) {}
|
|
};
|
|
|
|
class SetNatureResistanceTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetNatureResistanceTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "nature resistance totem", NATURE_RESISTANCE_TOTEM, TOTEM_BAR_SLOT_AIR) {}
|
|
};
|
|
|
|
class SetGroundingTotemTrigger : public SetTotemTrigger
|
|
{
|
|
public:
|
|
SetGroundingTotemTrigger(PlayerbotAI* botAI)
|
|
: SetTotemTrigger(botAI, "grounding totem", GROUNDING_TOTEM, TOTEM_BAR_SLOT_AIR) {}
|
|
};
|
|
|
|
#endif
|