fix(Scripts/Ulduar): rework Hodir hard mode timer to use Shatter Chest aura (#26910)

This commit is contained in:
Andrew
2026-08-02 12:37:17 -03:00
committed by GitHub
parent 4b5b1f9824
commit aebd62ce82
4 changed files with 37 additions and 32 deletions
@@ -0,0 +1,3 @@
--
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_hodir_shatter_chest', 'spell_hodir_shatter_chest_timer_aura');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES (65272, 'spell_hodir_shatter_chest_timer_aura');
@@ -46,6 +46,7 @@ enum HodirSpellData
SPELL_SAFE_AREA = 65705,
SPELL_SAFE_AREA_TRIGGERED = 62464,
SPELL_SHATTER_CHEST = 62501,
SPELL_SHATTER_CHEST_TIMER = 65272,
SPELL_ICICLE_BOSS_AURA = 62227,
SPELL_ICICLE_TBBA = 63545,
@@ -123,8 +124,6 @@ enum HodirEvents
EVENT_FREEZE = 4,
EVENT_SMALL_ICICLES_ENABLE = 5,
EVENT_HARD_MODE_MISSED = 6,
EVENT_DESPAWN_CHEST = 7,
EVENT_FAIL_HM = 8,
EVENT_TRY_FREE_HELPER = 10,
EVENT_PRIEST_DISPELL_MAGIC = 11,
@@ -258,12 +257,13 @@ struct boss_hodir : public BossAI
void JustEngagedWith(Unit* /*who*/) override
{
me->CastSpell(me, SPELL_BITING_COLD_BOSS_AURA, true);
// Hard mode timer: periodic dummy aura whose tick shatters the Rare Cache (sniffed on retail)
me->CastSpell(me, SPELL_SHATTER_CHEST_TIMER, true);
SmallIcicles(true);
events.Reset();
events.ScheduleEvent(EVENT_FLASH_FREEZE, 48s, 49s);
events.ScheduleEvent(EVENT_FREEZE, 17s, 20s);
events.ScheduleEvent(EVENT_BERSERK, 8min);
events.ScheduleEvent(EVENT_HARD_MODE_MISSED, 3min);
Talk(TEXT_AGGRO);
// Helpers spawn IMMUNE_TO_NPC so idle bosses (e.g. Freya's Ground Tremor, #26330) can't tag
@@ -289,14 +289,13 @@ struct boss_hodir : public BossAI
{
switch (action)
{
case EVENT_FAIL_HM:
case EVENT_HARD_MODE_MISSED:
Talk(TEXT_HM_MISS);
bAchievCacheRare = false;
if (instance)
{
if (GameObject* go = GetHardmodeChest())
{
go->SetGoState(GO_STATE_ACTIVE);
events.ScheduleEvent(EVENT_DESPAWN_CHEST, 3s);
}
me->CastSpell(go, SPELL_SHATTER_CHEST, false);
}
break;
}
@@ -409,21 +408,6 @@ struct boss_hodir : public BossAI
Talk(TEXT_BERSERK);
}
break;
case EVENT_HARD_MODE_MISSED:
{
Talk(TEXT_HM_MISS);
bAchievCacheRare = false;
if (instance)
{
if (GameObject* go = GetHardmodeChest())
me->CastSpell(go, SPELL_SHATTER_CHEST, false);
}
}
break;
case EVENT_DESPAWN_CHEST:
if (instance && instance->GetBossState(BOSS_HODIR) != DONE)
instance->SetData(TYPE_HODIR_HM_FAIL, 0);
break;
case EVENT_FLASH_FREEZE:
{
std::list<Unit*> targets;
@@ -1225,22 +1209,25 @@ struct npc_ulduar_hodir_mage : public ScriptedAI
}
};
class spell_hodir_shatter_chest : public SpellScript
class spell_hodir_shatter_chest_timer_aura : public AuraScript
{
PrepareSpellScript(spell_hodir_shatter_chest);
PrepareAuraScript(spell_hodir_shatter_chest_timer_aura);
void DestroyWinterCache(SpellEffIndex effIndex)
bool Validate(SpellInfo const* /*spellInfo*/) override
{
PreventHitDefaultEffect(effIndex);
return ValidateSpellInfo({ SPELL_SHATTER_CHEST });
}
if (Unit* hodir = GetCaster())
hodir->GetAI()->DoAction(EVENT_FAIL_HM);
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
{
if (Unit* hodir = GetTarget())
hodir->GetAI()->DoAction(EVENT_HARD_MODE_MISSED);
}
void Register() override
{
OnEffectHit += SpellEffectFn(spell_hodir_shatter_chest::DestroyWinterCache, EFFECT_0, SPELL_EFFECT_TRIGGER_MISSILE);
};
OnEffectPeriodic += AuraEffectPeriodicFn(spell_hodir_shatter_chest_timer_aura::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
}
};
class spell_hodir_biting_cold_main_aura : public AuraScript
@@ -1599,7 +1586,7 @@ void AddSC_boss_hodir()
RegisterUlduarCreatureAI(npc_ulduar_hodir_shaman);
RegisterUlduarCreatureAI(npc_ulduar_hodir_mage);
RegisterSpellScript(spell_hodir_shatter_chest);
RegisterSpellScript(spell_hodir_shatter_chest_timer_aura);
RegisterSpellScript(spell_hodir_biting_cold_main_aura);
RegisterSpellScript(spell_hodir_biting_cold_player_aura);
RegisterSpellScript(spell_hodir_periodic_icicle);
@@ -326,6 +326,18 @@ public:
// destory towers
if (eventId >= EVENT_TOWER_OF_LIFE_DESTROYED && eventId <= EVENT_TOWER_OF_FLAMES_DESTROYED)
SetData(eventId, 0);
else if (eventId == EVENT_HODIR_SHATTER_CHEST)
{
if (GameObject* go = GetHodirChest(true))
{
go->SetGoState(GO_STATE_ACTIVE);
scheduler.Schedule(3s, [this](TaskContext /*context*/)
{
if (GetBossState(BOSS_HODIR) != DONE)
SetData(TYPE_HODIR_HM_FAIL, 0);
});
}
}
}
bool SetBossState(uint32 type, EncounterState state) override
@@ -356,6 +356,9 @@ enum UlduarMisc
EVENT_TOWER_OF_FLAMES_DESTROYED = 21033,
EVENT_TOWER_OF_LIFE_DESTROYED = 21030,
// Sent by Shatter Chest (62502), triggered by Hodir's hard mode timer missile (62501)
EVENT_HODIR_SHATTER_CHEST = 20907,
ACTION_LEVIATHAN_REFRESH_TOWERS = -1,
ACTION_TOWER_OF_STORM_DESTROYED = 1,
ACTION_TOWER_OF_FROST_DESTROYED = 2,