diff options
| author | Cristian Vintila <127750549+cristianvnt@users.noreply.github.com> | 2025-12-22 00:32:12 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-21 23:32:12 +0100 |
| commit | d22dae08aafaeb8021438dd283fdee110f18d9b2 (patch) | |
| tree | 3cfc0062ff61e9ae4eabd7c09e36111793c1fbd0 /src | |
| parent | 161da58cf4040b4fbcd2e0efcb3a961dec202237 (diff) | |
Scripts/Spells: Implement priest talent Ultimate Penitence (#31444)
Co-authored-by: Shauren <shauren.trinity@gmail.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/scripts/Spells/spell_priest.cpp | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 1cb580810c5..5e42eec1432 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -199,8 +199,11 @@ enum PriestSpells SPELL_PRIEST_TWILIGHT_EQUILIBRIUM_HOLY = 390706, SPELL_PRIEST_TWILIGHT_EQUILIBRIUM_SHADOW = 390707, SPELL_PRIEST_ULTIMATE_PENITENCE = 421453, + SPELL_PRIEST_ULTIMATE_PENITENCE_CHANNEL = 421434, SPELL_PRIEST_ULTIMATE_PENITENCE_DAMAGE = 421543, + SPELL_PRIEST_ULTIMATE_PENITENCE_FALLING_FACING_CONTROL = 419305, SPELL_PRIEST_ULTIMATE_PENITENCE_HEAL = 421544, + SPELL_PRIEST_ULTIMATE_PENITENCE_IMMUNITY = 421354, SPELL_PRIEST_UNFURLING_DARKNESS = 341273, SPELL_PRIEST_UNFURLING_DARKNESS_AURA = 341282, SPELL_PRIEST_UNFURLING_DARKNESS_DEBUFF = 341291, @@ -3525,6 +3528,172 @@ class spell_pri_twist_of_fate : public AuraScript } }; +// 421453 - Ultimate Penitence +class spell_pri_ultimate_penitence : public SpellScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo({ SPELL_PRIEST_ULTIMATE_PENITENCE_CHANNEL, SPELL_PRIEST_ULTIMATE_PENITENCE_IMMUNITY }); + } + + void TriggerImmunity() const + { + Unit* caster = GetCaster(); + caster->CastSpell(caster, SPELL_PRIEST_ULTIMATE_PENITENCE_IMMUNITY, CastSpellExtraArgsInit + { + .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, + .TriggeringSpell = GetSpell() + }); + + int32 preferHealing = 1; + if (Unit const* target = GetExplTargetUnit(); target && !GetCaster()->IsFriendlyTo(target)) + preferHealing = 0; + + caster->m_Events.AddEventAtOffset([caster, originalCastId = GetSpell()->m_originalCastId, preferHealing] + { + caster->CastSpell(caster, SPELL_PRIEST_ULTIMATE_PENITENCE_CHANNEL, CastSpellExtraArgsInit + { + .TriggerFlags = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR, + .OriginalCastId = originalCastId, + .SpellValueOverrides = { { SPELLVALUE_BASE_POINT1, preferHealing } } + }); + }, 250ms); + } + + void Register() override + { + OnCast += SpellCastFn(spell_pri_ultimate_penitence::TriggerImmunity); + } +}; + +// 421453 - Ultimate Penitence (Aura) +class spell_pri_ultimate_penitence_aura : public AuraScript +{ + void CalculateAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated) const + { + canBeRecalculated = false; + Unit* caster = GetCaster(); + if (!caster) + return; + + amount = caster->CountPctFromMaxHealth(GetEffectInfo(EFFECT_0).CalcValue(caster)); + } + + void Register() override + { + DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_pri_ultimate_penitence_aura::CalculateAmount, EFFECT_2, SPELL_AURA_SCHOOL_ABSORB); + } +}; + +// 421434 - Ultimate Penitence (Channel) +class spell_pri_ultimate_penitence_channel : public AuraScript +{ + bool Validate(SpellInfo const* /*spellInfo*/) override + { + return ValidateSpellInfo( + { + SPELL_PRIEST_ULTIMATE_PENITENCE_FALLING_FACING_CONTROL + }) && ValidateSpellEffect( + { + { SPELL_PRIEST_ULTIMATE_PENITENCE_DAMAGE, EFFECT_0 }, + { SPELL_PRIEST_ULTIMATE_PENITENCE_HEAL, EFFECT_0 } + }); + } + + void HandlePeriodic(AuraEffect const* aurEff) const + { + if (aurEff->GetAmount() == 1) // set by spell_pri_ultimate_penitence + (void)(TryHealing() || TryDealingDamage()); + else + (void)(TryDealingDamage() || TryHealing()); + } + + bool TryDealingDamage() const + { + std::list<WorldObject*> enemies = SearchTargetCandidates(SPELL_PRIEST_ULTIMATE_PENITENCE_DAMAGE, TARGET_CHECK_ENEMY); + if (enemies.empty()) + return false; + + GetTarget()->CastSpell(Trinity::Containers::SelectRandomContainerElement(enemies), SPELL_PRIEST_ULTIMATE_PENITENCE_DAMAGE, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR); + return true; + } + + bool TryHealing() const + { + std::list<WorldObject*> allies = SearchTargetCandidates(SPELL_PRIEST_ULTIMATE_PENITENCE_HEAL, TARGET_CHECK_ALLY); + Trinity::Containers::EraseIf(allies, [](WorldObject const* ally) { return !ally->IsUnit() || ally->ToUnit()->IsFullHealth(); }); + if (allies.empty()) + return false; + + Unit* caster = GetTarget(); + + Trinity::SortTargetsWithPriorityRules(allies, 1, GetHealingRules(caster)); + + caster->CastSpell(allies.front(), SPELL_PRIEST_ULTIMATE_PENITENCE_HEAL, TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR); + return true; + } + + std::list<WorldObject*> SearchTargetCandidates(uint32 spellId, SpellTargetCheckTypes checkType) const + { + SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(spellId, GetCastDifficulty()); + SpellEffectInfo const& spellEffect = spellInfo->GetEffect(EFFECT_0); + + std::list<WorldObject*> targets; + if (uint32 containerTypeMask = Spell::GetSearcherTypeMask(spellInfo, spellEffect, TARGET_OBJECT_TYPE_UNIT, spellEffect.ImplicitTargetConditions.get())) + { + Unit* caster = GetTarget(); + + float maxRange = spellInfo->GetMaxRange(true, caster); + + Trinity::WorldObjectSpellAreaTargetCheck check(maxRange, caster, caster, caster, spellInfo, checkType, spellEffect.ImplicitTargetConditions.get(), TARGET_OBJECT_TYPE_UNIT); + Trinity::WorldObjectListSearcher searcher(caster->GetPhaseShift(), targets, check, containerTypeMask); + Spell::SearchTargets(searcher, containerTypeMask, caster, caster, maxRange + EXTRA_CELL_SEARCH_RADIUS); + } + + return targets; + } + + void HandleRemoveEffect(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) const + { + Unit* caster = GetTarget(); + CastSpellExtraArgs args = TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_DONT_REPORT_CAST_ERROR; + + caster->CastSpell(caster, SPELL_PRIEST_ULTIMATE_PENITENCE_IMMUNITY, args); + caster->CastSpell(caster, SPELL_PRIEST_ULTIMATE_PENITENCE_FALLING_FACING_CONTROL, args); + } + + static std::array<Trinity::TargetPriorityRule, 2> GetHealingRules(Unit const* caster) + { + return + { + [](WorldObject const* target) { return target->IsPlayer() || (target->IsCreature() && target->ToCreature()->IsTreatedAsRaidUnit()); }, + [caster](Unit const* target) { return !caster->IsPlayer() || !caster->ToPlayer()->GetGroup() || target->IsInRaidWith(caster); } + }; + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_pri_ultimate_penitence_channel::HandlePeriodic, EFFECT_1, SPELL_AURA_PERIODIC_DUMMY); + AfterEffectRemove += AuraEffectApplyFn(spell_pri_ultimate_penitence_channel::HandleRemoveEffect, EFFECT_0, SPELL_AURA_MECHANIC_IMMUNITY_MASK, AURA_EFFECT_HANDLE_REAL); + } +}; + +// 432154 - Ultimate Penitence (Jump) +class spell_pri_ultimate_penitence_jump : public SpellScript +{ + static constexpr Position JumpOffset = { 0.0f, 0.0f, 5.0f }; + + static void SetDestTarget(SpellScript const&, SpellDestination& dest) + { + dest.RelocateOffset(JumpOffset); + } + + void Register() override + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_pri_ultimate_penitence_jump::SetDestTarget, EFFECT_0, TARGET_DEST_CASTER); + } +}; + // 341273 - Unfurling Darkness // Triggered by 34914 - Vampiric Touch class spell_pri_unfurling_darkness : public SpellScript @@ -3821,6 +3990,9 @@ void AddSC_priest_spell_scripts() RegisterSpellScript(spell_pri_twilight_equilibrium); RegisterSpellScript(spell_pri_twilight_equilibrium_shadow_word_pain); RegisterSpellScript(spell_pri_twist_of_fate); + RegisterSpellAndAuraScriptPair(spell_pri_ultimate_penitence, spell_pri_ultimate_penitence_aura); + RegisterSpellScript(spell_pri_ultimate_penitence_channel); + RegisterSpellScript(spell_pri_ultimate_penitence_jump); RegisterSpellScript(spell_pri_unfurling_darkness); RegisterSpellScript(spell_pri_vampiric_embrace); RegisterSpellScript(spell_pri_vampiric_embrace_target); |
