/*
* 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 .
*/
/*
* Scripts for spells with SPELLFAMILY_DRUID and SPELLFAMILY_GENERIC spells used by druid players.
* Ordered alphabetically using scriptname.
* Scriptnames of files in this file should be prefixed with "spell_dru_".
*/
#include "ScriptMgr.h"
#include "Containers.h"
#include "Creature.h"
#include "DynamicObject.h"
#include "ObjectAccessor.h"
#include "Player.h"
#include "Spell.h"
#include "SpellAuraEffects.h"
#include "SpellHistory.h"
#include "SpellMgr.h"
#include "SpellScript.h"
#include "TemporarySummon.h"
namespace Spells::Druid
{
enum DruidSpells
{
SPELL_DRUID_ASTRAL_ALIGNMENT = 90164,
SPELL_DRUID_BLOOD_IN_THE_WATER_SCRIPT = 80863,
SPELL_DRUID_BLOOM = 90159,
SPELL_DRUID_BRUTAL_IMPACT_R1 = 16940,
SPELL_DRUID_WRATH = 5176,
SPELL_DRUID_STARFIRE = 2912,
SPELL_DRUID_STARSURGE = 78674,
SPELL_DRUID_ECLIPSE_GENERAL_ENERGIZE = 89265,
SPELL_DRUID_STARSURGE_ENERGIZE = 86605,
SPELL_DRUID_LUNAR_ECLIPSE_MARKER = 67484, // Will make the yellow arrow on eclipse bar point to the blue side (lunar)
SPELL_DRUID_SOLAR_ECLIPSE_MARKER = 67483, // Will make the yellow arrow on eclipse bar point to the yellow side (solar)
SPELL_DRUID_SOLAR_ECLIPSE = 48517,
SPELL_DRUID_LUNAR_ECLIPSE = 48518,
SPELL_DRUID_SOLAR_ECLIPSE_SUNFIRE = 94338,
SPELL_DRUID_HARMONY = 100977,
SPELL_DRUID_EFFLORESCENCE_AOE = 81262,
SPELL_DRUID_EFFLORESCENCE_HEAL = 81269,
SPELL_DRUID_ENRAGE_MOD_DAMAGE = 51185,
SPELL_DRUID_ENRAGED_DEFENSE = 70725,
SPELL_DRUID_EUPHORIA = 81061,
SPELL_DRUID_EUPHORIA_MANA_ENERGIZE = 81070,
SPELL_DRUID_EUPHORIA_ENERGIZE = 81069,
SPELL_DRUID_FERAL_CHARGE_BEAR = 16979,
SPELL_DRUID_FERAL_CHARGE_CAT = 49376,
SPELL_DRUID_FERAL_SWIFTNESS = 17002,
SPELL_DRUID_FERAL_SWIFTNESS_CLEAR_ROAR = 97993,
SPELL_DRUID_FERAL_SWIFTNESS_CLEAR_CAT = 97985,
SPELL_DRUID_FUNGAL_GROWTH_R1 = 78788,
SPELL_DRUID_FUNGAL_GROWTH_R2 = 78789,
SPELL_DRUID_FUNGAL_GROWTH_SUMMON_R1 = 81291,
SPELL_DRUID_FUNGAL_GROWTH_SUMMON_R2 = 81283,
SPELL_DRUID_FRENZIED_REGENERATION_HEAL = 22845,
SPELL_DRUID_EMPOWERED_TOUCH_SCRIPT = 88433,
SPELL_DRUID_FURY_OF_STORMRAGE = 81093,
SPELL_DRUID_GLYPH_OF_INNERVATE = 54833,
SPELL_DRUID_GLYPH_OF_STARFIRE = 54846,
SPELL_DRUID_GLYPH_OF_TYPHOON = 62135,
SPELL_DRUID_GLYPH_OF_FEROCIOUS_BITE = 101024,
SPELL_DRUID_IDOL_OF_FERAL_SHADOWS = 34241,
SPELL_DRUID_IDOL_OF_WORSHIP = 60774,
SPELL_DRUID_INCREASED_MOONFIRE_DURATION = 38414,
SPELL_DRUID_INNERVATE_TRIGGERED = 54833,
SPELL_DRUID_ITEM_T8_BALANCE_RELIC = 64950,
SPELL_DRUID_ITEM_T10_FERAL_4P_BONUS = 70726,
SPELL_DRUID_ITEM_T11_BALANCE_4P_BONUS = 90163,
SPELL_DRUID_KING_OF_THE_JUNGLE = 48492,
SPELL_DRUID_LACERATE = 33745,
SPELL_DRUID_LEADER_OF_THE_PACK_HEAL = 34299,
SPELL_DRUID_LEADER_OF_THE_PACK_ENERGIZE = 68285,
SPELL_DRUID_LIFEBLOOM = 33763,
SPELL_DRUID_LIFEBLOOM_ENERGIZE = 64372,
SPELL_DRUID_LIFEBLOOM_FINAL_HEAL = 33778,
SPELL_DRUID_LIVING_SEED_HEAL = 48503,
SPELL_DRUID_LIVING_SEED_PROC = 48504,
SPELL_DRUID_LUNAR_SHOWER = 33603,
SPELL_DRUID_MOONFIRE = 8921,
SPELL_DRUID_NATURES_BOUNTY = 96206,
SPELL_DRUID_NATURES_GRACE = 16880,
SPELL_DRUID_PULVERIZE_TRIGGERED = 80951,
SPELL_DRUID_REVITALIZE_R1 = 48539,
SPELL_DRUID_RIP = 1079,
SPELL_DRUID_SURVIVAL_INSTINCTS = 50322,
SPELL_DRUID_SAVAGE_ROAR = 62071,
SPELL_DRUID_SKULL_BASH_CHARGE = 93983,
SPELL_DRUID_SKULL_BASH_INTERRUPT = 93985,
SPELL_DRUID_SKULL_BASH_COST_INCREASE_R1 = 82364,
SPELL_DRUID_SKULL_BASH_COST_INCREASE_R2 = 82365,
SPELL_DRUID_SOLAR_BEAM_SILENCE = 81261,
SPELL_DRUID_STAMPEDE_RAVAGE_MARKER = 109881,
SPELL_DRUID_STAMPEDE_TRIGGERED_BEAR = 81016,
SPELL_DRUID_STAMPEDE_TRIGGERED_CAT = 81021,
SPELL_DRUID_STRENGTH_OF_THE_PANTHER = 90166,
SPELL_DRUID_SUNFIRE = 93402,
SPELL_DRUID_REGROWTH_REFRESH = 93036,
SPELL_DRUID_REJUVENATION = 774,
SPELL_DRUID_REJUVENATION_DIRECT_HEAL = 64801,
SPELL_DRUID_TIGER_S_FURY_ENERGIZE = 51178,
SPELL_DRUID_TREE_OF_LIFE = 33891,
SPELL_DRUID_TREE_OF_LIFE_PASSIVE_1 = 5420,
SPELL_DRUID_TREE_OF_LIFE_PASSIVE_2 = 81097,
SPELL_DRUID_TREE_OF_LIFE_PASSIVE_3 = 81098,
SPELL_DRUID_T13_FERAL_2P_BONUS = 105725,
SPELL_DRUID_WILD_MUSHROOM = 88747,
SPELL_DRUID_WILD_MUSHROOM_DAMAGE = 78777,
SPELL_DRUID_WILD_MUSHROOM_SUICIDE = 92853,
SPELL_DRUID_WILD_MUSHROOM_VISUAL = 92701,
SPELL_DRUID_FIREBLOOM = 99017
};
enum DruidSpellIconIds
{
SPELL_ICON_ID_GLYPH_OF_REGROWTH = 197,
SPELL_ICON_ID_DREAMSTATE = 2255,
SPELL_ICON_ID_GLYPH_OF_INNERVATE = 62,
SPELL_ICON_ID_EUPHORIA = 4431,
SPELL_ICON_ID_SAVAGE_DEFENDER = 146,
SPELL_ICON_ID_SUNFIRE = 3262,
SPELL_ICON_ID_GLYPH_OF_FEROCIOUS_BITE = 1680,
SPELL_ICON_ID_GLYPH_OF_FRENZIED_REGENERATION = 50,
SPELL_ICON_ID_GIFT_OF_THE_EARTHMOTHER = 3186,
SPELL_ICON_ID_STAMPEDE = 3930
};
enum MiscSpells
{
SPELL_CATEGORY_MANGLE_BEAR = 971,
SPELL_RACIAL_SHADOWMELD = 58984,
SPELL_REPLENISHMENT = 57669
};
// 50334 - Berserk
class spell_dru_berserk : public AuraScript
{
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
// Remove cooldown on Mangle (bear)
GetTarget()->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
return spellInfo && spellInfo->GetCategory() == SPELL_CATEGORY_MANGLE_BEAR;
}, true);
}
void Register() override
{
AfterEffectApply.Register(&spell_dru_berserk::HandleEffectApply, EFFECT_1, SPELL_AURA_ADD_PCT_MODIFIER, AURA_EFFECT_HANDLE_REAL);
}
};
// 1850 - Dash
class spell_dru_dash : public SpellScript
{
bool Validate(SpellInfo const* /*spell*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_FERAL_SWIFTNESS,
SPELL_DRUID_FERAL_SWIFTNESS_CLEAR_CAT
});
}
void HandleFeralSwiftness(SpellEffIndex /*effIndex*/)
{
Unit* target = GetHitUnit();
if (Aura* swiftness = target->GetAuraOfRankedSpell(SPELL_DRUID_FERAL_SWIFTNESS, target->GetGUID()))
if (roll_chance_i(swiftness->GetSpellInfo()->Effects[EFFECT_1].BasePoints))
target->CastSpell(target, SPELL_DRUID_FERAL_SWIFTNESS_CLEAR_CAT, true);
}
void Register() override
{
OnEffectHitTarget.Register(&spell_dru_dash::HandleFeralSwiftness, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
}
};
class spell_dru_dash_AuraScript : public AuraScript
{
void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
// do not set speed if not in cat form
if (GetUnitOwner()->GetShapeshiftForm() != FORM_CAT)
amount = 0;
}
void Register() override
{
DoEffectCalcAmount.Register(&spell_dru_dash_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_INCREASE_SPEED);
}
};
// 48517 - Eclipse (Solar)
class spell_dru_eclipse : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_SOLAR_ECLIPSE,
SPELL_DRUID_SUNFIRE,
SPELL_DRUID_SOLAR_ECLIPSE_SUNFIRE
});
}
void ApplyEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
// Handle Sunfire talent
if (GetSpellInfo()->Id == SPELL_DRUID_SOLAR_ECLIPSE && target->GetDummyAuraEffect(SPELLFAMILY_DRUID, SPELL_ICON_ID_SUNFIRE, EFFECT_0))
if (!target->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_SUNFIRE))
target->CastSpell(target, SPELL_DRUID_SOLAR_ECLIPSE_SUNFIRE, CastSpellExtraArgs(true).AddSpellBP0(SPELL_DRUID_SUNFIRE));
}
void RemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
if (GetSpellInfo()->Id == SPELL_DRUID_SOLAR_ECLIPSE && target->HasAura(SPELL_DRUID_SOLAR_ECLIPSE_SUNFIRE))
target->RemoveAurasDueToSpell(SPELL_DRUID_SOLAR_ECLIPSE_SUNFIRE);
}
void Register() override
{
AfterEffectApply.Register(&spell_dru_eclipse::ApplyEffect, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove.Register(&spell_dru_eclipse::RemoveEffect, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, AURA_EFFECT_HANDLE_REAL);
}
};
// 79577 - Eclipse Mastery Passive Driver
class spell_dru_eclipse_mastery_driver_passive : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_LUNAR_ECLIPSE,
SPELL_DRUID_LUNAR_ECLIPSE_MARKER,
SPELL_DRUID_SOLAR_ECLIPSE,
SPELL_DRUID_SOLAR_ECLIPSE_MARKER,
SPELL_DRUID_EUPHORIA_ENERGIZE,
SPELL_DRUID_EUPHORIA_MANA_ENERGIZE,
SPELL_DRUID_STARSURGE_ENERGIZE,
SPELL_DRUID_ECLIPSE_GENERAL_ENERGIZE,
SPELL_DRUID_NATURES_GRACE,
SPELL_DRUID_ITEM_T11_BALANCE_4P_BONUS
});
}
bool CheckProc(ProcEventInfo& eventInfo)
{
Player* player = GetTarget()->ToPlayer();
if (!player || player->GetPrimaryTalentTree(player->GetActiveSpec()) != TALENT_TREE_DRUID_BALANCE)
return false;
return eventInfo.GetSpellInfo();
}
bool CheckSolarEclipseProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
{
_eclipseMarker = GetTarget()->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_DRUID, 0x0, 0x0, 0x100000, GetTarget()->GetGUID());
if (_eclipseMarker && _eclipseMarker->GetSpellInfo()->Id != SPELL_DRUID_SOLAR_ECLIPSE_MARKER)
return false;
_energyAmount = GetEnergyGainFromSpellInfo(eventInfo.GetSpellInfo());
return _energyAmount > 0;
}
bool CheckLunarEclipseProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
{
_eclipseMarker = GetTarget()->GetAuraEffect(SPELL_AURA_DUMMY, SPELLFAMILY_DRUID, 0x0, 0x0, 0x100000, GetTarget()->GetGUID());
if (_eclipseMarker && _eclipseMarker->GetSpellInfo()->Id != SPELL_DRUID_LUNAR_ECLIPSE_MARKER)
return false;
_energyAmount = GetEnergyGainFromSpellInfo(eventInfo.GetSpellInfo());
return _energyAmount < 0;
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
Unit* target = GetTarget();
// Apply eclipse Marker if not present
if (!_eclipseMarker)
target->CastSpell(target, aurEff->GetEffIndex() == EFFECT_0 ? SPELL_DRUID_SOLAR_ECLIPSE_MARKER : SPELL_DRUID_LUNAR_ECLIPSE_MARKER, false);
// Cast Energy Gain
uint32 energizeSpell = (eventInfo.GetSpellInfo()->SpellFamilyFlags[2] & 0x2000000) != 0 ? SPELL_DRUID_STARSURGE_ENERGIZE : SPELL_DRUID_ECLIPSE_GENERAL_ENERGIZE;
target->CastSpell(target, energizeSpell, CastSpellExtraArgs().AddSpellBP0(_energyAmount));
// Cast Euphoria Bonus
if (_euphoriaEnergyAmount)
target->CastSpell(target, SPELL_DRUID_EUPHORIA_ENERGIZE, CastSpellExtraArgs().AddSpellBP0(_euphoriaEnergyAmount));
}
void HandleEclipseProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
{
Unit* target = GetTarget();
uint32 newMarkerSpellId = 0;
AuraEffect* eclipse = target->GetAuraEffect(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, SPELLFAMILY_DRUID, 0x0, 0x0, 0x4000);
if (eclipse)
{
if (_eclipseMarker)
{
if (eclipse->GetId() == SPELL_DRUID_LUNAR_ECLIPSE && _eclipseMarker->GetId() == SPELL_DRUID_LUNAR_ECLIPSE_MARKER)
newMarkerSpellId = SPELL_DRUID_SOLAR_ECLIPSE_MARKER;
else if (eclipse->GetId() == SPELL_DRUID_SOLAR_ECLIPSE && _eclipseMarker->GetId() == SPELL_DRUID_SOLAR_ECLIPSE_MARKER)
newMarkerSpellId = SPELL_DRUID_LUNAR_ECLIPSE_MARKER;
}
if ((eclipse->GetId() == SPELL_DRUID_LUNAR_ECLIPSE && target->GetPower(POWER_ECLIPSE) >= 0) ||
((eclipse->GetId() == SPELL_DRUID_SOLAR_ECLIPSE && target->GetPower(POWER_ECLIPSE) <= 0)))
if (Aura* aura = eclipse->GetBase())
aura->Remove();
}
if (!newMarkerSpellId)
return;
if (_eclipseMarker)
if (Aura* aura = _eclipseMarker->GetBase())
aura->Remove();
target->CastSpell(target, newMarkerSpellId, false);
// Reset Nature's Grace proc cooldown
if (Aura* aura = target->GetAuraOfRankedSpell(SPELL_DRUID_NATURES_GRACE))
aura->ResetProcCooldown();
// Euphoria Mana Bonus
if (AuraEffect const* euphoria = target->GetDummyAuraEffect(SPELLFAMILY_DRUID, SPELL_ICON_ID_EUPHORIA, EFFECT_2))
target->CastSpell(target, SPELL_DRUID_EUPHORIA_MANA_ENERGIZE, CastSpellExtraArgs().AddSpellBP0(euphoria->GetAmount()));
// T11 Bonus
if (target->GetAuraEffect(SPELL_DRUID_ITEM_T11_BALANCE_4P_BONUS, EFFECT_0))
target->CastSpell(target, SPELL_DRUID_ASTRAL_ALIGNMENT, CastSpellExtraArgs().AddSpellMod(SPELLVALUE_AURA_STACK, 3));
}
void Register() override
{
DoCheckProc.Register(&spell_dru_eclipse_mastery_driver_passive::CheckProc);
DoCheckEffectProc.Register(&spell_dru_eclipse_mastery_driver_passive::CheckSolarEclipseProc, EFFECT_0, SPELL_AURA_PROC_ON_POWER_AMOUNT);
DoCheckEffectProc.Register(&spell_dru_eclipse_mastery_driver_passive::CheckLunarEclipseProc, EFFECT_1, SPELL_AURA_PROC_ON_POWER_AMOUNT);
OnEffectProc.Register(&spell_dru_eclipse_mastery_driver_passive::HandleProc, EFFECT_0, SPELL_AURA_PROC_ON_POWER_AMOUNT);
OnEffectProc.Register(&spell_dru_eclipse_mastery_driver_passive::HandleProc, EFFECT_1, SPELL_AURA_PROC_ON_POWER_AMOUNT);
AfterEffectProc.Register(&spell_dru_eclipse_mastery_driver_passive::HandleEclipseProc, EFFECT_0, SPELL_AURA_PROC_ON_POWER_AMOUNT);
AfterEffectProc.Register(&spell_dru_eclipse_mastery_driver_passive::HandleEclipseProc, EFFECT_1, SPELL_AURA_PROC_ON_POWER_AMOUNT);
}
private:
int32 GetEnergyGainFromSpellInfo(SpellInfo const* spell)
{
Unit* target = GetTarget();
int32 energyAmount = 0;
int32 bonusEnergyAmount = 0;
// Wrath and Starfire energy amount
if ((spell->SpellFamilyFlags[0] & 0x1) != 0)
energyAmount = -spell->Effects[EFFECT_1].CalcValue(target);
else if ((spell->SpellFamilyFlags[0] & 0x4) != 0)
energyAmount = spell->Effects[EFFECT_1].CalcValue(target);
// Euphoria Talent Bonus
if (energyAmount != 0 && !target->GetAuraEffect(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE, SPELLFAMILY_DRUID, 0x0, 0x0, 0x4000))
if (AuraEffect const* euphoria = target->GetDummyAuraEffect(SPELLFAMILY_DRUID, SPELL_ICON_ID_EUPHORIA, EFFECT_0))
if (roll_chance_i(euphoria->GetAmount()))
bonusEnergyAmount = energyAmount;
// Starsurge energy amount
if ((spell->SpellFamilyFlags[2] & 0x2000000) != 0)
{
int32 bp = spell->Effects[EFFECT_1].CalcValue(target);
if (_eclipseMarker)
energyAmount += _eclipseMarker->GetSpellInfo()->Id == SPELL_DRUID_LUNAR_ECLIPSE_MARKER ? -bp : bp;
else
energyAmount -= bp;
}
// Lunar Shower Bonus for Starfire and Sunfire
if ((spell->SpellFamilyFlags[0] & 0x2) != 0)
{
if (Aura const* lunarShower = target->GetAuraOfRankedSpell(SPELL_DRUID_LUNAR_SHOWER, target->GetGUID()))
{
if (target->HasAura(lunarShower->GetSpellInfo()->Effects[EFFECT_0].TriggerSpell))
{
int32 bp = sSpellMgr->AssertSpellInfo(SPELL_DRUID_LUNAR_SHOWER)->Effects[EFFECT_2].CalcValue(target);
if (_eclipseMarker)
energyAmount += _eclipseMarker->GetSpellInfo()->Id == SPELL_DRUID_LUNAR_ECLIPSE_MARKER ? -bp : bp;
else
energyAmount -= bp;
}
}
}
_euphoriaEnergyAmount = bonusEnergyAmount;
return energyAmount;
}
AuraEffect* _eclipseMarker = nullptr;
int32 _energyAmount = 0;
int32 _euphoriaEnergyAmount = 0;
};
// 5229 - Enrage
class spell_dru_enrage : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_KING_OF_THE_JUNGLE,
SPELL_DRUID_ENRAGE_MOD_DAMAGE,
SPELL_DRUID_ENRAGED_DEFENSE,
SPELL_DRUID_ITEM_T10_FERAL_4P_BONUS
});
}
void RecalculateBaseArmor()
{
// Recalculate modifies the list while we're iterating through it, so let's copy it instead
Unit::AuraEffectList const& auras = GetTarget()->GetAuraEffectsByType(SPELL_AURA_MOD_BASE_RESISTANCE_PCT);
std::vector aurEffs(auras.begin(), auras.end());
for (AuraEffect* aurEff : aurEffs)
{
SpellInfo const* spellInfo = aurEff->GetSpellInfo();
// Dire- / Bear Form (Passive)
if (spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && spellInfo->SpellFamilyFlags.HasFlag(0x0, 0x0, 0x2))
aurEff->RecalculateAmount();
}
}
void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
if (AuraEffect const* aurEff = target->GetAuraEffectOfRankedSpell(SPELL_DRUID_KING_OF_THE_JUNGLE, EFFECT_0))
target->CastSpell(target, SPELL_DRUID_ENRAGE_MOD_DAMAGE, CastSpellExtraArgs(aurEff).AddSpellBP0(aurEff->GetAmount()));
// Item - Druid T10 Feral 4P Bonus
if (target->HasAura(SPELL_DRUID_ITEM_T10_FERAL_4P_BONUS))
target->CastSpell(target, SPELL_DRUID_ENRAGED_DEFENSE, true);
RecalculateBaseArmor();
}
void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->RemoveAurasDueToSpell(SPELL_DRUID_ENRAGE_MOD_DAMAGE);
GetTarget()->RemoveAurasDueToSpell(SPELL_DRUID_ENRAGED_DEFENSE);
RecalculateBaseArmor();
}
void Register() override
{
AfterEffectApply.Register(&spell_dru_enrage::HandleApply, EFFECT_0, SPELL_AURA_PERIODIC_ENERGIZE, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove.Register(&spell_dru_enrage::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_ENERGIZE, AURA_EFFECT_HANDLE_REAL);
}
};
// 54846 - Glyph of Starfire
class spell_dru_glyph_of_starfire : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_INCREASED_MOONFIRE_DURATION });
}
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (Unit* unitTarget = GetHitUnit())
{
if (AuraEffect const* aurEff = unitTarget->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x2, 0, 0, caster->GetGUID()))
{
Aura* aura = aurEff->GetBase();
uint32 countMin = aura->GetMaxDuration();
uint32 countMax = aura->GetSpellInfo()->GetMaxDuration() + 9000;
if (caster->HasAura(SPELL_DRUID_INCREASED_MOONFIRE_DURATION))
countMax += 3000;
if (countMin < countMax)
{
aura->SetDuration(uint32(aura->GetDuration() + 3000));
aura->SetMaxDuration(countMin + 3000);
}
}
}
}
void Register() override
{
OnEffectHitTarget.Register(&spell_dru_glyph_of_starfire::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 54845 - Glyph of Starfire
class spell_dru_glyph_of_starfire_proc : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_GLYPH_OF_STARFIRE });
}
bool CheckProc(ProcEventInfo& eventInfo)
{
if (eventInfo.GetSpellInfo()->SpellFamilyFlags[0] & 0x00000002)
{
_lastMoonFireTargetGuid = eventInfo.GetProcTarget()->GetGUID();
return false;
}
else if (_lastMoonFireTargetGuid != eventInfo.GetProcTarget()->GetGUID())
return false;
return true;
}
void HandleEffectProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_DRUID_GLYPH_OF_STARFIRE, aurEff);
}
void Register() override
{
DoCheckProc.Register(&spell_dru_glyph_of_starfire_proc::CheckProc);
OnEffectProc.Register(&spell_dru_glyph_of_starfire_proc::HandleEffectProc, EFFECT_0, SPELL_AURA_DUMMY);
}
private:
ObjectGuid _lastMoonFireTargetGuid;
};
// 34246 - Idol of the Emerald Queen
// 60779 - Idol of Lush Moss
class spell_dru_idol_lifebloom : public AuraScript
{
void HandleEffectCalcSpellMod(AuraEffect const* aurEff, SpellModifier*& spellModifier)
{
if (!spellModifier)
{
SpellModifierByClassMask* spellMod = new SpellModifierByClassMask(GetAura());
spellMod->op = SpellModOp::PeriodicHealingAndDamage;
spellMod->type = SPELLMOD_FLAT;
spellMod->spellId = GetId();
spellMod->mask = GetSpellInfo()->Effects[aurEff->GetEffIndex()].SpellClassMask;
}
static_cast(spellModifier)->value = aurEff->GetAmount() / 7;
}
void Register() override
{
DoEffectCalcSpellMod.Register(&spell_dru_idol_lifebloom::HandleEffectCalcSpellMod, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 29166 - Innervate
class spell_dru_innervate : public AuraScript
{
void CalculateAmount(AuraEffect const* aurEff, int32& amount, bool& /*canBeRecalculated*/)
{
Unit* target = GetUnitOwner();
if (!target)
return;
uint32 mana = target->GetMaxPower(POWER_MANA);
if (!mana)
return;
// Regenerate 5% of maximum mana
uint8 percentage = 5;
// If casted on self regenerate 15% additional mana
if (Unit* caster = GetCaster())
{
if (target == caster)
{
percentage += 15;
// Dreamstate increases the amount by additional 15%
if (AuraEffect* dreamState = caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, SPELL_ICON_ID_DREAMSTATE, EFFECT_0))
percentage += dreamState->GetAmount();
}
else
{
// Glyph of Innervate
if (caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, SPELL_ICON_ID_GLYPH_OF_INNERVATE, EFFECT_0))
caster->CastSpell(caster, SPELL_DRUID_INNERVATE_TRIGGERED, true);
}
}
amount = CalculatePct(mana, percentage) / aurEff->GetTotalTicks();
}
void Register() override
{
DoEffectCalcAmount.Register(&spell_dru_innervate::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_ENERGIZE);
}
};
// 5570 - Insect Swarm
class spell_dru_insect_swarm : public AuraScript
{
void CalculateAmount(AuraEffect const* aurEff, int32 & amount, bool & /*canBeRecalculated*/)
{
if (Unit* caster = GetCaster())
if (AuraEffect const* relicAurEff = caster->GetAuraEffect(SPELL_DRUID_ITEM_T8_BALANCE_RELIC, EFFECT_0))
amount += relicAurEff->GetAmount() / aurEff->GetTotalTicks();
}
void Register() override
{
DoEffectCalcAmount.Register(&spell_dru_insect_swarm::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
}
};
// 33763 - Lifebloom
// 94447 - Lifebloom
class spell_dru_lifebloom : public AuraScript
{
bool Validate(SpellInfo const* /*spell*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_REVITALIZE_R1,
SPELL_DRUID_LIFEBLOOM_FINAL_HEAL,
SPELL_DRUID_LIFEBLOOM_ENERGIZE,
SPELL_REPLENISHMENT
});
}
void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
// Refreshing Lifebloom while having Revitalize active causes Replenishment to be cast
if (Unit* caster = GetCaster())
if (caster->GetAuraOfRankedSpell(SPELL_DRUID_REVITALIZE_R1, caster->GetGUID()))
caster->CastSpell(nullptr, SPELL_REPLENISHMENT, true);
}
void AfterRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
// When Lifelboom expires or is dispelled, it instantly heals the target
if (!GetTargetApplication()->GetRemoveMode().HasFlag(AuraRemoveFlags::Expired | AuraRemoveFlags::ByEnemySpell))
return;
GetTarget()->CastSpell(GetTarget(), SPELL_DRUID_LIFEBLOOM_FINAL_HEAL, CastSpellExtraArgs(aurEff).SetOriginalCaster(GetCasterGUID()).AddSpellBP0(aurEff->GetAmount()));
}
void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
if (Unit* caster = GetCaster())
amount = caster->SpellHealingBonusDone(GetUnitOwner(), GetSpellInfo(), amount, HEAL, EFFECT_1) / GetStackAmount();
}
void Register() override
{
AfterEffectApply.Register(&spell_dru_lifebloom::AfterApply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
AfterEffectRemove.Register(&spell_dru_lifebloom::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
DoEffectCalcAmount.Register(&spell_dru_lifebloom::CalculateAmount, EFFECT_1, SPELL_AURA_DUMMY);
}
};
// -48496 - Living Seed
class spell_dru_living_seed : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_LIVING_SEED_PROC });
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
int32 amount = CalculatePct(eventInfo.GetHealInfo()->GetEffectiveHeal(), aurEff->GetAmount());
if (amount)
GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_DRUID_LIVING_SEED_PROC, CastSpellExtraArgs(aurEff).AddSpellBP0(amount));
}
void Register() override
{
OnEffectProc.Register(&spell_dru_living_seed::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 48504 - Living Seed (Proc)
class spell_dru_living_seed_proc : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_LIVING_SEED_HEAL });
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
{
PreventDefaultAction();
GetTarget()->CastSpell(GetTarget(), SPELL_DRUID_LIVING_SEED_HEAL, CastSpellExtraArgs(aurEff).AddSpellBP0(aurEff->GetAmount()));
}
void Register() override
{
OnEffectProc.Register(&spell_dru_living_seed_proc::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 1079 - Rip
// Updated 4.3.4
class spell_dru_rip : public AuraScript
{
bool Load() override
{
Unit* caster = GetCaster();
return caster && caster->GetTypeId() == TYPEID_PLAYER;
}
void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated)
{
canBeRecalculated = false;
if (Unit* caster = GetCaster())
{
// Formular: bp + 0.0207 * ap
uint8 cp = caster->ToPlayer()->GetComboPoints();
float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.0207f;
float bonus = ap * cp;
// Idol of Feral Shadows. Can't be handled as SpellMod due its dependency from CPs
if (AuraEffect const* auraEffIdolOfFeralShadows = caster->GetAuraEffect(SPELL_DRUID_IDOL_OF_FERAL_SHADOWS, EFFECT_0))
amount += cp * auraEffIdolOfFeralShadows->GetAmount();
// Idol of Worship. Can't be handled as SpellMod due its dependency from CPs
else if (AuraEffect const* auraEffIdolOfWorship = caster->GetAuraEffect(SPELL_DRUID_IDOL_OF_WORSHIP, EFFECT_0))
amount += cp * auraEffIdolOfWorship->GetAmount();
amount += int32(bonus);
}
}
void Register() override
{
DoEffectCalcAmount.Register(&spell_dru_rip::CalculateAmount, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
}
};
// 62606 - Savage Defense
class spell_dru_savage_defense : public AuraScript
{
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
{
PreventDefaultAction();
Unit* target = GetTarget();
uint32 absorbPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(target);
if (AuraEffect* masteryAurEff = target->GetDummyAuraEffect(SPELLFAMILY_HUNTER, SPELL_ICON_ID_SAVAGE_DEFENDER, EFFECT_0)) // no idea why hunter...
absorbPct += masteryAurEff->GetAmount();
int32 amount = uint32(CalculatePct(GetTarget()->GetTotalAttackPowerValue(BASE_ATTACK), absorbPct));
target->CastSpell(target, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, CastSpellExtraArgs(true).AddSpellBP0(amount));
}
void Register() override
{
OnEffectProc.Register(&spell_dru_savage_defense::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
// 52610 - Savage Roar
class spell_dru_savage_roar : public SpellScript
{
SpellCastResult CheckCast()
{
Unit* caster = GetCaster();
if (caster->GetShapeshiftForm() != FORM_CAT)
return SPELL_FAILED_ONLY_SHAPESHIFT;
return SPELL_CAST_OK;
}
void Register() override
{
OnCheckCast.Register(&spell_dru_savage_roar::CheckCast);
}
};
class spell_dru_savage_roar_AuraScript : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_SAVAGE_ROAR });
}
void AfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
target->CastSpell(target, SPELL_DRUID_SAVAGE_ROAR, { aurEff, GetCasterGUID() });
}
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->RemoveAurasDueToSpell(SPELL_DRUID_SAVAGE_ROAR);
}
void Register() override
{
AfterEffectApply.Register(&spell_dru_savage_roar_AuraScript::AfterApply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove.Register(&spell_dru_savage_roar_AuraScript::AfterRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 50286 - Starfall (Dummy)
class spell_dru_starfall_dummy : public SpellScript
{
void FilterTargets(std::list& targets)
{
Trinity::Containers::RandomResize(targets, 2);
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
// Shapeshifting into an animal form or mounting cancels the effect
if (caster->GetCreatureType() == CREATURE_TYPE_BEAST || caster->IsMounted())
{
if (SpellInfo const* spellInfo = GetTriggeringSpell())
caster->RemoveAurasDueToSpell(spellInfo->Id);
return;
}
// Any effect which causes you to lose control of your character will supress the starfall effect.
if (caster->HasUnitState(UNIT_STATE_CONTROLLED))
return;
caster->CastSpell(GetHitUnit(), uint32(GetEffectValue()), true);
}
void Register() override
{
OnObjectAreaTargetSelect.Register(&spell_dru_starfall_dummy::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
OnEffectHitTarget.Register(&spell_dru_starfall_dummy::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 61336 - Survival Instincts
class spell_dru_survival_instincts : public SpellScript
{
SpellCastResult CheckCast()
{
Unit* caster = GetCaster();
if (!caster->IsInFeralForm())
return SPELL_FAILED_ONLY_SHAPESHIFT;
return SPELL_CAST_OK;
}
void Register() override
{
OnCheckCast.Register(&spell_dru_survival_instincts::CheckCast);
}
};
class spell_dru_survival_instincts_AuraScript : public AuraScript
{
bool Validate(SpellInfo const* /*spell*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_SURVIVAL_INSTINCTS });
}
void AfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
GetTarget()->CastSpell(GetTarget(), SPELL_DRUID_SURVIVAL_INSTINCTS, aurEff);
}
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->RemoveAurasDueToSpell(SPELL_DRUID_SURVIVAL_INSTINCTS);
}
void Register() override
{
AfterEffectApply.Register(&spell_dru_survival_instincts_AuraScript::AfterApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK);
AfterEffectRemove.Register(&spell_dru_survival_instincts_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK);
}
};
// 40121 - Swift Flight Form (Passive)
class spell_dru_swift_flight_passive : public AuraScript
{
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void CalculateAmount(AuraEffect const* /*aurEff*/, int32 & amount, bool & /*canBeRecalculated*/)
{
if (Player* caster = GetCaster()->ToPlayer())
if (caster->GetSkillValue(SKILL_RIDING) >= 375)
amount = 310;
}
void Register() override
{
DoEffectCalcAmount.Register(&spell_dru_swift_flight_passive::CalculateAmount, EFFECT_1, SPELL_AURA_MOD_INCREASE_VEHICLE_FLIGHT_SPEED);
}
};
// 33943 - Flight Form (Shapeshift)
class spell_dru_flight_form : public SpellScript
{
SpellCastResult CheckCast()
{
Unit* caster = GetCaster();
if (caster->IsInDisallowedMountForm())
return SPELL_FAILED_NOT_SHAPESHIFT;
return SPELL_CAST_OK;
}
void Register() override
{
OnCheckCast.Register(&spell_dru_flight_form::CheckCast);
}
};
// 40120 - Swift Flight Form (Shapeshift)
class spell_dru_swift_flight_form : public AuraScript
{
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& /*canBeRecalculated*/)
{
if (Player* caster = GetCaster()->ToPlayer())
{
// the following values are sniffed but it is not clear how these values are actually being calculated since shapeshift auras usually don't do that.
if (caster->GetSkillValue(SKILL_RIDING) >= 375)
amount = 240;
else
amount = 239;
}
}
void Register() override
{
DoEffectCalcAmount.Register(&spell_dru_swift_flight_form::CalculateAmount, EFFECT_0, SPELL_AURA_MOD_SHAPESHIFT);
}
};
// 5217 - Tiger's Fury
class spell_dru_tiger_s_fury : public SpellScript
{
void OnHit()
{
if (AuraEffect const* aurEff = GetHitUnit()->GetAuraEffectOfRankedSpell(SPELL_DRUID_KING_OF_THE_JUNGLE, EFFECT_1))
GetHitUnit()->CastSpell(GetHitUnit(), SPELL_DRUID_TIGER_S_FURY_ENERGIZE, CastSpellExtraArgs(true).AddSpellBP0(aurEff->GetAmount()));
}
void Register() override
{
AfterHit.Register(&spell_dru_tiger_s_fury::OnHit);
}
};
// 61391 - Typhoon
class spell_dru_typhoon : public SpellScript
{
void HandleKnockBack(SpellEffIndex effIndex)
{
// Glyph of Typhoon
if (GetCaster()->HasAura(SPELL_DRUID_GLYPH_OF_TYPHOON))
PreventHitDefaultEffect(effIndex);
}
void Register() override
{
OnEffectHitTarget.Register(&spell_dru_typhoon::HandleKnockBack, EFFECT_0, SPELL_EFFECT_KNOCK_BACK);
}
};
// 70691 - Item T10 Restoration 4P Bonus
class spell_dru_t10_restoration_4p_bonus : public SpellScript
{
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void FilterTargets(std::list& targets)
{
if (!GetCaster()->ToPlayer()->GetGroup())
{
targets.clear();
targets.push_back(GetCaster());
}
else
{
targets.remove(GetExplTargetUnit());
std::list tempTargets;
for (std::list::const_iterator itr = targets.begin(); itr != targets.end(); ++itr)
if ((*itr)->GetTypeId() == TYPEID_PLAYER && GetCaster()->IsInRaidWith((*itr)->ToUnit()))
tempTargets.push_back((*itr)->ToUnit());
if (tempTargets.empty())
{
targets.clear();
FinishCast(SPELL_FAILED_DONT_REPORT);
return;
}
Unit* target = Trinity::Containers::SelectRandomContainerElement(tempTargets);
targets.clear();
targets.push_back(target);
}
}
void Register() override
{
OnObjectAreaTargetSelect.Register(&spell_dru_t10_restoration_4p_bonus::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
}
};
class RaidCheck
{
public:
explicit RaidCheck(Unit const* caster) : _caster(caster) { }
bool operator()(WorldObject* obj) const
{
if (Unit* target = obj->ToUnit())
return !_caster->IsInRaidWith(target);
return true;
}
private:
Unit const* _caster;
};
// 48438 - Wild Growth
class spell_dru_wild_growth : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_TREE_OF_LIFE });
}
void FilterTargets(std::list& targets)
{
targets.remove_if(RaidCheck(GetCaster()));
uint32 maxTargets = static_cast(GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster()));
// Tree of Life bonus
if (GetCaster()->HasAura(SPELL_DRUID_TREE_OF_LIFE))
maxTargets += 2;
if (targets.size() > maxTargets)
{
targets.sort(Trinity::HealthPctOrderPred());
targets.resize(maxTargets);
}
_targets = targets;
}
void SetTargets(std::list& targets)
{
targets = _targets;
}
void Register() override
{
OnObjectAreaTargetSelect.Register(&spell_dru_wild_growth::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
OnObjectAreaTargetSelect.Register(&spell_dru_wild_growth::SetTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ALLY);
}
private:
std::list _targets;
};
// 78675 - Solar Beam
class spell_dru_solar_beam : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_SOLAR_BEAM_SILENCE });
}
void HandleEffectPeriodic(AuraEffect const* aurEff)
{
if (DynamicObject* dyn = GetTarget()->GetDynObject(aurEff->GetId()))
GetTarget()->CastSpell({ dyn->GetPositionX(), dyn->GetPositionY(), dyn->GetPositionZ() }, SPELL_DRUID_SOLAR_BEAM_SILENCE, true);
}
void Register() override
{
OnEffectPeriodic.Register(&spell_dru_solar_beam::HandleEffectPeriodic, EFFECT_2, SPELL_AURA_PERIODIC_DUMMY);
}
};
// -34151 - Efflorescence (Proc Aura)
class spell_dru_effloresence : public AuraScript
{
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
if (HealInfo* heal = eventInfo.GetHealInfo())
{
int32 healAmount = CalculatePct(heal->GetEffectiveHeal(), GetSpellInfo()->Effects[EFFECT_0].BasePoints);
if (healAmount)
GetTarget()->CastSpell(heal->GetTarget(), GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, CastSpellExtraArgs(aurEff).AddSpellMod(SPELLVALUE_BASE_POINT1, healAmount));
}
}
void Register() override
{
OnEffectProc.Register(&spell_dru_effloresence::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
}
};
// 81262 - Efflorescence (Area Effect)
class spell_dru_effloresence_aoe : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_EFFLORESCENCE_HEAL });
}
void HandleEffectPeriodic(AuraEffect const* aurEff)
{
if (Unit* caster = GetCaster())
if (DynamicObject* dyn = caster->GetDynObject(aurEff->GetId()))
caster->CastSpell({ dyn->GetPositionX(), dyn->GetPositionY(), dyn->GetPositionZ() }, SPELL_DRUID_EFFLORESCENCE_HEAL, { aurEff, caster->GetGUID() });
}
void Register() override
{
OnEffectPeriodic.Register(&spell_dru_effloresence_aoe::HandleEffectPeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY);
}
};
// 81269 - Efflorescence (Heal)
class spell_dru_effloresence_heal : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_EFFLORESCENCE_AOE });
}
void FilterTargets(std::list& targets)
{
if (targets.size() > 3)
{
targets.sort(Trinity::HealthPctOrderPred(true));
targets.resize(3);
}
}
void HandleHeal(SpellEffIndex /*effIndex*/)
{
if (Unit* caster = GetCaster())
if (Aura const* aura = caster->GetAura(SPELL_DRUID_EFFLORESCENCE_AOE, caster->GetGUID()))
if (AuraEffect* aurEff = aura->GetEffect(EFFECT_1))
if (int32 heal = aurEff->GetAmount())
SetHitHeal(heal);
}
void Register() override
{
OnObjectAreaTargetSelect.Register(&spell_dru_effloresence_heal::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
OnEffectHitTarget.Register(&spell_dru_effloresence_heal::HandleHeal, EFFECT_0, SPELL_EFFECT_HEAL);
}
};
// 774 - Rejuvenation
class spell_dru_rejuvenation : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_REJUVENATION_DIRECT_HEAL });
}
void HandleGiftOfTheEarthmother(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (Unit* caster = GetCaster())
{
if (AuraEffect const* giftEffect = caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, SPELL_ICON_ID_GIFT_OF_THE_EARTHMOTHER, EFFECT_1))
{
int32 bp = CalculatePct(aurEff->GetAmount() * aurEff->GetTotalTicks(), giftEffect->GetAmount());
caster->CastSpell(GetTarget(), SPELL_DRUID_REJUVENATION_DIRECT_HEAL, CastSpellExtraArgs(true).AddSpellBP0(bp));
}
}
}
void Register() override
{
AfterEffectApply.Register(&spell_dru_rejuvenation::HandleGiftOfTheEarthmother, EFFECT_0, SPELL_AURA_PERIODIC_HEAL, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
}
};
// 33891 - Tree of Life
class spell_dru_tree_of_life : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_TREE_OF_LIFE_PASSIVE_1,
SPELL_DRUID_TREE_OF_LIFE_PASSIVE_2,
SPELL_DRUID_TREE_OF_LIFE_PASSIVE_3
});
}
void AfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
if (Unit* target = GetTarget())
{
target->CastSpell(target, SPELL_DRUID_TREE_OF_LIFE_PASSIVE_1, aurEff);
target->CastSpell(target, SPELL_DRUID_TREE_OF_LIFE_PASSIVE_2, aurEff);
target->CastSpell(target, SPELL_DRUID_TREE_OF_LIFE_PASSIVE_3, aurEff);
}
}
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (Unit* target = GetTarget())
{
target->RemoveAurasDueToSpell(SPELL_DRUID_TREE_OF_LIFE_PASSIVE_1);
target->RemoveAurasDueToSpell(SPELL_DRUID_TREE_OF_LIFE_PASSIVE_2);
target->RemoveAurasDueToSpell(SPELL_DRUID_TREE_OF_LIFE_PASSIVE_3);
}
}
void Register() override
{
AfterEffectApply.Register(&spell_dru_tree_of_life::AfterApply, EFFECT_0, SPELL_AURA_MOD_SHAPESHIFT, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove.Register(&spell_dru_tree_of_life::AfterRemove, EFFECT_0, SPELL_AURA_MOD_SHAPESHIFT, AURA_EFFECT_HANDLE_REAL);
}
};
// 77495 - Harmony
class spell_dru_harmony : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_HARMONY });
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
{
PreventDefaultAction();
int32 amount = aurEff->GetAmount();
GetTarget()->CastSpell(GetTarget(), SPELL_DRUID_HARMONY, CastSpellExtraArgs(aurEff).AddSpellBP0(amount));
}
void Register() override
{
OnEffectProc.Register(&spell_dru_harmony::HandleProc, EFFECT_0, SPELL_AURA_ADD_PCT_MODIFIER);
}
};
// 17007 - Leader of the Pack
class spell_dru_leader_of_the_pack : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_LEADER_OF_THE_PACK_HEAL,
SPELL_DRUID_LEADER_OF_THE_PACK_ENERGIZE
});
}
bool CheckProc(ProcEventInfo& /*eventInfo*/)
{
return (GetTarget()->GetShapeshiftForm() == FORM_CAT || GetTarget()->GetShapeshiftForm() == FORM_BEAR);
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
{
PreventDefaultAction();
Unit* target = GetTarget();
int32 heal = 0;
if (SpellInfo const* healSpell = sSpellMgr->GetSpellInfo(SPELL_DRUID_LEADER_OF_THE_PACK_HEAL))
if (int32 bp = healSpell->Effects[EFFECT_0].BasePoints)
heal = CalculatePct(target->GetMaxHealth(), bp);
int32 mana = 0;
if (SpellInfo const* energizeSpell = sSpellMgr->GetSpellInfo(SPELL_DRUID_LEADER_OF_THE_PACK_ENERGIZE))
if (int32 bp = energizeSpell->Effects[EFFECT_0].BasePoints)
mana = CalculatePct(target->GetMaxPower(POWER_MANA), bp);
if (heal)
target->CastSpell(target, SPELL_DRUID_LEADER_OF_THE_PACK_HEAL, CastSpellExtraArgs(aurEff).AddSpellBP0(heal));
if (mana)
target->CastSpell(target, SPELL_DRUID_LEADER_OF_THE_PACK_ENERGIZE, CastSpellExtraArgs(aurEff).AddSpellBP0(mana));
}
void Register() override
{
DoCheckProc.Register(&spell_dru_leader_of_the_pack::CheckProc);
OnEffectProc.Register(&spell_dru_leader_of_the_pack::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
class spell_dru_wild_mushroom : public SpellScript
{
void HandleSummon()
{
Unit* caster = GetCaster();
if (!caster)
return;
std::list mushrooms;
caster->GetAllMinionsByEntry(mushrooms, GetSpellInfo()->Effects[EFFECT_0].MiscValue);
if (mushrooms.empty())
return;
TempSummon* oldestMushroom = nullptr;
if (mushrooms.size() > uint32(GetSpellInfo()->Effects[EFFECT_0].BasePoints))
{
for (auto itr : mushrooms)
{
if (TempSummon* mushroomToCheck = itr->ToTempSummon())
{
if (!oldestMushroom)
oldestMushroom = mushroomToCheck;
else
{
if (mushroomToCheck->GetTimer() < oldestMushroom->GetTimer())
oldestMushroom = mushroomToCheck;
}
}
}
if (oldestMushroom)
oldestMushroom->UnSummon();
}
}
void Register() override
{
AfterCast.Register(&spell_dru_wild_mushroom::HandleSummon);
}
};
class spell_dru_wild_mushroom_detonate : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_WILD_MUSHROOM,
SPELL_DRUID_WILD_MUSHROOM_DAMAGE,
SPELL_DRUID_WILD_MUSHROOM_SUICIDE,
SPELL_DRUID_WILD_MUSHROOM_VISUAL,
SPELL_DRUID_FUNGAL_GROWTH_R1,
SPELL_DRUID_FUNGAL_GROWTH_R2,
SPELL_DRUID_FUNGAL_GROWTH_SUMMON_R1,
SPELL_DRUID_FUNGAL_GROWTH_SUMMON_R2
});
}
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (!caster)
return;
SpellInfo const* spell = sSpellMgr->GetSpellInfo(SPELL_DRUID_WILD_MUSHROOM);
if (!spell)
return;
std::list mushrooms;
caster->GetAllMinionsByEntry(mushrooms, spell->Effects[EFFECT_0].MiscValue);
if (mushrooms.empty())
return;
for (auto itr : mushrooms)
{
if (TempSummon* mushroom = itr->ToTempSummon())
{
if (caster->HasAura(SPELL_DRUID_FUNGAL_GROWTH_R1))
caster->CastSpell(mushroom, SPELL_DRUID_FUNGAL_GROWTH_SUMMON_R1, true);
else if (caster->HasAura(SPELL_DRUID_FUNGAL_GROWTH_R2))
caster->CastSpell(mushroom, SPELL_DRUID_FUNGAL_GROWTH_SUMMON_R2, true);
caster->CastSpell(mushroom, SPELL_DRUID_WILD_MUSHROOM_DAMAGE, true);
mushroom->CastSpell(mushroom, SPELL_DRUID_WILD_MUSHROOM_VISUAL, true);
mushroom->CastSpell(mushroom, SPELL_DRUID_WILD_MUSHROOM_SUICIDE, true);
mushroom->UnSummon(1500);
}
}
}
void Register() override
{
OnEffectHitTarget.Register(&spell_dru_wild_mushroom_detonate::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 16913 - Moonfire (Passive)
class spell_dru_moonfire : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_LUNAR_ECLIPSE_MARKER,
SPELL_DRUID_SOLAR_ECLIPSE_MARKER,
SPELL_DRUID_SOLAR_ECLIPSE,
SPELL_DRUID_LUNAR_ECLIPSE,
SPELL_DRUID_SOLAR_ECLIPSE_SUNFIRE
});
}
void RemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* caster = GetCaster();
if (!caster)
return;
caster->RemoveAurasDueToSpell(SPELL_DRUID_SOLAR_ECLIPSE_SUNFIRE);
caster->RemoveAurasDueToSpell(SPELL_DRUID_LUNAR_ECLIPSE_MARKER);
caster->RemoveAurasDueToSpell(SPELL_DRUID_SOLAR_ECLIPSE_MARKER);
caster->RemoveAurasDueToSpell(SPELL_DRUID_SOLAR_ECLIPSE);
caster->RemoveAurasDueToSpell(SPELL_DRUID_LUNAR_ECLIPSE);
caster->SetPower(POWER_ECLIPSE, 0);
}
void Register() override
{
AfterEffectRemove.Register(&spell_dru_moonfire::RemoveEffect, EFFECT_0, SPELL_AURA_ADD_PCT_MODIFIER, AURA_EFFECT_HANDLE_REAL);
}
};
// 22568 - Ferocious Bite
class spell_dru_ferocious_bite : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_GLYPH_OF_FEROCIOUS_BITE });
}
bool Load() override
{
if (GetCaster()->GetTypeId() != TYPEID_PLAYER)
return false;
if (GetCaster()->ToPlayer()->getClass() != CLASS_DRUID)
return false;
return true;
}
void ChangeDamage(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (!caster)
return;
if (Player* player = caster->ToPlayer())
{
int32 damage = GetHitDamage();
damage += int32(player->GetComboPoints() * (player->GetTotalAttackPowerValue(BASE_ATTACK) * 0.109f));
// converts each extra point of energy (up to 35 energy) into additional damage
int32 energy = -(caster->ModifyPower(POWER_ENERGY, -35));
AddPct(damage, energy * float(100.0f / 35));
SetHitDamage(damage);
// Glyph of Ferocious Bite
if (AuraEffect* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, SPELL_ICON_ID_GLYPH_OF_FEROCIOUS_BITE, EFFECT_0))
{
int32 totalEnergySpentMultiplier = std::floor((GetSpell()->GetPowerCost() + energy) / 10);
int32 bp = aurEff->GetAmount() * totalEnergySpentMultiplier;
caster->CastSpell(caster, SPELL_DRUID_GLYPH_OF_FEROCIOUS_BITE, CastSpellExtraArgs(true).AddSpellBP0(bp));
}
}
}
void Register() override
{
OnEffectLaunchTarget.Register(&spell_dru_ferocious_bite::ChangeDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
// -33879 - Empowered Touch
class spell_dru_empowered_touch : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_EMPOWERED_TOUCH_SCRIPT });
}
bool CheckProc(ProcEventInfo& /*eventInfo*/)
{
return roll_chance_i(GetEffect(EFFECT_1)->GetAmount());
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
Unit* target = GetTarget();
target->CastSpell(eventInfo.GetProcTarget(), SPELL_DRUID_EMPOWERED_TOUCH_SCRIPT, aurEff);
}
void Register() override
{
DoCheckProc.Register(&spell_dru_empowered_touch::CheckProc);
OnEffectProc.Register(&spell_dru_empowered_touch::HandleProc, EFFECT_1, SPELL_AURA_DUMMY);
}
};
// 88433 - Empowered Touch
class spell_dru_empowered_touch_script : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_LIFEBLOOM });
}
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
if (Unit* caster = GetCaster())
{
if (Aura* aura = GetHitUnit()->GetAura(SPELL_DRUID_LIFEBLOOM, caster->GetGUID()))
{
aura->RefreshDuration(false);
// Refreshing Lifebloom while having Revitalize active causes Replenishment to be cast
if (caster->GetAuraOfRankedSpell(SPELL_DRUID_REVITALIZE_R1, caster->GetGUID()))
caster->CastSpell(nullptr, SPELL_REPLENISHMENT, true);
}
}
}
void Register() override
{
OnEffectHitTarget.Register(&spell_dru_empowered_touch_script::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 93400 - Shooting Stars
class spell_dru_shooting_stars : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_STARSURGE });
}
void HandleCooldownReset(SpellEffIndex /*effIndex*/)
{
GetHitUnit()->GetSpellHistory()->ResetCooldown(SPELL_DRUID_STARSURGE, true);
}
void Register() override
{
OnEffectHitTarget.Register(&spell_dru_shooting_stars::HandleCooldownReset, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
}
};
// 80313 - Pulverize
class spell_dru_pulverize : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_PULVERIZE_TRIGGERED,
SPELL_DRUID_LACERATE
});
}
void CalculateDamage(Unit* victim, int32& damage, int32& /*flatMod*/, float& /*pctMod*/)
{
// Overriding the default damage calculation since the normalized weapon damage bonus scales
// with the amount of Lacerate stacks
Unit* caster = GetCaster();
int32 weaponDamagePct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(caster);
int32 weaponDamage = CalculatePct(caster->CalculateDamage(BASE_ATTACK, true, true), weaponDamagePct);
damage = weaponDamage;
// Damage bonus per application of Lacerate
if (Aura* aura = victim->GetAura(SPELL_DRUID_LACERATE, caster->GetGUID()))
{
int32 normalizedDamageBonus = GetSpellInfo()->Effects[EFFECT_2].CalcValue(caster);
damage += CalculatePct(normalizedDamageBonus, weaponDamagePct) * aura->GetStackAmount();
}
}
void HandleLacerateRemoval(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (Aura* aura = GetHitUnit()->GetAura(SPELL_DRUID_LACERATE, caster->GetGUID()))
{
// Crit chance bonus per Lacerate stack consumed
int32 critPerStack = sSpellMgr->GetSpellInfo(SPELL_DRUID_PULVERIZE_TRIGGERED)->Effects[EFFECT_0].CalcValue(caster);
caster->CastSpell(caster, SPELL_DRUID_PULVERIZE_TRIGGERED, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellBP0(critPerStack * aura->GetStackAmount()));
aura->Remove();
}
}
void Register() override
{
CalcDamage.Register(&spell_dru_pulverize::CalculateDamage);
OnEffectHitTarget.Register(&spell_dru_pulverize::HandleLacerateRemoval, EFFECT_0, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE);
}
};
// 22842 - Frenzied Regeneration
class spell_dru_frenzied_regeneration : public AuraScript
{
bool Validate(SpellInfo const* /*spell*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_FRENZIED_REGENERATION_HEAL });
}
void HandleHealthAfterApply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
int32 pct = GetSpellInfo()->Effects[aurEff->GetEffIndex()].CalcValue();
if (target->GetHealthPct() < pct)
target->SetHealth(CalculatePct(target->GetMaxHealth(), pct));
}
void HandleRegeneration(AuraEffect const* aurEff)
{
Unit* target = GetTarget();
// Glyph of Frenzied Regeneration - block heal
if (target->GetAuraEffect(SPELL_AURA_ADD_FLAT_MODIFIER, SPELLFAMILY_DRUID, SPELL_ICON_ID_GLYPH_OF_FRENZIED_REGENERATION, EFFECT_0))
return;
float healthPct = CalculatePct(aurEff->GetAmount(), 1);
uint32 rage = target->GetPower(POWER_RAGE) > 100 ? 100 : target->GetPower(POWER_RAGE);
int32 heal = CalculatePct(target->GetMaxHealth(), healthPct) * CalculatePct(rage, 10);
target->ModifyPower(POWER_RAGE, int32(rage * -1));
target->CastSpell(target, SPELL_DRUID_FRENZIED_REGENERATION_HEAL, CastSpellExtraArgs(aurEff).AddSpellBP0(heal));
}
void Register() override
{
OnEffectPeriodic.Register(&spell_dru_frenzied_regeneration::HandleRegeneration, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
AfterEffectApply.Register(&spell_dru_frenzied_regeneration::HandleHealthAfterApply, EFFECT_1, SPELL_AURA_MOD_INCREASE_HEALTH_2, AURA_EFFECT_HANDLE_REAL);
}
};
class spell_dru_stampeding_roar : public SpellScript
{
bool Validate(SpellInfo const* /*spell*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_FERAL_SWIFTNESS,
SPELL_DRUID_FERAL_SWIFTNESS_CLEAR_ROAR
});
}
void HandleFeralSwiftness(SpellEffIndex /*effIndex*/)
{
Unit* target = GetHitUnit();
if (GetCaster() != target)
return;
if (Aura* swiftness = target->GetAuraOfRankedSpell(SPELL_DRUID_FERAL_SWIFTNESS, target->GetGUID()))
if (roll_chance_i(swiftness->GetSpellInfo()->Effects[EFFECT_1].BasePoints))
target->CastSpell(target, SPELL_DRUID_FERAL_SWIFTNESS_CLEAR_ROAR, true);
}
void Register() override
{
OnEffectHitTarget.Register(&spell_dru_stampeding_roar::HandleFeralSwiftness, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
}
};
class spell_dru_feral_swiftness_clear : public SpellScript
{
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
GetHitUnit()->RemoveAppliedAuras([](AuraApplication const* aurApp)->bool
{
SpellInfo const* auraSpellInfo = aurApp->GetBase()->GetSpellInfo();
uint32 mechanicMask = auraSpellInfo->GetSpellMechanicMaskByEffectMask(EFFECT_ALL);
return (mechanicMask & (1 << MECHANIC_ROOT)) || (mechanicMask & (1 << MECHANIC_SNARE));
});
}
void Register() override
{
OnEffectHitTarget.Register(&spell_dru_feral_swiftness_clear::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// -80318 - Blood in the Water
class spell_dru_blood_in_the_water : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_BLOOD_IN_THE_WATER_SCRIPT,
SPELL_DRUID_T13_FERAL_2P_BONUS
});
}
bool CheckProc(ProcEventInfo& eventInfo)
{
if (!eventInfo.GetDamageInfo() || !eventInfo.GetDamageInfo()->GetVictim())
return false;
float healthPct = 25.f;
// T13 Bonus
if (GetTarget()->HasAura(SPELL_DRUID_T13_FERAL_2P_BONUS))
healthPct = sSpellMgr->AssertSpellInfo(SPELL_DRUID_T13_FERAL_2P_BONUS)->Effects[EFFECT_1].BasePoints;
return eventInfo.GetDamageInfo()->GetVictim()->GetHealthPct() <= healthPct && roll_chance_i(50 * GetSpellInfo()->GetRank());
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_DRUID_BLOOD_IN_THE_WATER_SCRIPT, aurEff);
}
void Register() override
{
DoCheckProc.Register(&spell_dru_blood_in_the_water::CheckProc);
OnEffectProc.Register(&spell_dru_blood_in_the_water::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 80863 - Blood in the Water
class spell_dru_blood_in_the_water_script : public SpellScript
{
bool Validate(SpellInfo const* /*spell*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_RIP });
}
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
if (Unit* caster = GetCaster())
if (Aura* aura = GetHitUnit()->GetAura(SPELL_DRUID_RIP, caster->GetGUID()))
aura->RefreshDuration(false);
}
void Register() override
{
OnEffectHitTarget.Register(&spell_dru_blood_in_the_water_script::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 90164 - Astral Alignment
class spell_dru_astral_alignment : public AuraScript
{
void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& /*eventInfo*/)
{
PreventDefaultAction();
GetAura()->ModStackAmount(-1);
}
void Register() override
{
OnEffectProc.Register(&spell_dru_astral_alignment::HandleProc, EFFECT_0, SPELL_AURA_MOD_SPELL_CRIT_CHANCE);
}
};
// 100977 - Harmony
class spell_dru_harmony_triggered : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_BLOOM });
}
void RemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->RemoveAurasDueToSpell(SPELL_DRUID_BLOOM);
}
void Register() override
{
AfterEffectRemove.Register(&spell_dru_harmony_triggered::RemoveEffect, EFFECT_0, SPELL_AURA_ADD_PCT_MODIFIER, AURA_EFFECT_HANDLE_REAL);
}
};
// 90165 - Item - Druid T11 Feral 4P Bonus
class spell_dru_item_t11_feral_4p_bonus : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_STRENGTH_OF_THE_PANTHER });
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& /*eventInfo*/)
{
PreventDefaultAction();
GetTarget()->CastSpell(GetTarget(), SPELL_DRUID_STRENGTH_OF_THE_PANTHER, aurEff);
}
void Register() override
{
OnEffectProc.Register(&spell_dru_item_t11_feral_4p_bonus::HandleProc, EFFECT_0, SPELL_AURA_ADD_PCT_MODIFIER);
}
};
// 80964 - Skull Bash (Bear Form)
// 80965 - Skull Bash (Cat Form)
class spell_dru_skull_bash : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_SKULL_BASH_CHARGE,
SPELL_DRUID_SKULL_BASH_INTERRUPT,
SPELL_DRUID_SKULL_BASH_COST_INCREASE_R1,
SPELL_DRUID_SKULL_BASH_COST_INCREASE_R2,
SPELL_DRUID_BRUTAL_IMPACT_R1
});
}
void HandleDummyEffect(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (!caster)
return;
Unit* target = GetHitUnit();
caster->CastSpell(target, SPELL_DRUID_SKULL_BASH_CHARGE);
caster->CastSpell(target, SPELL_DRUID_SKULL_BASH_INTERRUPT);
if (Aura const* aura = caster->GetAuraOfRankedSpell(SPELL_DRUID_BRUTAL_IMPACT_R1, caster->GetGUID()))
caster->CastSpell(target, aura->GetSpellInfo()->GetRank() == 1 ? SPELL_DRUID_SKULL_BASH_COST_INCREASE_R1 : SPELL_DRUID_SKULL_BASH_COST_INCREASE_R2);
}
void Register() override
{
OnEffectHitTarget.Register(&spell_dru_skull_bash::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
// 50464 - Nourish
class spell_dru_nourish : public SpellScript
{
// Nourish heals for an additional 20% if Rejuvenation, Regrowth, Wild Growth or Lifebloom is on the target
void HandleHealBonus(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (!caster)
return;
auto const& periodicHealEffects = GetHitUnit()->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);
bool applyBonus = std::any_of(periodicHealEffects.begin(), periodicHealEffects.end(), [guid = caster->GetGUID()](AuraEffect const* aurEff)
{
if (aurEff->GetCasterGUID() != guid || aurEff->GetSpellInfo()->SpellFamilyName != SPELLFAMILY_DRUID)
return false;
return aurEff->GetSpellInfo()->SpellFamilyFlags.HasFlag(0x10 | 0x40, 0x10 | 0x4000000, 0);
});
if (applyBonus)
SetEffectValue(GetEffectValue() * 1.2f);
}
void Register() override
{
OnEffectLaunchTarget.Register(&spell_dru_nourish::HandleHealBonus, EFFECT_0, SPELL_EFFECT_HEAL);
}
};
// 6807 - Maul (Bear Form)
class spell_dru_maul : public SpellScript
{
void CalculateDamage(Unit* /*victim*/, int32& damage, int32& /*flatMod*/, float& /*pctMod*/)
{
damage = 35 + GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK) * 0.19f -1;
}
void Register() override
{
CalcDamage.Register(&spell_dru_maul::CalculateDamage);
}
};
// 9005 - Pounce
class spell_dru_pounce : public SpellScript
{
SpellCastResult CheckCast()
{
if (GetCaster()->HasAura(SPELL_RACIAL_SHADOWMELD))
return SPELL_FAILED_TARGET_AURASTATE;
return SPELL_CAST_OK;
}
void Register() override
{
OnCheckCast.Register(&spell_dru_pounce::CheckCast);
}
};
// 6785 - Ravage
class spell_dru_ravage : public SpellScript
{
SpellCastResult CheckCast()
{
if (GetCaster()->HasAura(SPELL_RACIAL_SHADOWMELD))
return SPELL_FAILED_TARGET_AURASTATE;
return SPELL_CAST_OK;
}
void Register() override
{
OnCheckCast.Register(&spell_dru_ravage::CheckCast);
}
};
// 99015 - Item - Druid T12 Restoration 4P Bonus
class spell_dru_t12_restoration_4p_bonus : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_FIREBLOOM });
}
void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_DRUID_FIREBLOOM, CastSpellExtraArgs(aurEff).AddSpellBP0(eventInfo.GetHealInfo()->GetEffectiveHeal()));
}
void Register() override
{
OnEffectProc.Register(&spell_dru_t12_restoration_4p_bonus::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 99017 - Firebloom
class spell_dru_firebloom : public SpellScript
{
void FilterTargets(std::list& targets)
{
if (targets.size() < 2)
return;
targets.sort(Trinity::HealthPctOrderPred());
targets.resize(1);
}
void Register() override
{
OnObjectAreaTargetSelect.Register(&spell_dru_firebloom::FilterTargets, EFFECT_0, TARGET_UNIT_DEST_AREA_ALLY);
}
};
// -17074 Nature's Bounty
class spell_dru_natures_bounty : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_NATURES_BOUNTY,
SPELL_DRUID_REJUVENATION
});
}
void CalcPeriodic(AuraEffect const* /*aurEff*/, bool& isPeriodic, int32& period)
{
isPeriodic = true;
period = 1 * IN_MILLISECONDS;
}
void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
{
PreventDefaultAction();
if (Unit* target = eventInfo.GetProcTarget())
_activeRejuvenationTargetGUIDs.push_back(target->GetGUID());
if (_activeRejuvenationTargetGUIDs.size() >= 3 && !_bountyActive)
{
int32 bp = GetSpellInfo()->Effects[EFFECT_1].CalcValue();
GetTarget()->CastSpell(nullptr, SPELL_DRUID_NATURES_BOUNTY, CastSpellExtraArgs(true).AddSpellBP0(bp));
_bountyActive = true;
}
}
void HandlePeriodic(AuraEffect const* /*aurEff*/)
{
Unit* target = GetTarget();
for (auto itr = _activeRejuvenationTargetGUIDs.begin(); itr != _activeRejuvenationTargetGUIDs.end();)
{
Unit* healTarget = ObjectAccessor::GetUnit(*target, *itr);
if (!healTarget || !healTarget->HasAura(SPELL_DRUID_REJUVENATION, target->GetGUID()))
itr = _activeRejuvenationTargetGUIDs.erase(itr);
else
++itr;
}
if (_bountyActive && _activeRejuvenationTargetGUIDs.size() < 3)
{
target->RemoveAurasDueToSpell(SPELL_DRUID_NATURES_BOUNTY, target->GetGUID());
_bountyActive = false;
}
}
void Register() override
{
DoEffectCalcPeriodic.Register(&spell_dru_natures_bounty::CalcPeriodic, EFFECT_0, SPELL_AURA_ADD_FLAT_MODIFIER);
OnEffectProc.Register(&spell_dru_natures_bounty::HandleProc, EFFECT_0, SPELL_AURA_ADD_FLAT_MODIFIER);
OnEffectPeriodic.Register(&spell_dru_natures_bounty::HandlePeriodic, EFFECT_0, SPELL_AURA_ADD_FLAT_MODIFIER);
}
private:
std::vector _activeRejuvenationTargetGUIDs;
bool _bountyActive = false;
};
// 339 - Entangling Roots
class spell_dru_entangling_roots : public AuraScript
{
static constexpr uint8 DEFAULT_PROCS = 4; // The number of allowed procs for a target of the same level as the caster
static constexpr uint8 MINIMUM_PROCS = 2; // The minimum amount of procs
void CalculateProcAmount(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* caster = GetCaster();
if (!caster)
return;
// Every two level difference increase or reduce the chance of breaking. Tree of Life enhances this effect
int16 offset = (caster->getLevel() - GetTarget()->getLevel()) / 2;
_allowedProcs = std::max(MINIMUM_PROCS, DEFAULT_PROCS + offset);
if (caster->GetShapeshiftForm() == FORM_TREE)
++_allowedProcs;
}
bool CheckProc(ProcEventInfo& /*eventInfo*/)
{
if (_allowedProcs != 0)
--_allowedProcs;
if (_allowedProcs == 0)
return true;
return false;
}
void Register() override
{
AfterEffectApply.Register(&spell_dru_entangling_roots::CalculateProcAmount, EFFECT_0, SPELL_AURA_MOD_ROOT, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
DoCheckProc.Register(&spell_dru_entangling_roots::CheckProc);
}
private:
uint8 _allowedProcs = 0;
};
// 8936 - Regrowth
class spell_dru_regrowth : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_REGROWTH_REFRESH });
}
void HandleGlyphEffect(AuraEffect const* aurEff)
{
Unit* caster = GetCaster();
if (!caster)
return;
if (aurEff->GetTickNumber() < aurEff->GetTotalTicks() - 1)
return;
if (AuraEffect const* glyphEffect = caster->GetDummyAuraEffect(SPELLFAMILY_DRUID, SPELL_ICON_ID_GLYPH_OF_REGROWTH, EFFECT_0))
if (GetTarget()->GetHealthPct() <= glyphEffect->GetAmount())
caster->CastSpell(GetTarget(), SPELL_DRUID_REGROWTH_REFRESH, true);
}
void Register() override
{
OnEffectPeriodic.Register(&spell_dru_regrowth::HandleGlyphEffect, EFFECT_1, SPELL_AURA_PERIODIC_HEAL);
}
};
// 93036 - Regrowth Refresh
class spell_dru_regrowth_refresh : public SpellScript
{
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
// Though the script effect implies that the duration is refreshed by 6 seconds, sniffs show that it's a plain refresh with rolling ticks
if (Unit* caster = GetCaster())
if (AuraEffect* aurEff = GetHitUnit()->GetAuraEffect(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40, 0, 0, caster->GetGUID()))
aurEff->GetBase()->RefreshDuration(false);
}
void Register() override
{
OnEffectHitTarget.Register(&spell_dru_regrowth_refresh::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 16979 - Feral Charge (Bear Form)
// 49376 - Feral Charge (Cat Form)
class spell_dru_feral_charge : public SpellScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo(
{
SPELL_DRUID_FERAL_CHARGE_BEAR,
SPELL_DRUID_FERAL_CHARGE_CAT,
SPELL_DRUID_STAMPEDE_TRIGGERED_BEAR,
SPELL_DRUID_STAMPEDE_TRIGGERED_CAT
});
}
void HandleBearFormEffect(SpellEffIndex /*effIndex*/)
{
if (AuraEffect const* stampedeEffect = GetCaster()->GetDummyAuraEffect(SPELLFAMILY_DRUID, SPELL_ICON_ID_STAMPEDE, EFFECT_0))
GetCaster()->CastSpell(nullptr, sSpellMgr->GetSpellWithRank(SPELL_DRUID_STAMPEDE_TRIGGERED_BEAR, stampedeEffect->GetSpellInfo()->GetRank()));
}
void HandleCatFormEffect(SpellEffIndex /*effIndex*/)
{
if (AuraEffect const* stampedeEffect = GetCaster()->GetDummyAuraEffect(SPELLFAMILY_DRUID, SPELL_ICON_ID_STAMPEDE, EFFECT_0))
GetCaster()->CastSpell(nullptr, sSpellMgr->GetSpellWithRank(SPELL_DRUID_STAMPEDE_TRIGGERED_CAT, stampedeEffect->GetSpellInfo()->GetRank()));
}
void Register() override
{
if (m_scriptSpellId == SPELL_DRUID_FERAL_CHARGE_BEAR)
OnEffectLaunchTarget.Register(&spell_dru_feral_charge::HandleBearFormEffect, EFFECT_0, SPELL_EFFECT_CHARGE);
else if (m_scriptSpellId == SPELL_DRUID_FERAL_CHARGE_CAT)
OnEffectLaunchTarget.Register(&spell_dru_feral_charge::HandleCatFormEffect, EFFECT_0, SPELL_EFFECT_TRIGGER_SPELL);
}
};
// -81021 - Stampede
class spell_dru_stampede_triggered : public AuraScript
{
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_DRUID_STAMPEDE_RAVAGE_MARKER });
}
void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->CastSpell(nullptr, SPELL_DRUID_STAMPEDE_RAVAGE_MARKER);
}
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->RemoveAurasDueToSpell(SPELL_DRUID_STAMPEDE_RAVAGE_MARKER, GetTarget()->GetGUID());
}
void Register() override
{
// Going with SPELL_AURA_ANY because both ranks have different aura effects for some reason
AfterEffectApply.Register(&spell_dru_stampede_triggered::AfterApply, EFFECT_0, SPELL_AURA_ANY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
AfterEffectRemove.Register(&spell_dru_stampede_triggered::AfterRemove, EFFECT_0, SPELL_AURA_ANY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
}
};
}
void AddSC_druid_spell_scripts()
{
using namespace Spells::Druid;
RegisterSpellScript(spell_dru_astral_alignment);
RegisterSpellScript(spell_dru_berserk);
RegisterSpellScript(spell_dru_blood_in_the_water);
RegisterSpellScript(spell_dru_blood_in_the_water_script);
RegisterSpellAndAuraScriptPair(spell_dru_dash, spell_dru_dash_AuraScript);
RegisterSpellScript(spell_dru_eclipse);
RegisterSpellScript(spell_dru_eclipse_mastery_driver_passive);
RegisterSpellScript(spell_dru_effloresence);
RegisterSpellScript(spell_dru_effloresence_aoe);
RegisterSpellScript(spell_dru_effloresence_heal);
RegisterSpellScript(spell_dru_empowered_touch);
RegisterSpellScript(spell_dru_empowered_touch_script);
RegisterSpellScript(spell_dru_enrage);
RegisterSpellScript(spell_dru_entangling_roots);
RegisterSpellScript(spell_dru_feral_charge);
RegisterSpellScript(spell_dru_ferocious_bite);
RegisterSpellScript(spell_dru_firebloom);
RegisterSpellScript(spell_dru_frenzied_regeneration);
RegisterSpellScript(spell_dru_glyph_of_starfire);
RegisterSpellScript(spell_dru_glyph_of_starfire_proc);
RegisterSpellScript(spell_dru_harmony);
RegisterSpellScript(spell_dru_harmony_triggered);
RegisterSpellScript(spell_dru_idol_lifebloom);
RegisterSpellScript(spell_dru_innervate);
RegisterSpellScript(spell_dru_insect_swarm);
RegisterSpellScript(spell_dru_leader_of_the_pack);
RegisterSpellScript(spell_dru_lifebloom);
RegisterSpellScript(spell_dru_living_seed);
RegisterSpellScript(spell_dru_living_seed_proc);
RegisterSpellScript(spell_dru_maul);
RegisterSpellScript(spell_dru_moonfire);
RegisterSpellScript(spell_dru_natures_bounty);
RegisterSpellScript(spell_dru_nourish);
RegisterSpellScript(spell_dru_pulverize);
RegisterSpellScript(spell_dru_regrowth);
RegisterSpellScript(spell_dru_regrowth_refresh);
RegisterSpellScript(spell_dru_rejuvenation);
RegisterSpellScript(spell_dru_rip);
RegisterSpellScript(spell_dru_savage_defense);
RegisterSpellAndAuraScriptPair(spell_dru_savage_roar, spell_dru_savage_roar_AuraScript);
RegisterSpellScript(spell_dru_shooting_stars);
RegisterSpellScript(spell_dru_skull_bash);
RegisterSpellScript(spell_dru_stampede_triggered);
RegisterSpellScript(spell_dru_starfall_dummy);
RegisterSpellScript(spell_dru_solar_beam);
RegisterSpellAndAuraScriptPair(spell_dru_survival_instincts, spell_dru_survival_instincts_AuraScript);
RegisterSpellScript(spell_dru_swift_flight_passive);
RegisterSpellScript(spell_dru_swift_flight_form);
RegisterSpellScript(spell_dru_flight_form);
RegisterSpellScript(spell_dru_tiger_s_fury);
RegisterSpellScript(spell_dru_tree_of_life);
RegisterSpellScript(spell_dru_typhoon);
RegisterSpellScript(spell_dru_t10_restoration_4p_bonus);
RegisterSpellScript(spell_dru_t12_restoration_4p_bonus);
RegisterSpellScript(spell_dru_item_t11_feral_4p_bonus);
RegisterSpellScript(spell_dru_wild_growth);
RegisterSpellScript(spell_dru_wild_mushroom);
RegisterSpellScript(spell_dru_wild_mushroom_detonate);
RegisterSpellScript(spell_dru_stampeding_roar);
RegisterSpellScript(spell_dru_feral_swiftness_clear);
RegisterSpellScript(spell_dru_pounce);
RegisterSpellScript(spell_dru_ravage);
}