aboutsummaryrefslogtreecommitdiff
path: root/src/server/scripts
diff options
context:
space:
mode:
authorCristian Vintila <127750549+cristianvnt@users.noreply.github.com>2025-12-22 00:32:12 +0200
committerGitHub <noreply@github.com>2025-12-21 23:32:12 +0100
commitd22dae08aafaeb8021438dd283fdee110f18d9b2 (patch)
tree3cfc0062ff61e9ae4eabd7c09e36111793c1fbd0 /src/server/scripts
parent161da58cf4040b4fbcd2e0efcb3a961dec202237 (diff)
Scripts/Spells: Implement priest talent Ultimate Penitence (#31444)
Co-authored-by: Shauren <shauren.trinity@gmail.com>
Diffstat (limited to 'src/server/scripts')
-rw-r--r--src/server/scripts/Spells/spell_priest.cpp172
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);