fix(Scripts/Northrend): Rework 'The Cleansing' quest (#23942)

Co-authored-by: offl <11556157+offl@users.noreply.github.com>
This commit is contained in:
sogladev
2025-11-30 20:51:18 +01:00
committed by GitHub
parent d6e03b45db
commit e58683b78b
4 changed files with 246 additions and 127 deletions

View File

@@ -66,109 +66,6 @@ public:
}
};
// The cleansing
enum TurmoilTexts
{
SAY_TURMOIL_0 = 0,
SAY_TURMOIL_1 = 1,
SAY_TURMOIL_HALF_HP = 2,
SAY_TURMOIL_DEATH = 3,
};
class npc_your_inner_turmoil : public CreatureScript
{
public:
npc_your_inner_turmoil() : CreatureScript("npc_your_inner_turmoil") { }
struct npc_your_inner_turmoilAI : public ScriptedAI
{
npc_your_inner_turmoilAI(Creature* creature) : ScriptedAI(creature) {}
uint32 timer;
short phase;
bool health50;
void Reset() override
{
timer = 0;
phase = 0;
health50 = false;
}
void UpdateAI(uint32 diff) override
{
if (timer >= 6000 && phase < 2)
{
phase++;
setphase(phase);
timer = 0;
}
timer += diff;
DoMeleeAttackIfReady();
}
void DamageTaken(Unit*, uint32& /*damage*/, DamageEffectType /*damagetype*/, SpellSchoolMask /*damageSchoolMask*/) override
{
if (HealthBelowPct(50) && !health50)
{
if (TempSummon const* tempSummon = me->ToTempSummon())
{
if (WorldObject* summoner = tempSummon->GetSummonerUnit())
{
Talk(SAY_TURMOIL_HALF_HP, summoner);
}
}
health50 = true;
}
}
void JustDied(Unit* /*killer*/) override
{
if (TempSummon const* tempSummon = me->ToTempSummon())
{
if (WorldObject* summoner = tempSummon->GetSummonerUnit())
{
Talk(SAY_TURMOIL_DEATH, summoner);
}
}
}
void setphase(short newPhase)
{
Unit* summoner = me->ToTempSummon() ? me->ToTempSummon()->GetSummonerUnit() : nullptr;
if (!summoner || !summoner->IsPlayer())
return;
switch (newPhase)
{
case 1:
Talk(SAY_TURMOIL_0, summoner->ToPlayer());
return;
case 2:
{
Talk(SAY_TURMOIL_1, summoner->ToPlayer());
me->SetLevel(summoner->GetLevel());
me->SetFaction(FACTION_MONSTER);
if (me->GetExactDist(summoner) < 50.0f)
{
me->UpdatePosition(summoner->GetPositionX(), summoner->GetPositionY(), summoner->GetPositionZ(), 0.0f, true);
summoner->CastSpell(me, 50218, true); // clone caster
AttackStart(summoner);
}
}
}
}
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_your_inner_turmoilAI(creature);
}
};
/*######
## npc_apothecary_hanes
######*/
@@ -457,13 +354,145 @@ class spell_hawk_hunting : public SpellScript
}
};
/*######
## Quest 11317, 11322: The Cleansing
######*/
enum TheCleansing
{
SPELL_CLEANSING_SOUL = 43351,
SPELL_SUMMON_INNER_TURMOIL = 50167,
SPELL_RECENT_MEDITATION = 61720,
SPELL_MIRROR_IMAGE_AURA = 50218,
QUEST_THE_CLEANSING_H = 11317,
QUEST_THE_CLEANSING_A = 11322
};
// 43365 - The Cleansing: Shrine Cast
class spell_the_cleansing_shrine_cast : public SpellScript
{
PrepareSpellScript(spell_the_cleansing_shrine_cast);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_RECENT_MEDITATION, SPELL_CLEANSING_SOUL }) &&
sObjectMgr->GetQuestTemplate(QUEST_THE_CLEANSING_H) &&
sObjectMgr->GetQuestTemplate(QUEST_THE_CLEANSING_A);
}
SpellCastResult CheckCast()
{
// Error is correct for quest check but may be not correct for aura and this may be a wrong place to send error
if (Player* target = GetExplTargetUnit()->ToPlayer())
{
if (target->HasAura(SPELL_RECENT_MEDITATION) || (!(target->GetQuestStatus(QUEST_THE_CLEANSING_H) == QUEST_STATUS_INCOMPLETE ||
target->GetQuestStatus(QUEST_THE_CLEANSING_A) == QUEST_STATUS_INCOMPLETE)))
{
Spell::SendCastResult(target, GetSpellInfo(), 0, SPELL_FAILED_FIZZLE);
return SPELL_FAILED_FIZZLE;
}
}
return SPELL_CAST_OK;
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
GetHitUnit()->CastSpell(GetHitUnit(), SPELL_CLEANSING_SOUL, true);
}
void Register() override
{
OnCheckCast += SpellCheckCastFn(spell_the_cleansing_shrine_cast::CheckCast);
OnEffectHitTarget += SpellEffectFn(spell_the_cleansing_shrine_cast::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 43351 - Cleansing Soul
class spell_the_cleansing_cleansing_soul : public AuraScript
{
PrepareAuraScript(spell_the_cleansing_cleansing_soul);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_SUMMON_INNER_TURMOIL, SPELL_RECENT_MEDITATION });
}
void AfterApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
GetTarget()->SetStandState(UNIT_STAND_STATE_SIT);
}
void AfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* target = GetTarget();
target->SetStandState(UNIT_STAND_STATE_STAND);
target->CastSpell(target, SPELL_SUMMON_INNER_TURMOIL, true);
target->CastSpell(target, SPELL_RECENT_MEDITATION, true);
}
void Register() override
{
AfterEffectApply += AuraEffectApplyFn(spell_the_cleansing_cleansing_soul::AfterApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove += AuraEffectRemoveFn(spell_the_cleansing_cleansing_soul::AfterRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
// 50217 - The Cleansing: Script Effect Player Cast Mirror Image
class spell_the_cleansing_mirror_image_script_effect : public SpellScript
{
PrepareSpellScript(spell_the_cleansing_mirror_image_script_effect);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_MIRROR_IMAGE_AURA });
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
GetHitUnit()->CastSpell(GetHitUnit(), SPELL_MIRROR_IMAGE_AURA, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_the_cleansing_mirror_image_script_effect::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
// 50238 - The Cleansing: Your Inner Turmoil's On Death Cast on Master
class spell_the_cleansing_on_death_cast_on_master : public SpellScript
{
PrepareSpellScript(spell_the_cleansing_on_death_cast_on_master);
bool Validate(SpellInfo const* spellInfo) override
{
return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* caster = GetCaster())
if (TempSummon* casterSummon = caster->ToTempSummon())
if (Unit* summoner = casterSummon->GetSummonerUnit())
summoner->CastSpell(summoner, GetSpellInfo()->Effects[EFFECT_0].CalcValue(), true);
}
void Register() override
{
OnEffectHit += SpellEffectFn(spell_the_cleansing_on_death_cast_on_master::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
void AddSC_howling_fjord()
{
new npc_attracted_reef_bull();
new npc_your_inner_turmoil();
new npc_apothecary_hanes();
new npc_plaguehound_tracker();
new npc_razael_and_lyana();
RegisterCreatureAI(npc_rodin_lightning_enabler);
RegisterSpellScript(spell_hawk_hunting);
RegisterSpellScript(spell_the_cleansing_shrine_cast);
RegisterSpellScript(spell_the_cleansing_cleansing_soul);
RegisterSpellScript(spell_the_cleansing_mirror_image_script_effect);
RegisterSpellScript(spell_the_cleansing_on_death_cast_on_master);
}

View File

@@ -5673,6 +5673,29 @@ class spell_gen_bm_on : public SpellScript
}
};
class spell_gen_whisper_to_controller : public SpellScript
{
PrepareSpellScript(spell_gen_whisper_to_controller);
bool Validate(SpellInfo const* spellInfo) override
{
return sObjectMgr->GetBroadcastText(uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()));
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* caster = GetCaster())
if (TempSummon* casterSummon = caster->ToTempSummon())
if (Player* target = casterSummon->GetSummonerUnit()->ToPlayer())
casterSummon->Unit::Whisper(uint32(GetEffectValue()), target, false);
}
void Register() override
{
OnEffectHit += SpellEffectFn(spell_gen_whisper_to_controller::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
void AddSC_generic_spell_scripts()
{
RegisterSpellScript(spell_silithyst);
@@ -5846,4 +5869,5 @@ void AddSC_generic_spell_scripts()
RegisterSpellScript(spell_gen_invis_on);
RegisterSpellScript(spell_gen_bm_on);
RegisterSpellScript(spell_gen_bm_off);
RegisterSpellScript(spell_gen_whisper_to_controller);
}

View File

@@ -247,28 +247,6 @@ class spell_q10525_vision_guide : public AuraScript
}
};
class spell_q11322_q11317_the_cleansing : public AuraScript
{
PrepareAuraScript(spell_q11322_q11317_the_cleansing)
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Unit* ar = GetCaster();
if (ar && ar->ToPlayer())
{
if (ar->ToPlayer()->GetQuestStatus(11317) == QUEST_STATUS_INCOMPLETE || ar->ToPlayer()->GetQuestStatus(11322) == QUEST_STATUS_INCOMPLETE)
ar->SummonCreature(27959, 3032.0f, -5095.0f, 723.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000);
ar->SetStandState(UNIT_STAND_STATE_SIT);
}
}
void Register() override
{
OnEffectApply += AuraEffectApplyFn(spell_q11322_q11317_the_cleansing::HandleEffectApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
};
class spell_q10714_on_spirits_wings : public SpellScript
{
PrepareSpellScript(spell_q10714_on_spirits_wings);
@@ -2499,7 +2477,6 @@ void AddSC_quest_spell_scripts()
RegisterSpellScript(spell_q12014_steady_as_a_rock);
RegisterSpellAndAuraScriptPair(spell_q11026_a11051_banish_the_demons, spell_q11026_a11051_banish_the_demons_aura);
RegisterSpellScript(spell_q10525_vision_guide);
RegisterSpellScript(spell_q11322_q11317_the_cleansing);
RegisterSpellScript(spell_q10714_on_spirits_wings);
RegisterSpellScript(spell_q10720_the_smallest_creature);
RegisterSpellScript(spell_q13086_last_line_of_defence);