/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#include "PlayerAI.h"
#include "Creature.h"
#include "Item.h"
#include "Map.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "Spell.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "SpellHistory.h"
#include "SpellMgr.h"
enum Spells
{
/* Generic */
SPELL_AUTO_SHOT = 75,
SPELL_SHOOT = 3018,
SPELL_THROW = 2764,
SPELL_SHOOT_WAND = 5019,
/* Warrior - Generic */
SPELL_BATTLE_STANCE = 2457,
SPELL_BERSERKER_STANCE = 2458,
SPELL_DEFENSIVE_STANCE = 71,
SPELL_CHARGE = 11578,
SPELL_INTERCEPT = 20252,
SPELL_ENRAGED_REGEN = 55694,
SPELL_INTIMIDATING_SHOUT= 5246,
SPELL_PUMMEL = 6552,
SPELL_SHIELD_BASH = 72,
SPELL_BLOODRAGE = 2687,
/* Warrior - Arms */
SPELL_SWEEPING_STRIKES = 12328,
SPELL_MORTAL_STRIKE = 12294,
SPELL_BLADESTORM = 46924,
SPELL_REND = 47465,
SPELL_RETALIATION = 20230,
SPELL_SHATTERING_THROW = 64382,
SPELL_THUNDER_CLAP = 47502,
/* Warrior - Fury */
SPELL_DEATH_WISH = 12292,
SPELL_BLOODTHIRST = 23881,
PASSIVE_TITANS_GRIP = 46917,
SPELL_DEMO_SHOUT = 47437,
SPELL_EXECUTE = 47471,
SPELL_HEROIC_FURY = 60970,
SPELL_RECKLESSNESS = 1719,
SPELL_PIERCING_HOWL = 12323,
/* Warrior - Protection */
SPELL_VIGILANCE = 50720,
SPELL_DEVASTATE = 20243,
SPELL_SHOCKWAVE = 46968,
SPELL_CONCUSSION_BLOW = 12809,
SPELL_DISARM = 676,
SPELL_LAST_STAND = 12975,
SPELL_SHIELD_BLOCK = 2565,
SPELL_SHIELD_SLAM = 47488,
SPELL_SHIELD_WALL = 871,
SPELL_SPELL_REFLECTION = 23920,
/* Paladin - Generic */
SPELL_PAL_AURA_MASTERY = 31821,
SPELL_LAY_ON_HANDS = 48788,
SPELL_BLESSING_OF_MIGHT = 48932,
SPELL_AVENGING_WRATH = 31884,
SPELL_DIVINE_PROTECTION = 498,
SPELL_DIVINE_SHIELD = 642,
SPELL_HAMMER_OF_JUSTICE = 10308,
SPELL_HAND_OF_FREEDOM = 1044,
SPELL_HAND_OF_PROTECTION = 10278,
SPELL_HAND_OF_SACRIFICE = 6940,
/* Paladin - Holy*/
PASSIVE_ILLUMINATION = 20215,
SPELL_HOLY_SHOCK = 20473,
SPELL_BEACON_OF_LIGHT = 53563,
SPELL_CONSECRATION = 48819,
SPELL_FLASH_OF_LIGHT = 48785,
SPELL_HOLY_LIGHT = 48782,
SPELL_DIVINE_FAVOR = 20216,
SPELL_DIVINE_ILLUMINATION = 31842,
/* Paladin - Protection */
SPELL_BLESS_OF_SANC = 20911,
SPELL_HOLY_SHIELD = 20925,
SPELL_AVENGERS_SHIELD = 48827,
SPELL_DIVINE_SACRIFICE = 64205,
SPELL_HAMMER_OF_RIGHTEOUS = 53595,
SPELL_RIGHTEOUS_FURY = 25780,
SPELL_SHIELD_OF_RIGHTEOUS = 61411,
/* Paladin - Retribution */
SPELL_SEAL_OF_COMMAND = 20375,
SPELL_CRUSADER_STRIKE = 35395,
SPELL_DIVINE_STORM = 53385,
SPELL_JUDGEMENT = 20271,
SPELL_HAMMER_OF_WRATH = 48806,
/* Hunter - Generic */
SPELL_DETERRENCE = 19263,
SPELL_EXPLOSIVE_TRAP = 49067,
SPELL_FREEZING_ARROW = 60192,
SPELL_RAPID_FIRE = 3045,
SPELL_KILL_SHOT = 61006,
SPELL_MULTI_SHOT = 49048,
SPELL_VIPER_STING = 3034,
/* Hunter - Beast Mastery */
SPELL_BESTIAL_WRATH = 19574,
PASSIVE_BEAST_WITHIN = 34692,
PASSIVE_BEAST_MASTERY = 53270,
/* Hunter - Marksmanship */
SPELL_AIMED_SHOT = 19434,
PASSIVE_TRUESHOT_AURA = 19506,
SPELL_CHIMERA_SHOT = 53209,
SPELL_ARCANE_SHOT = 49045,
SPELL_STEADY_SHOT = 49052,
SPELL_READINESS = 23989,
SPELL_SILENCING_SHOT = 34490,
/* Hunter - Survival */
PASSIVE_LOCK_AND_LOAD = 56344,
SPELL_WYVERN_STING = 19386,
SPELL_EXPLOSIVE_SHOT = 53301,
SPELL_BLACK_ARROW = 3674,
/* Rogue - Generic */
SPELL_DISMANTLE = 51722,
SPELL_EVASION = 26669,
SPELL_KICK = 1766,
SPELL_VANISH = 26889,
SPELL_BLIND = 2094,
SPELL_CLOAK_OF_SHADOWS = 31224,
/* Rogue - Assassination */
SPELL_COLD_BLOOD = 14177,
SPELL_MUTILATE = 1329,
SPELL_HUNGER_FOR_BLOOD = 51662,
SPELL_ENVENOM = 57993,
/* Rogue - Combat */
SPELL_SINISTER_STRIKE = 48637,
SPELL_BLADE_FLURRY = 13877,
SPELL_ADRENALINE_RUSH = 13750,
SPELL_KILLING_SPREE = 51690,
SPELL_EVISCERATE = 48668,
/* Rogue - Sublety */
SPELL_HEMORRHAGE = 16511,
SPELL_PREMEDITATION = 14183,
SPELL_SHADOW_DANCE = 51713,
SPELL_ROGUE_PREPARATION = 14185,
SPELL_SHADOWSTEP = 36554,
/* Priest - Generic */
SPELL_FEAR_WARD = 6346,
SPELL_POWER_WORD_FORT = 48161,
SPELL_DIVINE_SPIRIT = 48073,
SPELL_SHADOW_PROTECTION = 48169,
SPELL_DIVINE_HYMN = 64843,
SPELL_HYMN_OF_HOPE = 64901,
SPELL_SHADOW_WORD_DEATH = 48158,
SPELL_PSYCHIC_SCREAM = 10890,
/* Priest - Discipline */
PASSIVE_SOUL_WARDING = 63574,
SPELL_POWER_INFUSION = 10060,
SPELL_PENANCE = 47540,
SPELL_PAIN_SUPPRESSION = 33206,
SPELL_INNER_FOCUS = 14751,
SPELL_POWER_WORD_SHIELD = 48066,
/* Priest - Holy */
PASSIVE_SPIRIT_REDEMPTION = 20711,
SPELL_DESPERATE_PRAYER = 19236,
SPELL_GUARDIAN_SPIRIT = 47788,
SPELL_FLASH_HEAL = 48071,
SPELL_RENEW = 48068,
/* Priest - Shadow */
SPELL_VAMPIRIC_EMBRACE = 15286,
SPELL_SHADOWFORM = 15473,
SPELL_VAMPIRIC_TOUCH = 34914,
SPELL_MIND_FLAY = 15407,
SPELL_MIND_BLAST = 48127,
SPELL_SHADOW_WORD_PAIN = 48125,
SPELL_DEVOURING_PLAGUE = 48300,
SPELL_DISPERSION = 47585,
/* Death Knight - Generic */
SPELL_DEATH_GRIP = 49576,
SPELL_STRANGULATE = 47476,
SPELL_EMPOWER_RUNE_WEAP = 47568,
SPELL_ICEBORN_FORTITUDE = 48792,
SPELL_ANTI_MAGIC_SHELL = 48707,
SPELL_DEATH_COIL_DK = 49895,
SPELL_MIND_FREEZE = 47528,
SPELL_ICY_TOUCH = 49909,
AURA_FROST_FEVER = 55095,
SPELL_PLAGUE_STRIKE = 49921,
AURA_BLOOD_PLAGUE = 55078,
SPELL_PESTILENCE = 50842,
/* Death Knight - Blood */
SPELL_RUNE_TAP = 48982,
SPELL_HYSTERIA = 49016,
SPELL_HEART_STRIKE = 55050,
SPELL_DEATH_STRIKE = 49924,
SPELL_BLOOD_STRIKE = 49930,
SPELL_MARK_OF_BLOOD = 49005,
SPELL_VAMPIRIC_BLOOD = 55233,
/* Death Knight - Frost */
PASSIVE_ICY_TALONS = 50887,
SPELL_FROST_STRIKE = 49143,
SPELL_HOWLING_BLAST = 49184,
SPELL_UNBREAKABLE_ARMOR = 51271,
SPELL_OBLITERATE = 51425,
SPELL_DEATHCHILL = 49796,
/* Death Knight - Unholy */
PASSIVE_UNHOLY_BLIGHT = 49194,
PASSIVE_MASTER_OF_GHOUL = 52143,
SPELL_SCOURGE_STRIKE = 55090,
SPELL_DEATH_AND_DECAY = 49938,
SPELL_ANTI_MAGIC_ZONE = 51052,
SPELL_SUMMON_GARGOYLE = 49206,
/* Shaman - Generic */
SPELL_HEROISM = 32182,
SPELL_BLOODLUST = 2825,
SPELL_GROUNDING_TOTEM = 8177,
/* Shaman - Elemental*/
PASSIVE_ELEMENTAL_FOCUS = 16164,
SPELL_TOTEM_OF_WRATH = 30706,
SPELL_THUNDERSTORM = 51490,
SPELL_LIGHTNING_BOLT = 49238,
SPELL_EARTH_SHOCK = 49231,
SPELL_FLAME_SHOCK = 49233,
SPELL_LAVA_BURST = 60043,
SPELL_CHAIN_LIGHTNING = 49271,
SPELL_ELEMENTAL_MASTERY = 16166,
/* Shaman - Enhancement */
PASSIVE_SPIRIT_WEAPONS = 16268,
SPELL_LAVA_LASH = 60103,
SPELL_FERAL_SPIRIT = 51533,
AURA_MAELSTROM_WEAPON = 53817,
SPELL_STORMSTRIKE = 17364,
SPELL_SHAMANISTIC_RAGE = 30823,
/* Shaman - Restoration*/
SPELL_SHA_NATURE_SWIFT = 591,
SPELL_MANA_TIDE_TOTEM = 590,
SPELL_EARTH_SHIELD = 49284,
SPELL_RIPTIDE = 61295,
SPELL_HEALING_WAVE = 49273,
SPELL_LESSER_HEAL_WAVE = 49276,
SPELL_TIDAL_FORCE = 55198,
/* Mage - Generic */
SPELL_DAMPEN_MAGIC = 43015,
SPELL_EVOCATION = 12051,
SPELL_MANA_SHIELD = 43020,
SPELL_MIRROR_IMAGE = 55342,
SPELL_SPELLSTEAL = 30449,
SPELL_COUNTERSPELL = 2139,
SPELL_ICE_BLOCK = 45438,
/* Mage - Arcane */
SPELL_FOCUS_MAGIC = 54646,
SPELL_ARCANE_POWER = 12042,
SPELL_ARCANE_BARRAGE = 44425,
SPELL_ARCANE_BLAST = 42897,
AURA_ARCANE_BLAST = 36032,
SPELL_ARCANE_MISSILES = 42846,
SPELL_PRESENCE_OF_MIND = 12043,
/* Mage - Fire */
SPELL_PYROBLAST = 11366,
SPELL_COMBUSTION = 11129,
SPELL_LIVING_BOMB = 44457,
SPELL_FIREBALL = 42833,
SPELL_FIRE_BLAST = 42873,
SPELL_DRAGONS_BREATH = 31661,
SPELL_BLAST_WAVE = 11113,
/* Mage - Frost */
SPELL_ICY_VEINS = 12472,
SPELL_ICE_BARRIER = 11426,
SPELL_DEEP_FREEZE = 44572,
SPELL_FROST_NOVA = 42917,
SPELL_FROSTBOLT = 42842,
SPELL_COLD_SNAP = 11958,
SPELL_ICE_LANCE = 42914,
/* Warlock - Generic */
SPELL_FEAR = 6215,
SPELL_HOWL_OF_TERROR = 17928,
SPELL_CORRUPTION = 47813,
SPELL_DEATH_COIL_W = 47860,
SPELL_SHADOW_BOLT = 47809,
SPELL_INCINERATE = 47838,
SPELL_IMMOLATE = 47811,
SPELL_SEED_OF_CORRUPTION = 47836,
/* Warlock - Affliction */
PASSIVE_SIPHON_LIFE = 63108,
SPELL_UNSTABLE_AFFLICTION = 30108,
SPELL_HAUNT = 48181,
SPELL_CURSE_OF_AGONY = 47864,
SPELL_DRAIN_SOUL = 47855,
/* Warlock - Demonology */
SPELL_SOUL_LINK = 19028,
SPELL_DEMONIC_EMPOWERMENT = 47193,
SPELL_METAMORPHOSIS = 59672,
SPELL_IMMOLATION_AURA = 50589,
SPELL_DEMON_CHARGE = 54785,
AURA_DECIMATION = 63167,
AURA_MOLTEN_CORE = 71165,
SPELL_SOUL_FIRE = 47825,
/* Warlock - Destruction */
SPELL_SHADOWBURN = 17877,
SPELL_CONFLAGRATE = 17962,
SPELL_CHAOS_BOLT = 50796,
SPELL_SHADOWFURY = 47847,
/* Druid - Generic */
SPELL_BARKSKIN = 22812,
SPELL_INNERVATE = 29166,
/* Druid - Balance */
SPELL_INSECT_SWARM = 5570,
SPELL_MOONKIN_FORM = 24858,
SPELL_STARFALL = 48505,
SPELL_TYPHOON = 61384,
AURA_ECLIPSE_LUNAR = 48518,
SPELL_MOONFIRE = 48463,
SPELL_STARFIRE = 48465,
SPELL_WRATH = 48461,
/* Druid - Feral */
SPELL_CAT_FORM = 768,
SPELL_SURVIVAL_INSTINCTS = 61336,
SPELL_MANGLE = 33917,
SPELL_BERSERK = 50334,
SPELL_MANGLE_CAT = 48566,
SPELL_FERAL_CHARGE_CAT = 49376,
SPELL_RAKE = 48574,
SPELL_RIP = 49800,
SPELL_SAVAGE_ROAR = 52610,
SPELL_TIGER_FURY = 50213,
SPELL_CLAW = 48570,
SPELL_DASH = 33357,
SPELL_MAIM = 49802,
/* Druid - Restoration */
SPELL_SWIFTMEND = 18562,
SPELL_TREE_OF_LIFE = 33891,
SPELL_WILD_GROWTH = 48438,
SPELL_NATURE_SWIFTNESS = 17116,
SPELL_TRANQUILITY = 48447,
SPELL_NOURISH = 50464,
SPELL_HEALING_TOUCH = 48378,
SPELL_REJUVENATION = 48441,
SPELL_REGROWTH = 48443,
SPELL_LIFEBLOOM = 48451
};
PlayerAI::PlayerAI(Player* player) : UnitAI(player), me(player),
_selfSpec(player->GetPrimarySpecialization()),
_isSelfHealer(PlayerAI::IsPlayerHealer(player)),
_isSelfRangedAttacker(PlayerAI::IsPlayerRangedAttacker(player))
{
}
Creature* PlayerAI::GetCharmer() const
{
if (me->GetCharmerGUID().IsCreature())
return ObjectAccessor::GetCreature(*me, me->GetCharmerGUID());
return nullptr;
}
ChrSpecialization PlayerAI::GetSpec(Player const* who /*= nullptr*/) const
{
return (!who || who == me) ? _selfSpec : who->GetPrimarySpecialization();
}
bool PlayerAI::IsPlayerHealer(Player const* who)
{
if (!who)
return false;
ChrSpecializationEntry const* chrSpec = who->GetPrimarySpecializationEntry();
return chrSpec && chrSpec->GetRole() == ChrSpecializationRole::Healer;
}
bool PlayerAI::IsPlayerRangedAttacker(Player const* who)
{
if (!who)
return false;
ChrSpecializationEntry const* chrSpec = who->GetPrimarySpecializationEntry();
return chrSpec && chrSpec->GetFlags().HasFlag(ChrSpecializationFlag::Ranged);
}
PlayerAI::TargetedSpell PlayerAI::VerifySpellCast(uint32 spellId, Unit* target)
{
// Find highest spell rank that we know
uint32 knownRank, nextRank;
if (me->HasSpell(spellId))
{
// this will save us some lookups if the player has the highest rank (expected case)
knownRank = spellId;
nextRank = sSpellMgr->GetNextSpellInChain(spellId);
}
else
{
knownRank = 0;
nextRank = sSpellMgr->GetFirstSpellInChain(spellId);
}
while (nextRank && me->HasSpell(nextRank))
{
knownRank = nextRank;
nextRank = sSpellMgr->GetNextSpellInChain(knownRank);
}
if (!knownRank)
return {};
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(knownRank, me->GetMap()->GetDifficultyID());
if (!spellInfo)
return {};
if (me->GetSpellHistory()->HasGlobalCooldown(spellInfo))
return {};
Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE);
if (spell->CanAutoCast(target))
return{ spell, target };
delete spell;
return {};
}
PlayerAI::TargetedSpell PlayerAI::VerifySpellCast(uint32 spellId, SpellTarget target)
{
Unit* pTarget = nullptr;
switch (target)
{
case TARGET_NONE:
break;
case TARGET_VICTIM:
pTarget = me->GetVictim();
if (!pTarget)
return {};
break;
case TARGET_CHARMER:
pTarget = me->GetCharmer();
if (!pTarget)
return {};
break;
case TARGET_SELF:
pTarget = me;
break;
}
return VerifySpellCast(spellId, pTarget);
}
PlayerAI::TargetedSpell PlayerAI::SelectSpellCast(PossibleSpellVector& spells)
{
if (spells.empty())
return{};
uint32 totalWeights = 0;
for (PossibleSpell const& wSpell : spells)
totalWeights += wSpell.second;
TargetedSpell selected;
uint32 randNum = urand(0, totalWeights - 1);
for (PossibleSpell const& wSpell : spells)
{
if (selected)
{
delete wSpell.first.first;
continue;
}
if (randNum < wSpell.second)
selected = wSpell.first;
else
{
randNum -= wSpell.second;
delete wSpell.first.first;
}
}
spells.clear();
return selected;
}
void PlayerAI::DoCastAtTarget(TargetedSpell spell)
{
SpellCastTargets targets;
targets.SetUnitTarget(spell.second);
spell.first->prepare(targets);
}
void PlayerAI::DoRangedAttackIfReady()
{
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
if (!me->isAttackReady(RANGED_ATTACK))
return;
Unit* victim = me->GetVictim();
if (!victim)
return;
uint32 rangedAttackSpell = 0;
Item const* rangedItem = me->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);
if (ItemTemplate const* rangedTemplate = rangedItem ? rangedItem->GetTemplate() : nullptr)
{
switch (rangedTemplate->GetSubClass())
{
case ITEM_SUBCLASS_WEAPON_BOW:
case ITEM_SUBCLASS_WEAPON_GUN:
case ITEM_SUBCLASS_WEAPON_CROSSBOW:
rangedAttackSpell = SPELL_SHOOT;
break;
case ITEM_SUBCLASS_WEAPON_THROWN:
rangedAttackSpell = SPELL_THROW;
break;
case ITEM_SUBCLASS_WEAPON_WAND:
rangedAttackSpell = SPELL_SHOOT_WAND;
break;
}
}
if (!rangedAttackSpell)
return;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(rangedAttackSpell, me->GetMap()->GetDifficultyID());
if (!spellInfo)
return;
Spell* spell = new Spell(me, spellInfo, TRIGGERED_CAST_DIRECTLY);
if (spell->CheckPetCast(victim) != SPELL_CAST_OK)
{
delete spell;
return;
}
SpellCastTargets targets;
targets.SetUnitTarget(victim);
spell->prepare(targets);
me->resetAttackTimer(RANGED_ATTACK);
}
void PlayerAI::DoAutoAttackIfReady()
{
if (IsRangedAttacker())
DoRangedAttackIfReady();
}
void PlayerAI::CancelAllShapeshifts()
{
Unit::AuraEffectList const& shapeshiftAuras = me->GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT);
std::set removableShapeshifts;
for (AuraEffect* auraEff : shapeshiftAuras)
{
Aura* aura = auraEff->GetBase();
if (!aura)
continue;
SpellInfo const* auraInfo = aura->GetSpellInfo();
if (!auraInfo)
continue;
if (auraInfo->HasAttribute(SPELL_ATTR0_NO_AURA_CANCEL))
continue;
if (!auraInfo->IsPositive() || auraInfo->IsPassive())
continue;
removableShapeshifts.insert(aura);
}
for (Aura* aura : removableShapeshifts)
me->RemoveOwnedAura(aura, AURA_REMOVE_BY_CANCEL);
}
Unit* PlayerAI::SelectAttackTarget() const
{
return me->GetCharmer() ? me->GetCharmer()->GetVictim() : nullptr;
}
struct ValidTargetSelectPredicate
{
ValidTargetSelectPredicate(UnitAI const* ai) : _ai(ai) { }
UnitAI const* const _ai;
bool operator()(Unit const* target) const
{
return _ai->CanAIAttack(target);
}
};
bool SimpleCharmedPlayerAI::CanAIAttack(Unit const* who) const
{
if (!me->IsValidAttackTarget(who) || who->HasBreakableByDamageCrowdControlAura())
return false;
if (Unit* charmer = me->GetCharmer())
if (!charmer->IsValidAttackTarget(who))
return false;
return UnitAI::CanAIAttack(who);
}
Unit* SimpleCharmedPlayerAI::SelectAttackTarget() const
{
if (Unit* charmer = me->GetCharmer())
{
if (UnitAI* charmerAI = charmer->GetAI())
return charmerAI->SelectTarget(SelectTargetMethod::Random, 0, ValidTargetSelectPredicate(this));
return charmer->GetVictim();
}
return nullptr;
}
PlayerAI::TargetedSpell SimpleCharmedPlayerAI::SelectAppropriateCastForSpec()
{
PossibleSpellVector spells;
/*
switch (me->getClass())
{
case CLASS_WARRIOR:
if (!me->IsWithinMeleeRange(me->GetVictim()))
{
VerifyAndPushSpellCast(spells, SPELL_CHARGE, TARGET_VICTIM, 15);
VerifyAndPushSpellCast(spells, SPELL_INTERCEPT, TARGET_VICTIM, 10);
}
VerifyAndPushSpellCast(spells, SPELL_ENRAGED_REGEN, TARGET_NONE, 3);
VerifyAndPushSpellCast(spells, SPELL_INTIMIDATING_SHOUT, TARGET_VICTIM, 4);
if (me->GetVictim() && me->GetVictim()->HasUnitState(UNIT_STATE_CASTING))
{
VerifyAndPushSpellCast(spells, SPELL_PUMMEL, TARGET_VICTIM, 15);
VerifyAndPushSpellCast(spells, SPELL_SHIELD_BASH, TARGET_VICTIM, 15);
}
VerifyAndPushSpellCast(spells, SPELL_BLOODRAGE, TARGET_NONE, 5);
switch (GetSpec())
{
case TALENT_SPEC_WARRIOR_PROTECTION:
VerifyAndPushSpellCast(spells, SPELL_SHOCKWAVE, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_CONCUSSION_BLOW, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_DISARM, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_LAST_STAND, TARGET_NONE, 5);
VerifyAndPushSpellCast(spells, SPELL_SHIELD_BLOCK, TARGET_NONE, 1);
VerifyAndPushSpellCast(spells, SPELL_SHIELD_SLAM, TARGET_VICTIM, 4);
VerifyAndPushSpellCast(spells, SPELL_SHIELD_WALL, TARGET_NONE, 5);
VerifyAndPushSpellCast(spells, SPELL_SPELL_REFLECTION, TARGET_NONE, 3);
VerifyAndPushSpellCast(spells, SPELL_DEVASTATE, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_REND, TARGET_VICTIM, 1);
VerifyAndPushSpellCast(spells, SPELL_THUNDER_CLAP, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_DEMO_SHOUT, TARGET_VICTIM, 1);
break;
case TALENT_SPEC_WARRIOR_ARMS:
VerifyAndPushSpellCast(spells, SPELL_SWEEPING_STRIKES, TARGET_NONE, 2);
VerifyAndPushSpellCast(spells, SPELL_MORTAL_STRIKE, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_BLADESTORM, TARGET_NONE, 10);
VerifyAndPushSpellCast(spells, SPELL_REND, TARGET_VICTIM, 1);
VerifyAndPushSpellCast(spells, SPELL_RETALIATION, TARGET_NONE, 3);
VerifyAndPushSpellCast(spells, SPELL_SHATTERING_THROW, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_SWEEPING_STRIKES, TARGET_NONE, 5);
VerifyAndPushSpellCast(spells, SPELL_THUNDER_CLAP, TARGET_VICTIM, 1);
VerifyAndPushSpellCast(spells, SPELL_EXECUTE, TARGET_VICTIM, 15);
break;
case TALENT_SPEC_WARRIOR_FURY:
VerifyAndPushSpellCast(spells, SPELL_DEATH_WISH, TARGET_NONE, 10);
VerifyAndPushSpellCast(spells, SPELL_BLOODTHIRST, TARGET_VICTIM, 4);
VerifyAndPushSpellCast(spells, SPELL_DEMO_SHOUT, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_EXECUTE, TARGET_VICTIM, 15);
VerifyAndPushSpellCast(spells, SPELL_HEROIC_FURY, TARGET_NONE, 5);
VerifyAndPushSpellCast(spells, SPELL_RECKLESSNESS, TARGET_NONE, 8);
VerifyAndPushSpellCast(spells, SPELL_PIERCING_HOWL, TARGET_VICTIM, 2);
break;
}
break;
case CLASS_PALADIN:
VerifyAndPushSpellCast(spells, SPELL_AURA_MASTERY, TARGET_NONE, 3);
VerifyAndPushSpellCast(spells, SPELL_LAY_ON_HANDS, TARGET_CHARMER, 8);
VerifyAndPushSpellCast(spells, SPELL_BLESSING_OF_MIGHT, TARGET_CHARMER, 8);
VerifyAndPushSpellCast(spells, SPELL_AVENGING_WRATH, TARGET_NONE, 5);
VerifyAndPushSpellCast(spells, SPELL_DIVINE_PROTECTION, TARGET_NONE, 4);
VerifyAndPushSpellCast(spells, SPELL_DIVINE_SHIELD, TARGET_NONE, 2);
VerifyAndPushSpellCast(spells, SPELL_HAMMER_OF_JUSTICE, TARGET_VICTIM, 6);
VerifyAndPushSpellCast(spells, SPELL_HAND_OF_FREEDOM, TARGET_SELF, 3);
VerifyAndPushSpellCast(spells, SPELL_HAND_OF_PROTECTION, TARGET_SELF, 1);
if (Creature* creatureCharmer = GetCharmer())
{
if (creatureCharmer->IsDungeonBoss() || creatureCharmer->isWorldBoss())
VerifyAndPushSpellCast(spells, SPELL_HAND_OF_SACRIFICE, creatureCharmer, 10);
else
VerifyAndPushSpellCast(spells, SPELL_HAND_OF_PROTECTION, creatureCharmer, 3);
}
switch (GetSpec())
{
case TALENT_SPEC_PALADIN_PROTECTION:
VerifyAndPushSpellCast(spells, SPELL_HAMMER_OF_RIGHTEOUS, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_DIVINE_SACRIFICE, TARGET_NONE, 2);
VerifyAndPushSpellCast(spells, SPELL_SHIELD_OF_RIGHTEOUS, TARGET_VICTIM, 4);
VerifyAndPushSpellCast(spells, SPELL_JUDGEMENT, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_CONSECRATION, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_HOLY_SHIELD, TARGET_NONE, 1);
break;
case TALENT_SPEC_PALADIN_HOLY:
VerifyAndPushSpellCast(spells, SPELL_HOLY_SHOCK, TARGET_CHARMER, 3);
VerifyAndPushSpellCast(spells, SPELL_HOLY_SHOCK, TARGET_VICTIM, 1);
VerifyAndPushSpellCast(spells, SPELL_FLASH_OF_LIGHT, TARGET_CHARMER, 4);
VerifyAndPushSpellCast(spells, SPELL_HOLY_LIGHT, TARGET_CHARMER, 3);
VerifyAndPushSpellCast(spells, SPELL_DIVINE_FAVOR, TARGET_NONE, 5);
VerifyAndPushSpellCast(spells, SPELL_DIVINE_ILLUMINATION, TARGET_NONE, 3);
break;
case TALENT_SPEC_PALADIN_RETRIBUTION:
VerifyAndPushSpellCast(spells, SPELL_CRUSADER_STRIKE, TARGET_VICTIM, 4);
VerifyAndPushSpellCast(spells, SPELL_DIVINE_STORM, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_JUDGEMENT, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_HAMMER_OF_WRATH, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_RIGHTEOUS_FURY, TARGET_NONE, 2);
break;
}
break;
case CLASS_HUNTER:
VerifyAndPushSpellCast(spells, SPELL_DETERRENCE, TARGET_NONE, 3);
VerifyAndPushSpellCast(spells, SPELL_EXPLOSIVE_TRAP, TARGET_NONE, 1);
VerifyAndPushSpellCast(spells, SPELL_FREEZING_ARROW, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_RAPID_FIRE, TARGET_NONE, 10);
VerifyAndPushSpellCast(spells, SPELL_KILL_SHOT, TARGET_VICTIM, 10);
if (me->GetVictim() && me->GetVictim()->GetPowerType() == POWER_MANA && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_VIPER_STING, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_VIPER_STING, TARGET_VICTIM, 5);
switch (GetSpec())
{
case TALENT_SPEC_HUNTER_BEASTMASTER:
VerifyAndPushSpellCast(spells, SPELL_AIMED_SHOT, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_ARCANE_SHOT, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_STEADY_SHOT, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_MULTI_SHOT, TARGET_VICTIM, 2);
break;
case TALENT_SPEC_HUNTER_MARKSMAN:
VerifyAndPushSpellCast(spells, SPELL_AIMED_SHOT, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_CHIMERA_SHOT, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_ARCANE_SHOT, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_STEADY_SHOT, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_READINESS, TARGET_NONE, 10);
VerifyAndPushSpellCast(spells, SPELL_SILENCING_SHOT, TARGET_VICTIM, 5);
break;
case TALENT_SPEC_HUNTER_SURVIVAL:
VerifyAndPushSpellCast(spells, SPELL_EXPLOSIVE_SHOT, TARGET_VICTIM, 8);
VerifyAndPushSpellCast(spells, SPELL_BLACK_ARROW, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_MULTI_SHOT, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_STEADY_SHOT, TARGET_VICTIM, 1);
break;
}
break;
case CLASS_ROGUE:
{
VerifyAndPushSpellCast(spells, SPELL_DISMANTLE, TARGET_VICTIM, 8);
VerifyAndPushSpellCast(spells, SPELL_EVASION, TARGET_NONE, 8);
VerifyAndPushSpellCast(spells, SPELL_VANISH, TARGET_NONE, 4);
VerifyAndPushSpellCast(spells, SPELL_BLIND, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_CLOAK_OF_SHADOWS, TARGET_NONE, 2);
uint32 builder = 0, finisher = 0;
switch (GetSpec())
{
case TALENT_SPEC_ROGUE_ASSASSINATION:
builder = SPELL_MUTILATE, finisher = SPELL_ENVENOM;
VerifyAndPushSpellCast(spells, SPELL_COLD_BLOOD, TARGET_NONE, 20);
break;
case TALENT_SPEC_ROGUE_COMBAT:
builder = SPELL_SINISTER_STRIKE, finisher = SPELL_EVISCERATE;
VerifyAndPushSpellCast(spells, SPELL_ADRENALINE_RUSH, TARGET_NONE, 6);
VerifyAndPushSpellCast(spells, SPELL_BLADE_FLURRY, TARGET_NONE, 5);
VerifyAndPushSpellCast(spells, SPELL_KILLING_SPREE, TARGET_NONE, 25);
break;
case TALENT_SPEC_ROGUE_SUBTLETY:
builder = SPELL_HEMORRHAGE, finisher = SPELL_EVISCERATE;
VerifyAndPushSpellCast(spells, SPELL_ROGUE_PREPARATION, TARGET_NONE, 10);
if (!me->IsWithinMeleeRange(me->GetVictim()))
VerifyAndPushSpellCast(spells, SPELL_SHADOWSTEP, TARGET_VICTIM, 25);
VerifyAndPushSpellCast(spells, SPELL_SHADOW_DANCE, TARGET_NONE, 10);
break;
}
if (Unit* victim = me->GetVictim())
{
if (victim->HasUnitState(UNIT_STATE_CASTING))
VerifyAndPushSpellCast(spells, SPELL_KICK, TARGET_VICTIM, 25);
uint8 const cp = me->GetPower(POWER_COMBO_POINTS);
if (cp >= 4)
VerifyAndPushSpellCast(spells, finisher, TARGET_VICTIM, 10);
if (cp <= 4)
VerifyAndPushSpellCast(spells, builder, TARGET_VICTIM, 5);
}
break;
}
case CLASS_PRIEST:
VerifyAndPushSpellCast(spells, SPELL_FEAR_WARD, TARGET_SELF, 2);
VerifyAndPushSpellCast(spells, SPELL_POWER_WORD_FORT, TARGET_CHARMER, 1);
VerifyAndPushSpellCast(spells, SPELL_DIVINE_SPIRIT, TARGET_CHARMER, 1);
VerifyAndPushSpellCast(spells, SPELL_SHADOW_PROTECTION, TARGET_CHARMER, 2);
VerifyAndPushSpellCast(spells, SPELL_DIVINE_HYMN, TARGET_NONE, 5);
VerifyAndPushSpellCast(spells, SPELL_HYMN_OF_HOPE, TARGET_NONE, 5);
VerifyAndPushSpellCast(spells, SPELL_SHADOW_WORD_DEATH, TARGET_VICTIM, 1);
VerifyAndPushSpellCast(spells, SPELL_PSYCHIC_SCREAM, TARGET_VICTIM, 3);
switch (GetSpec())
{
case TALENT_SPEC_PRIEST_DISCIPLINE:
VerifyAndPushSpellCast(spells, SPELL_POWER_WORD_SHIELD, TARGET_CHARMER, 3);
VerifyAndPushSpellCast(spells, SPELL_INNER_FOCUS, TARGET_NONE, 3);
VerifyAndPushSpellCast(spells, SPELL_PAIN_SUPPRESSION, TARGET_CHARMER, 15);
VerifyAndPushSpellCast(spells, SPELL_POWER_INFUSION, TARGET_CHARMER, 10);
VerifyAndPushSpellCast(spells, SPELL_PENANCE, TARGET_CHARMER, 3);
VerifyAndPushSpellCast(spells, SPELL_FLASH_HEAL, TARGET_CHARMER, 1);
break;
case TALENT_SPEC_PRIEST_HOLY:
VerifyAndPushSpellCast(spells, SPELL_DESPERATE_PRAYER, TARGET_NONE, 3);
VerifyAndPushSpellCast(spells, SPELL_GUARDIAN_SPIRIT, TARGET_CHARMER, 5);
VerifyAndPushSpellCast(spells, SPELL_FLASH_HEAL, TARGET_CHARMER, 1);
VerifyAndPushSpellCast(spells, SPELL_RENEW, TARGET_CHARMER, 3);
break;
case TALENT_SPEC_PRIEST_SHADOW:
if (!me->HasAura(SPELL_SHADOWFORM))
{
VerifyAndPushSpellCast(spells, SPELL_SHADOWFORM, TARGET_NONE, 100);
break;
}
if (Unit* victim = me->GetVictim())
{
if (!victim->GetAuraApplicationOfRankedSpell(SPELL_VAMPIRIC_TOUCH, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_VAMPIRIC_TOUCH, TARGET_VICTIM, 4);
if (!victim->GetAuraApplicationOfRankedSpell(SPELL_SHADOW_WORD_PAIN, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_SHADOW_WORD_PAIN, TARGET_VICTIM, 3);
if (!victim->GetAuraApplicationOfRankedSpell(SPELL_DEVOURING_PLAGUE, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_DEVOURING_PLAGUE, TARGET_VICTIM, 4);
}
VerifyAndPushSpellCast(spells, SPELL_MIND_BLAST, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_MIND_FLAY, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_DISPERSION, TARGET_NONE, 10);
break;
}
break;
case CLASS_DEATH_KNIGHT:
{
if (!me->IsWithinMeleeRange(me->GetVictim()))
VerifyAndPushSpellCast(spells, SPELL_DEATH_GRIP, TARGET_VICTIM, 25);
VerifyAndPushSpellCast(spells, SPELL_STRANGULATE, TARGET_VICTIM, 15);
VerifyAndPushSpellCast(spells, SPELL_EMPOWER_RUNE_WEAP, TARGET_NONE, 5);
VerifyAndPushSpellCast(spells, SPELL_ICEBORN_FORTITUDE, TARGET_NONE, 15);
VerifyAndPushSpellCast(spells, SPELL_ANTI_MAGIC_SHELL, TARGET_NONE, 10);
bool hasFF = false, hasBP = false;
if (Unit* victim = me->GetVictim())
{
if (victim->HasUnitState(UNIT_STATE_CASTING))
VerifyAndPushSpellCast(spells, SPELL_MIND_FREEZE, TARGET_VICTIM, 25);
hasFF = !!victim->GetAuraApplicationOfRankedSpell(AURA_FROST_FEVER, me->GetGUID()), hasBP = !!victim->GetAuraApplicationOfRankedSpell(AURA_BLOOD_PLAGUE, me->GetGUID());
if (hasFF && hasBP)
VerifyAndPushSpellCast(spells, SPELL_PESTILENCE, TARGET_VICTIM, 3);
if (!hasFF)
VerifyAndPushSpellCast(spells, SPELL_ICY_TOUCH, TARGET_VICTIM, 4);
if (!hasBP)
VerifyAndPushSpellCast(spells, SPELL_PLAGUE_STRIKE, TARGET_VICTIM, 4);
}
switch (GetSpec())
{
case TALENT_SPEC_DEATHKNIGHT_BLOOD:
VerifyAndPushSpellCast(spells, SPELL_RUNE_TAP, TARGET_NONE, 2);
VerifyAndPushSpellCast(spells, SPELL_HYSTERIA, TARGET_SELF, 5);
if (Creature* creatureCharmer = GetCharmer())
if (!creatureCharmer->IsDungeonBoss() && !creatureCharmer->isWorldBoss())
VerifyAndPushSpellCast(spells, SPELL_HYSTERIA, creatureCharmer, 15);
VerifyAndPushSpellCast(spells, SPELL_HEART_STRIKE, TARGET_VICTIM, 2);
if (hasFF && hasBP)
VerifyAndPushSpellCast(spells, SPELL_DEATH_STRIKE, TARGET_VICTIM, 8);
VerifyAndPushSpellCast(spells, SPELL_DEATH_COIL_DK, TARGET_VICTIM, 1);
VerifyAndPushSpellCast(spells, SPELL_MARK_OF_BLOOD, TARGET_VICTIM, 20);
VerifyAndPushSpellCast(spells, SPELL_VAMPIRIC_BLOOD, TARGET_NONE, 10);
break;
case TALENT_SPEC_DEATHKNIGHT_FROST:
if (hasFF && hasBP)
VerifyAndPushSpellCast(spells, SPELL_OBLITERATE, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_HOWLING_BLAST, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_UNBREAKABLE_ARMOR, TARGET_NONE, 10);
VerifyAndPushSpellCast(spells, SPELL_DEATHCHILL, TARGET_NONE, 10);
VerifyAndPushSpellCast(spells, SPELL_FROST_STRIKE, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_BLOOD_STRIKE, TARGET_VICTIM, 1);
break;
case TALENT_SPEC_DEATHKNIGHT_UNHOLY:
if (hasFF && hasBP)
VerifyAndPushSpellCast(spells, SPELL_SCOURGE_STRIKE, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_DEATH_AND_DECAY, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_ANTI_MAGIC_ZONE, TARGET_NONE, 8);
VerifyAndPushSpellCast(spells, SPELL_SUMMON_GARGOYLE, TARGET_VICTIM, 7);
VerifyAndPushSpellCast(spells, SPELL_BLOOD_STRIKE, TARGET_VICTIM, 1);
VerifyAndPushSpellCast(spells, SPELL_DEATH_COIL_DK, TARGET_VICTIM, 3);
break;
}
break;
}
case CLASS_SHAMAN:
VerifyAndPushSpellCast(spells, SPELL_HEROISM, TARGET_NONE, 25);
VerifyAndPushSpellCast(spells, SPELL_BLOODLUST, TARGET_NONE, 25);
VerifyAndPushSpellCast(spells, SPELL_GROUNDING_TOTEM, TARGET_NONE, 2);
switch (GetSpec())
{
case TALENT_SPEC_SHAMAN_RESTORATION:
if (Unit* charmer = me->GetCharmer())
if (!charmer->GetAuraApplicationOfRankedSpell(SPELL_EARTH_SHIELD, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_EARTH_SHIELD, charmer, 2);
if (me->HasAura(SPELL_SHA_NATURE_SWIFT))
VerifyAndPushSpellCast(spells, SPELL_HEALING_WAVE, TARGET_CHARMER, 20);
else
VerifyAndPushSpellCast(spells, SPELL_LESSER_HEAL_WAVE, TARGET_CHARMER, 1);
VerifyAndPushSpellCast(spells, SPELL_TIDAL_FORCE, TARGET_NONE, 4);
VerifyAndPushSpellCast(spells, SPELL_SHA_NATURE_SWIFT, TARGET_NONE, 4);
VerifyAndPushSpellCast(spells, SPELL_MANA_TIDE_TOTEM, TARGET_NONE, 3);
break;
case TALENT_SPEC_SHAMAN_ELEMENTAL:
if (Unit* victim = me->GetVictim())
{
if (victim->GetAuraOfRankedSpell(SPELL_FLAME_SHOCK, GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_LAVA_BURST, TARGET_VICTIM, 5);
else
VerifyAndPushSpellCast(spells, SPELL_FLAME_SHOCK, TARGET_VICTIM, 3);
}
VerifyAndPushSpellCast(spells, SPELL_CHAIN_LIGHTNING, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_LIGHTNING_BOLT, TARGET_VICTIM, 1);
VerifyAndPushSpellCast(spells, SPELL_ELEMENTAL_MASTERY, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_THUNDERSTORM, TARGET_NONE, 3);
break;
case TALENT_SPEC_SHAMAN_ENHANCEMENT:
if (Aura const* maelstrom = me->GetAura(AURA_MAELSTROM_WEAPON))
if (maelstrom->GetStackAmount() == 5)
VerifyAndPushSpellCast(spells, SPELL_LIGHTNING_BOLT, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_STORMSTRIKE, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_EARTH_SHOCK, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_LAVA_LASH, TARGET_VICTIM, 1);
VerifyAndPushSpellCast(spells, SPELL_SHAMANISTIC_RAGE, TARGET_NONE, 10);
break;
}
break;
case CLASS_MAGE:
if (me->GetVictim() && me->GetVictim()->HasUnitState(UNIT_STATE_CASTING))
VerifyAndPushSpellCast(spells, SPELL_COUNTERSPELL, TARGET_VICTIM, 25);
VerifyAndPushSpellCast(spells, SPELL_DAMPEN_MAGIC, TARGET_CHARMER, 2);
VerifyAndPushSpellCast(spells, SPELL_EVOCATION, TARGET_NONE, 3);
VerifyAndPushSpellCast(spells, SPELL_MANA_SHIELD, TARGET_NONE, 1);
VerifyAndPushSpellCast(spells, SPELL_MIRROR_IMAGE, TARGET_NONE, 3);
VerifyAndPushSpellCast(spells, SPELL_SPELLSTEAL, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_ICE_BLOCK, TARGET_NONE, 1);
VerifyAndPushSpellCast(spells, SPELL_ICY_VEINS, TARGET_NONE, 3);
switch (GetSpec())
{
case TALENT_SPEC_MAGE_ARCANE:
if (Aura* abAura = me->GetAura(AURA_ARCANE_BLAST))
if (abAura->GetStackAmount() >= 3)
VerifyAndPushSpellCast(spells, SPELL_ARCANE_MISSILES, TARGET_VICTIM, 7);
VerifyAndPushSpellCast(spells, SPELL_ARCANE_BLAST, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_ARCANE_BARRAGE, TARGET_VICTIM, 1);
VerifyAndPushSpellCast(spells, SPELL_ARCANE_POWER, TARGET_NONE, 8);
VerifyAndPushSpellCast(spells, SPELL_PRESENCE_OF_MIND, TARGET_NONE, 7);
break;
case TALENT_SPEC_MAGE_FIRE:
if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_LIVING_BOMB))
VerifyAndPushSpellCast(spells, SPELL_LIVING_BOMB, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_COMBUSTION, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_FIREBALL, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_FIRE_BLAST, TARGET_VICTIM, 1);
VerifyAndPushSpellCast(spells, SPELL_DRAGONS_BREATH, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_BLAST_WAVE, TARGET_VICTIM, 1);
break;
case TALENT_SPEC_MAGE_FROST:
VerifyAndPushSpellCast(spells, SPELL_DEEP_FREEZE, TARGET_VICTIM, 10);
VerifyAndPushSpellCast(spells, SPELL_FROST_NOVA, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_FROSTBOLT, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_COLD_SNAP, TARGET_VICTIM, 5);
if (me->GetVictim() && me->GetVictim()->HasAuraState(AURA_STATE_FROZEN, nullptr, me))
VerifyAndPushSpellCast(spells, SPELL_ICE_LANCE, TARGET_VICTIM, 5);
break;
}
break;
case CLASS_WARLOCK:
VerifyAndPushSpellCast(spells, SPELL_DEATH_COIL_W, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_FEAR, TARGET_VICTIM, 2);
VerifyAndPushSpellCast(spells, SPELL_SEED_OF_CORRUPTION, TARGET_VICTIM, 4);
VerifyAndPushSpellCast(spells, SPELL_HOWL_OF_TERROR, TARGET_NONE, 2);
if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_CORRUPTION, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_CORRUPTION, TARGET_VICTIM, 10);
switch (GetSpec())
{
case TALENT_SPEC_WARLOCK_AFFLICTION:
if (Unit* victim = me->GetVictim())
{
VerifyAndPushSpellCast(spells, SPELL_SHADOW_BOLT, TARGET_VICTIM, 7);
if (!victim->GetAuraApplicationOfRankedSpell(SPELL_UNSTABLE_AFFLICTION, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_UNSTABLE_AFFLICTION, TARGET_VICTIM, 8);
if (!victim->GetAuraApplicationOfRankedSpell(SPELL_HAUNT, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_HAUNT, TARGET_VICTIM, 8);
if (!victim->GetAuraApplicationOfRankedSpell(SPELL_CURSE_OF_AGONY, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_CURSE_OF_AGONY, TARGET_VICTIM, 4);
if (victim->HealthBelowPct(25))
VerifyAndPushSpellCast(spells, SPELL_DRAIN_SOUL, TARGET_VICTIM, 100);
}
break;
case TALENT_SPEC_WARLOCK_DEMONOLOGY:
VerifyAndPushSpellCast(spells, SPELL_METAMORPHOSIS, TARGET_NONE, 15);
VerifyAndPushSpellCast(spells, SPELL_SHADOW_BOLT, TARGET_VICTIM, 7);
if (me->HasAura(AURA_DECIMATION))
VerifyAndPushSpellCast(spells, SPELL_SOUL_FIRE, TARGET_VICTIM, 100);
if (me->HasAura(SPELL_METAMORPHOSIS))
{
VerifyAndPushSpellCast(spells, SPELL_IMMOLATION_AURA, TARGET_NONE, 30);
if (!me->IsWithinMeleeRange(me->GetVictim()))
VerifyAndPushSpellCast(spells, SPELL_DEMON_CHARGE, TARGET_VICTIM, 20);
}
if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_IMMOLATE, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_IMMOLATE, TARGET_VICTIM, 5);
if (me->HasAura(AURA_MOLTEN_CORE))
VerifyAndPushSpellCast(spells, SPELL_INCINERATE, TARGET_VICTIM, 10);
break;
case TALENT_SPEC_WARLOCK_DESTRUCTION:
if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_IMMOLATE, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_IMMOLATE, TARGET_VICTIM, 8);
if (me->GetVictim() && me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_IMMOLATE, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_CONFLAGRATE, TARGET_VICTIM, 8);
VerifyAndPushSpellCast(spells, SPELL_SHADOWFURY, TARGET_VICTIM, 5);
VerifyAndPushSpellCast(spells, SPELL_CHAOS_BOLT, TARGET_VICTIM, 10);
VerifyAndPushSpellCast(spells, SPELL_SHADOWBURN, TARGET_VICTIM, 3);
VerifyAndPushSpellCast(spells, SPELL_INCINERATE, TARGET_VICTIM, 7);
break;
}
break;
case CLASS_MONK:
switch (GetSpec())
{
case TALENT_SPEC_MONK_BREWMASTER:
case TALENT_SPEC_MONK_BATTLEDANCER:
case TALENT_SPEC_MONK_MISTWEAVER:
break;
}
break;
case CLASS_DRUID:
VerifyAndPushSpellCast(spells, SPELL_INNERVATE, TARGET_CHARMER, 5);
VerifyAndPushSpellCast(spells, SPELL_BARKSKIN, TARGET_NONE, 5);
switch (GetSpec())
{
case TALENT_SPEC_DRUID_RESTORATION:
if (!me->HasAura(SPELL_TREE_OF_LIFE))
{
CancelAllShapeshifts();
VerifyAndPushSpellCast(spells, SPELL_TREE_OF_LIFE, TARGET_NONE, 100);
break;
}
VerifyAndPushSpellCast(spells, SPELL_TRANQUILITY, TARGET_NONE, 10);
VerifyAndPushSpellCast(spells, SPELL_NATURE_SWIFTNESS, TARGET_NONE, 7);
if (Creature* creatureCharmer = GetCharmer())
{
VerifyAndPushSpellCast(spells, SPELL_NOURISH, creatureCharmer, 5);
VerifyAndPushSpellCast(spells, SPELL_WILD_GROWTH, creatureCharmer, 5);
if (!creatureCharmer->GetAuraApplicationOfRankedSpell(SPELL_REJUVENATION, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_REJUVENATION, creatureCharmer, 8);
if (!creatureCharmer->GetAuraApplicationOfRankedSpell(SPELL_REGROWTH, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_REGROWTH, creatureCharmer, 8);
uint8 lifebloomStacks = 0;
if (Aura const* lifebloom = creatureCharmer->GetAura(SPELL_LIFEBLOOM, me->GetGUID()))
lifebloomStacks = lifebloom->GetStackAmount();
if (lifebloomStacks < 3)
VerifyAndPushSpellCast(spells, SPELL_LIFEBLOOM, creatureCharmer, 5);
if (creatureCharmer->GetAuraApplicationOfRankedSpell(SPELL_REJUVENATION) ||
creatureCharmer->GetAuraApplicationOfRankedSpell(SPELL_REGROWTH))
VerifyAndPushSpellCast(spells, SPELL_SWIFTMEND, creatureCharmer, 10);
if (me->HasAura(SPELL_NATURE_SWIFTNESS))
VerifyAndPushSpellCast(spells, SPELL_HEALING_TOUCH, creatureCharmer, 100);
}
break;
case TALENT_SPEC_DRUID_BALANCE:
{
if (!me->HasAura(SPELL_MOONKIN_FORM))
{
CancelAllShapeshifts();
VerifyAndPushSpellCast(spells, SPELL_MOONKIN_FORM, TARGET_NONE, 100);
break;
}
uint32 const mainAttackSpell = me->HasAura(AURA_ECLIPSE_LUNAR) ? SPELL_STARFIRE : SPELL_WRATH;
VerifyAndPushSpellCast(spells, SPELL_STARFALL, TARGET_NONE, 20);
VerifyAndPushSpellCast(spells, mainAttackSpell, TARGET_VICTIM, 10);
if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_INSECT_SWARM, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_INSECT_SWARM, TARGET_VICTIM, 7);
if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_MOONFIRE, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_MOONFIRE, TARGET_VICTIM, 5);
if (me->GetVictim() && me->GetVictim()->HasUnitState(UNIT_STATE_CASTING))
VerifyAndPushSpellCast(spells, SPELL_TYPHOON, TARGET_NONE, 15);
break;
}
case TALENT_SPEC_DRUID_CAT:
case TALENT_SPEC_DRUID_BEAR:
if (!me->HasAura(SPELL_CAT_FORM))
{
CancelAllShapeshifts();
VerifyAndPushSpellCast(spells, SPELL_CAT_FORM, TARGET_NONE, 100);
break;
}
VerifyAndPushSpellCast(spells, SPELL_BERSERK, TARGET_NONE, 20);
VerifyAndPushSpellCast(spells, SPELL_SURVIVAL_INSTINCTS, TARGET_NONE, 15);
VerifyAndPushSpellCast(spells, SPELL_TIGER_FURY, TARGET_NONE, 15);
VerifyAndPushSpellCast(spells, SPELL_DASH, TARGET_NONE, 5);
if (Unit* victim = me->GetVictim())
{
uint8 const cp = me->GetPower(POWER_COMBO_POINTS);
if (victim->HasUnitState(UNIT_STATE_CASTING) && cp >= 1)
VerifyAndPushSpellCast(spells, SPELL_MAIM, TARGET_VICTIM, 25);
if (!me->IsWithinMeleeRange(victim))
VerifyAndPushSpellCast(spells, SPELL_FERAL_CHARGE_CAT, TARGET_VICTIM, 25);
if (cp >= 4)
VerifyAndPushSpellCast(spells, SPELL_RIP, TARGET_VICTIM, 50);
if (cp <= 4)
{
VerifyAndPushSpellCast(spells, SPELL_MANGLE_CAT, TARGET_VICTIM, 10);
VerifyAndPushSpellCast(spells, SPELL_CLAW, TARGET_VICTIM, 5);
if (!victim->GetAuraApplicationOfRankedSpell(SPELL_RAKE, me->GetGUID()))
VerifyAndPushSpellCast(spells, SPELL_RAKE, TARGET_VICTIM, 8);
if (!me->HasAura(SPELL_SAVAGE_ROAR))
VerifyAndPushSpellCast(spells, SPELL_SAVAGE_ROAR, TARGET_NONE, 15);
}
}
break;
}
break;
case CLASS_DEMON_HUNTER:
switch (GetSpec())
{
case TALENT_SPEC_DEMON_HUNTER_HAVOC:
case TALENT_SPEC_DEMON_HUNTER_VENGEANCE:
break;
}
break;
}
*/
return SelectSpellCast(spells);
}
static const float CASTER_CHASE_DISTANCE = 28.0f;
void SimpleCharmedPlayerAI::UpdateAI(uint32 diff)
{
Creature* charmer = GetCharmer();
if (!charmer)
return;
// kill self if charm aura has infinite duration
if (charmer->IsInEvadeMode())
{
for (AuraEffect* aura : me->GetAuraEffectsByType(SPELL_AURA_MOD_CHARM))
{
if (aura->GetCasterGUID() == charmer->GetGUID() && aura->GetBase()->IsPermanent())
{
me->KillSelf();
return;
}
}
}
if (charmer->IsEngaged())
{
Unit* target = me->GetVictim();
if (!target || !CanAIAttack(target))
{
target = SelectAttackTarget();
if (!target || !CanAIAttack(target))
{
if (!_isFollowing)
{
_isFollowing = true;
me->AttackStop();
me->CastStop();
if (me->HasUnitState(UNIT_STATE_CHASE))
me->GetMotionMaster()->Remove(CHASE_MOTION_TYPE);
me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
}
return;
}
_isFollowing = false;
if (IsRangedAttacker())
{
_chaseCloser = !me->IsWithinLOSInMap(target);
if (_chaseCloser)
AttackStart(target);
else
AttackStartCaster(target, CASTER_CHASE_DISTANCE);
}
else
AttackStart(target);
_forceFacing = true;
}
if (me->IsStopped() && !me->HasUnitState(UNIT_STATE_CANNOT_TURN))
{
float targetAngle = me->GetAbsoluteAngle(target);
if (_forceFacing || fabs(me->GetOrientation() - targetAngle) > 0.4f)
{
me->SetFacingTo(targetAngle);
_forceFacing = false;
}
}
if (_castCheckTimer <= diff)
{
if (me->HasUnitState(UNIT_STATE_CASTING))
_castCheckTimer = 0;
else
{
if (IsRangedAttacker()) // chase to zero if the target isn't in line of sight
{
bool inLOS = me->IsWithinLOSInMap(target);
if (_chaseCloser != !inLOS)
{
_chaseCloser = !inLOS;
if (_chaseCloser)
AttackStart(target);
else
AttackStartCaster(target, CASTER_CHASE_DISTANCE);
}
}
if (TargetedSpell shouldCast = SelectAppropriateCastForSpec())
DoCastAtTarget(shouldCast);
_castCheckTimer = 500;
}
}
else
_castCheckTimer -= diff;
DoAutoAttackIfReady();
}
else if (!_isFollowing)
{
_isFollowing = true;
me->AttackStop();
me->CastStop();
if (me->HasUnitState(UNIT_STATE_CHASE))
me->GetMotionMaster()->Remove(CHASE_MOTION_TYPE);
me->GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
}
}
void SimpleCharmedPlayerAI::OnCharmed(bool isNew)
{
if (me->IsCharmed())
{
me->CastStop();
me->AttackStop();
if (me->GetMotionMaster()->Size() <= 1) // if there is no current movement (we dont want to erase/overwrite any existing stuff)
me->GetMotionMaster()->MovePoint(0, me->GetPosition(), false); // force re-sync of current position for all clients
}
else
{
me->CastStop();
me->AttackStop();
me->GetMotionMaster()->Clear(MOTION_PRIORITY_NORMAL);
}
PlayerAI::OnCharmed(isNew);
}