fix(Scripts/Naxxramas): modernise Heigan (#24234)

This commit is contained in:
Dan
2025-12-29 04:47:02 +01:00
committed by GitHub
parent f1dadadfb9
commit 5dbc6e07ba
3 changed files with 118 additions and 154 deletions
@@ -55,33 +55,18 @@ enum Misc
PHASE_FAST_DANCE = 1 PHASE_FAST_DANCE = 1
}; };
class boss_heigan : public CreatureScript float const heiganFastDanceFaceDirection = 2.40f;
struct boss_heigan : public BossAI
{ {
public: boss_heigan(Creature* creature) : BossAI(creature, DATA_HEIGAN_BOSS) { }
boss_heigan() : CreatureScript("boss_heigan") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetNaxxramasAI<boss_heiganAI>(pCreature);
}
struct boss_heiganAI : public BossAI
{
explicit boss_heiganAI(Creature* c) : BossAI(c, BOSS_HEIGAN)
{}
EventMap events;
uint8 currentPhase{};
uint8 currentSection{};
bool moveRight{};
void Reset() override void Reset() override
{ {
BossAI::Reset(); BossAI::Reset();
events.Reset(); _currentPhase = 0;
currentPhase = 0; _currentSection = 3;
currentSection = 3; _moveRight = true;
moveRight = true;
} }
void KilledUnit(Unit* who) override void KilledUnit(Unit* who) override
@@ -109,18 +94,33 @@ public:
void StartFightPhase(uint8 phase) void StartFightPhase(uint8 phase)
{ {
currentSection = 3; _currentSection = 3;
currentPhase = phase; _currentPhase = phase;
events.Reset(); scheduler.CancelAll();
if (phase == PHASE_SLOW_DANCE) if (phase == PHASE_SLOW_DANCE)
{ {
me->CastStop(); me->CastStop();
me->SetReactState(REACT_AGGRESSIVE); me->SetReactState(REACT_AGGRESSIVE);
DoZoneInCombat(); DoZoneInCombat();
events.ScheduleEvent(EVENT_DISRUPTION, 12s, 15s); ScheduleTimedEvent(12s, 15s, [&] {
events.ScheduleEvent(EVENT_DECEPIT_FEVER, 17s); DoCastSelf(SPELL_ERUPTION);
events.ScheduleEvent(EVENT_ERUPT_SECTION, 15s); }, 10s);
events.ScheduleEvent(EVENT_SWITCH_PHASE, 90s); ScheduleTimedEvent(17s, [&] {
DoCastSelf(SPELL_DECREPIT_FEVER);
}, 22s, 25s);
ScheduleTimedEvent(15s, [&] {
instance->SetData(DATA_HEIGAN_ERUPTION, _currentSection);
if (_currentSection == 3)
_moveRight = false;
else if (_currentSection == 0)
_moveRight = true;
_moveRight ? _currentSection++ : _currentSection--;
Talk(SAY_TAUNT);
}, 10s);
scheduler.Schedule(90s, [this](TaskContext /*context*/) {
StartFightPhase(PHASE_FAST_DANCE);
});
} }
else // if (phase == PHASE_FAST_DANCE) else // if (phase == PHASE_FAST_DANCE)
{ {
@@ -130,99 +130,51 @@ public:
me->StopMoving(); me->StopMoving();
me->SetReactState(REACT_PASSIVE); me->SetReactState(REACT_PASSIVE);
me->CastSpell(me, SPELL_TELEPORT_SELF, false); me->CastSpell(me, SPELL_TELEPORT_SELF, false);
me->SetFacingTo(2.40f); me->SetFacingTo(heiganFastDanceFaceDirection);
events.ScheduleEvent(EVENT_PLAGUE_CLOUD, 1s); scheduler.Schedule(1s, [this](TaskContext /*context*/) {
events.ScheduleEvent(EVENT_ERUPT_SECTION, 7s); DoCastSelf(SPELL_PLAGUE_CLOUD);
events.ScheduleEvent(EVENT_SWITCH_PHASE, 45s); });
} ScheduleTimedEvent(7s, [&] {
events.ScheduleEvent(EVENT_SAFETY_DANCE, 5s); instance->SetData(DATA_HEIGAN_ERUPTION, _currentSection);
} if (_currentSection == 3)
_moveRight = false;
else if (_currentSection == 0)
_moveRight = true;
bool IsInRoom(Unit* who) _moveRight ? _currentSection++ : _currentSection--;
{ }, 4s);
if (who->GetPositionX() > 2826 || who->GetPositionX() < 2723 || who->GetPositionY() > -3641 || who->GetPositionY() < -3736) scheduler.Schedule(45s, [this](TaskContext /*context*/) {
{
if (who->GetGUID() == me->GetGUID())
EnterEvadeMode();
return false;
}
return true;
}
void UpdateAI(uint32 diff) override
{
if (!IsInRoom(me))
return;
if (!UpdateVictim())
return;
events.Update(diff);
switch (events.ExecuteEvent())
{
case EVENT_DISRUPTION:
me->CastSpell(me, SPELL_SPELL_DISRUPTION, false);
events.Repeat(10s);
break;
case EVENT_DECEPIT_FEVER:
me->CastSpell(me, SPELL_DECREPIT_FEVER, false);
events.Repeat(22s, 25s);
break;
case EVENT_PLAGUE_CLOUD:
me->CastSpell(me, SPELL_PLAGUE_CLOUD, false);
break;
case EVENT_SWITCH_PHASE:
if (currentPhase == PHASE_SLOW_DANCE)
{
StartFightPhase(PHASE_FAST_DANCE);
}
else
{
StartFightPhase(PHASE_SLOW_DANCE); StartFightPhase(PHASE_SLOW_DANCE);
Talk(EMOTE_DANCE_END); // avoid play the emote on aggro Talk(EMOTE_DANCE_END); // avoid play the emote on aggro
});
} }
break; ScheduleTimedEvent(5s, [&] {
case EVENT_ERUPT_SECTION: CheckSafetyDance();
{ }, 5s);
instance->SetData(DATA_HEIGAN_ERUPTION, currentSection);
if (currentSection == 3)
moveRight = false;
else if (currentSection == 0)
moveRight = true;
moveRight ? currentSection++ : currentSection--;
if (currentPhase == PHASE_SLOW_DANCE)
Talk(SAY_TAUNT);
events.Repeat(currentPhase == PHASE_SLOW_DANCE ? 10s : 4s);
break;
} }
case EVENT_SAFETY_DANCE:
void CheckSafetyDance()
{ {
Map::PlayerList const& pList = me->GetMap()->GetPlayers(); if (Map* map = me->GetMap())
for (auto const& itr : pList)
{ {
if (IsInRoom(itr.GetSource()) && !itr.GetSource()->IsAlive()) map->DoForAllPlayers([&](Player* p)
{
if (IsInBoundary(p) && !p->IsAlive())
{ {
instance->SetData(DATA_DANCE_FAIL, 0); instance->SetData(DATA_DANCE_FAIL, 0);
instance->StorePersistentData(PERSISTENT_DATA_IMMORTAL_FAIL, 1); instance->StorePersistentData(PERSISTENT_DATA_IMMORTAL_FAIL, 1);
return; return;
} }
} });
events.Repeat(5s);
return;
} }
} }
private:
DoMeleeAttackIfReady(); uint8 _currentPhase{};
} uint8 _currentSection{};
}; bool _moveRight{true};
}; };
void AddSC_boss_heigan() void AddSC_boss_heigan()
{ {
new boss_heigan(); RegisterNaxxramasCreatureAI(boss_heigan);
} }
@@ -109,6 +109,7 @@ static ObjectData const creatureData[]
{ NPC_THADDIUS, DATA_THADDIUS_BOSS }, { NPC_THADDIUS, DATA_THADDIUS_BOSS },
{ NPC_RAZUVIOUS, DATA_RAZUVIOUS_BOSS }, { NPC_RAZUVIOUS, DATA_RAZUVIOUS_BOSS },
{ NPC_GOTHIK, DATA_GOTHIK_BOSS }, { NPC_GOTHIK, DATA_GOTHIK_BOSS },
{ NPC_HEIGAN, DATA_HEIGAN_BOSS },
{ NPC_BARON_RIVENDARE, DATA_BARON_RIVENDARE_BOSS }, { NPC_BARON_RIVENDARE, DATA_BARON_RIVENDARE_BOSS },
{ NPC_SIR_ZELIEK, DATA_SIR_ZELIEK_BOSS }, { NPC_SIR_ZELIEK, DATA_SIR_ZELIEK_BOSS },
{ NPC_LADY_BLAUMEUX, DATA_LADY_BLAUMEUX_BOSS }, { NPC_LADY_BLAUMEUX, DATA_LADY_BLAUMEUX_BOSS },
@@ -136,6 +137,12 @@ static ObjectData const gameObjectData[]
{ 0, 0 } { 0, 0 }
}; };
BossBoundaryData const boundaries =
{
{ DATA_HEIGAN_BOSS, new RectangleBoundary(2723.0f, 2826.0f, -3736.0f, -3641.0f) },
{ 0, 0 }
};
class instance_naxxramas : public InstanceScript class instance_naxxramas : public InstanceScript
{ {
public: public:
@@ -146,6 +153,7 @@ public:
SetPersistentDataCount(PERSISTENT_DATA_COUNT); SetPersistentDataCount(PERSISTENT_DATA_COUNT);
LoadDoorData(doorData); LoadDoorData(doorData);
LoadObjectData(creatureData, gameObjectData); LoadObjectData(creatureData, gameObjectData);
LoadBossBoundaries(boundaries);
// GameObjects // GameObjects
for (auto& i : _heiganEruption) for (auto& i : _heiganEruption)
@@ -50,13 +50,14 @@ enum NaxxramasData
DATA_THADDIUS_BOSS = 103, DATA_THADDIUS_BOSS = 103,
DATA_RAZUVIOUS_BOSS = 104, DATA_RAZUVIOUS_BOSS = 104,
DATA_GOTHIK_BOSS = 105, DATA_GOTHIK_BOSS = 105,
DATA_BARON_RIVENDARE_BOSS = 106, DATA_HEIGAN_BOSS = 106,
DATA_SIR_ZELIEK_BOSS = 107, DATA_BARON_RIVENDARE_BOSS = 107,
DATA_LADY_BLAUMEUX_BOSS = 108, DATA_SIR_ZELIEK_BOSS = 108,
DATA_THANE_KORTHAZZ_BOSS = 109, DATA_LADY_BLAUMEUX_BOSS = 109,
DATA_SAPPHIRON_BOSS = 110, DATA_THANE_KORTHAZZ_BOSS = 110,
DATA_KELTHUZAD_BOSS = 111, DATA_SAPPHIRON_BOSS = 111,
DATA_LICH_KING_BOSS = 112, DATA_KELTHUZAD_BOSS = 112,
DATA_LICH_KING_BOSS = 113,
DATA_LOATHEB_PORTAL = 200, DATA_LOATHEB_PORTAL = 200,
DATA_MAEXXNA_PORTAL = 201, DATA_MAEXXNA_PORTAL = 201,
@@ -167,6 +168,9 @@ enum NaxxramasCreatureId
// Gothik // Gothik
NPC_GOTHIK = 16060, NPC_GOTHIK = 16060,
// Heigan the Unclean
NPC_HEIGAN = 15936,
// Four horseman // Four horseman
NPC_BARON_RIVENDARE = 30549, NPC_BARON_RIVENDARE = 30549,
NPC_SIR_ZELIEK = 16063, NPC_SIR_ZELIEK = 16063,