aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/scripts/Spells/spell_monk.cpp230
1 files changed, 230 insertions, 0 deletions
diff --git a/src/server/scripts/Spells/spell_monk.cpp b/src/server/scripts/Spells/spell_monk.cpp
index 772244cf753..b12aa458e68 100644
--- a/src/server/scripts/Spells/spell_monk.cpp
+++ b/src/server/scripts/Spells/spell_monk.cpp
@@ -21,6 +21,7 @@
*/
#include "ScriptMgr.h"
+#include "DB2Stores.h"
#include "Spell.h"
#include "SpellAuraEffects.h"
#include "SpellInfo.h"
@@ -38,6 +39,10 @@ enum MonkSpells
SPELL_MONK_PROVOKE_AOE = 118635,
SPELL_MONK_SOOTHING_MIST = 115175,
SPELL_MONK_STANCE_OF_THE_SPIRITED_CRANE = 154436,
+ SPELL_MONK_STAGGER_DAMAGE_AURA = 124255,
+ SPELL_MONK_STAGGER_HEAVY = 124273,
+ SPELL_MONK_STAGGER_LIGHT = 124275,
+ SPELL_MONK_STAGGER_MODERATE = 124274,
SPELL_MONK_SURGING_MIST_HEAL = 116995,
};
@@ -159,9 +164,234 @@ class spell_monk_provoke : public SpellScript
}
};
+// Utility for stagger scripts
+Aura* FindExistingStaggerEffect(Unit* unit)
+{
+ if (Aura* auraLight = unit->GetAura(SPELL_MONK_STAGGER_LIGHT))
+ return auraLight;
+
+ if (Aura* auraModerate = unit->GetAura(SPELL_MONK_STAGGER_MODERATE))
+ return auraModerate;
+
+ if (Aura* auraHeavy = unit->GetAura(SPELL_MONK_STAGGER_HEAVY))
+ return auraHeavy;
+
+ return nullptr;
+}
+
+static constexpr SpellEffIndex AuraStaggerEffectTick = EFFECT_0;
+static constexpr SpellEffIndex AuraStaggerEffectTotal = EFFECT_1;
+
+// 115069 - Stagger
+class spell_monk_stagger : public AuraScript
+{
+ PrepareAuraScript(spell_monk_stagger);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_MONK_STAGGER_LIGHT, SPELL_MONK_STAGGER_MODERATE, SPELL_MONK_STAGGER_HEAVY });
+ }
+
+ void AbsorbNormal(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& /*absorbAmount*/)
+ {
+ Absorb(dmgInfo, 1.0f);
+ }
+
+ void AbsorbMagic(AuraEffect* /*aurEff*/, DamageInfo& dmgInfo, uint32& /*absorbAmount*/)
+ {
+ AuraEffect const* effect = GetEffect(EFFECT_4);
+ if (!effect)
+ return;
+
+ Absorb(dmgInfo, float(effect->GetAmount()) / 100.0f);
+ }
+
+ void Absorb(DamageInfo& dmgInfo, float multiplier)
+ {
+ // Prevent default action (which would remove the aura)
+ PreventDefaultAction();
+
+ // make sure damage doesn't come from stagger damage spell SPELL_MONK_STAGGER_DAMAGE_AURA
+ if (SpellInfo const* dmgSpellInfo = dmgInfo.GetSpellInfo())
+ if (dmgSpellInfo->Id == SPELL_MONK_STAGGER_DAMAGE_AURA)
+ return;
+
+ AuraEffect const* effect = GetEffect(AuraStaggerEffectTick);
+ if (!effect)
+ return;
+
+ Unit* target = GetTarget();
+ float agility = target->GetStat(STAT_AGILITY);
+ float base = CalculatePct(agility, float(effect->GetAmount()));
+ float K = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::ArmorConstant, target->getLevel(), -2, 0, Classes(target->getClass()));
+
+ float newAmount = (base / (base + K));
+ newAmount *= multiplier;
+
+ // Absorb X percentage of the damage
+ float absorbAmount = float(dmgInfo.GetDamage()) * newAmount;
+ if (absorbAmount > 0)
+ {
+ dmgInfo.AbsorbDamage(absorbAmount);
+
+ // Cast stagger and make it tick on each tick
+ AddAndRefreshStagger(absorbAmount);
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_monk_stagger::AbsorbNormal, EFFECT_1);
+ OnEffectAbsorb += AuraEffectAbsorbFn(spell_monk_stagger::AbsorbMagic, EFFECT_2);
+ }
+
+private:
+ void AddAndRefreshStagger(float amount)
+ {
+ Unit* target = GetTarget();
+ if (Aura* auraStagger = FindExistingStaggerEffect(target))
+ {
+ AuraEffect* effStaggerRemaining = auraStagger->GetEffect(AuraStaggerEffectTotal);
+ if (!effStaggerRemaining)
+ return;
+
+ float newAmount = effStaggerRemaining->GetAmount() + amount;
+ uint32 spellId = GetStaggerSpellId(target, newAmount);
+ if (spellId == effStaggerRemaining->GetSpellInfo()->Id)
+ {
+ auraStagger->RefreshDuration();
+ effStaggerRemaining->ChangeAmount(newAmount, false, true /* reapply */);
+ }
+ else
+ {
+ // amount changed the stagger type so we need to change the stagger amount (e.g. from medium to light)
+ GetTarget()->RemoveAura(auraStagger);
+ AddNewStagger(target, spellId, newAmount);
+ }
+ }
+ else
+ AddNewStagger(target, GetStaggerSpellId(target, amount), amount);
+ }
+
+ uint32 GetStaggerSpellId(Unit* unit, float amount)
+ {
+ const float StaggerHeavy = 0.6f;
+ const float StaggerModerate = 0.3f;
+
+ float staggerPct = amount / float(unit->GetMaxHealth());
+ return (staggerPct >= StaggerHeavy) ? SPELL_MONK_STAGGER_HEAVY :
+ (staggerPct >= StaggerModerate) ? SPELL_MONK_STAGGER_MODERATE :
+ SPELL_MONK_STAGGER_LIGHT;
+ }
+
+ void AddNewStagger(Unit* unit, uint32 staggerSpellId, float staggerAmount)
+ {
+ // We only set the total stagger amount. The amount per tick will be set by the stagger spell script
+ unit->CastSpell(unit, staggerSpellId, CastSpellExtraArgs(SPELLVALUE_BASE_POINT1, staggerAmount).SetTriggerFlags(TRIGGERED_FULL_MASK));
+ }
+};
+
+// 124255 - Stagger - SPELL_MONK_STAGGER_DAMAGE_AURA
+class spell_monk_stagger_damage_aura : public AuraScript
+{
+ PrepareAuraScript(spell_monk_stagger_damage_aura);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return ValidateSpellInfo({ SPELL_MONK_STAGGER_LIGHT, SPELL_MONK_STAGGER_MODERATE, SPELL_MONK_STAGGER_HEAVY });
+ }
+
+ void OnPeriodicDamage(AuraEffect const* aurEff)
+ {
+ // Update our light/medium/heavy stagger with the correct stagger amount left
+ if (Aura* auraStagger = FindExistingStaggerEffect(GetTarget()))
+ {
+ if (AuraEffect* auraEff = auraStagger->GetEffect(AuraStaggerEffectTotal))
+ {
+ float total = float(auraEff->GetAmount());
+ float tickDamage = float(aurEff->GetDamage());
+ auraEff->ChangeAmount(total - tickDamage);
+ }
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_monk_stagger_damage_aura::OnPeriodicDamage, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
+ }
+};
+
+// 124273, 124274, 124275 - Light/Moderate/Heavy Stagger - SPELL_MONK_STAGGER_LIGHT / SPELL_MONK_STAGGER_MODERATE / SPELL_MONK_STAGGER_HEAVY
+class spell_monk_stagger_debuff_aura : public AuraScript
+{
+ PrepareAuraScript(spell_monk_stagger_debuff_aura);
+
+ bool Load() override
+ {
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_MONK_STAGGER_DAMAGE_AURA, GetCastDifficulty());
+ SpellEffectInfo const* effInfo = !spellInfo ? nullptr : spellInfo->GetEffect(EFFECT_0);
+ if (!effInfo)
+ return false;
+
+ _period = float(effInfo->ApplyAuraPeriod);
+ return true;
+ }
+
+ void OnReapply(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ // Calculate damage per tick
+ float total = float(aurEff->GetAmount());
+ float perTick = total * _period / float(GetDuration()); // should be same as GetMaxDuration() TODO: verify
+
+ // Set amount on effect for tooltip
+ AuraEffect* effInfo = GetAura()->GetEffect(AuraStaggerEffectTick);
+ if (effInfo)
+ effInfo->ChangeAmount(perTick);
+
+ // Set amount on damage aura (or cast it if needed)
+ CastOrChangeTickDamage(perTick);
+ }
+
+ void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes mode)
+ {
+ if (mode != AURA_EFFECT_HANDLE_REAL)
+ return;
+
+ // Remove damage aura
+ GetTarget()->RemoveAura(SPELL_MONK_STAGGER_DAMAGE_AURA);
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectRemoveFn(spell_monk_stagger_debuff_aura::OnReapply, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_monk_stagger_debuff_aura::OnRemove, EFFECT_1, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
+ }
+
+private:
+ float _period = 0.0f;
+
+ void CastOrChangeTickDamage(float tickDamage)
+ {
+ Unit* unit = GetTarget();
+ Aura* auraDamage = unit->GetAura(SPELL_MONK_STAGGER_DAMAGE_AURA);
+ if (!auraDamage)
+ {
+ unit->CastSpell(unit, SPELL_MONK_STAGGER_DAMAGE_AURA, true);
+ auraDamage = unit->GetAura(SPELL_MONK_STAGGER_DAMAGE_AURA);
+ }
+
+ if (auraDamage)
+ if (AuraEffect* eff = auraDamage->GetEffect(AuraStaggerEffectTick))
+ eff->SetDamage(tickDamage);
+ }
+};
+
void AddSC_monk_spell_scripts()
{
RegisterAuraScript(spell_monk_crackling_jade_lightning);
RegisterAuraScript(spell_monk_crackling_jade_lightning_knockback_proc_aura);
RegisterSpellScript(spell_monk_provoke);
+ RegisterAuraScript(spell_monk_stagger);
+ RegisterAuraScript(spell_monk_stagger_damage_aura);
+ RegisterAuraScript(spell_monk_stagger_debuff_aura);
}