mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-24 19:06:49 +01:00
Scripts/Spells: Implemented monk stagger (#26295)
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
-- Stagger
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_monk_stagger', 'spell_monk_stagger_damage_aura', 'spell_monk_stagger_debuff_aura');
|
||||
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
|
||||
(115069, 'spell_monk_stagger'),
|
||||
(124255, 'spell_monk_stagger_damage_aura'),
|
||||
(124273, 'spell_monk_stagger_debuff_aura'),
|
||||
(124274, 'spell_monk_stagger_debuff_aura'),
|
||||
(124275, 'spell_monk_stagger_debuff_aura');
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user