From 324d014bb845437d82c8df7d807cd37f06e55f4a Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Sat, 31 Jan 2026 13:41:21 -0300 Subject: [PATCH] fix(Scripts/EoE): fix Malygos reseting at p3 and other improvements (#24566) --- .../Nexus/EyeOfEternity/boss_malygos.cpp | 65 ++----- .../Nexus/EyeOfEternity/eye_of_eternity.h | 9 +- .../instance_eye_of_eternity.cpp | 162 ++++++++---------- 3 files changed, 97 insertions(+), 139 deletions(-) diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index d77608b47..744b60477 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -188,16 +188,9 @@ enum MalygosLightOverrides LIGHT_OBSCURE_ARCANE_RUNES = 1825, }; -struct boss_malygos : public ScriptedAI +struct boss_malygos : public BossAI { - boss_malygos(Creature* c) : ScriptedAI(c), summons(me) - { - pInstance = me->GetInstanceScript(); - } - - InstanceScript* pInstance; - EventMap events; - SummonList summons; + boss_malygos(Creature* creature) : BossAI(creature, DATA_MALYGOS) { } uint32 timer1, timer2; uint8 IntroCounter; @@ -211,9 +204,7 @@ struct boss_malygos : public ScriptedAI void Reset() override { - events.Reset(); - events.SetPhase(PHASE_NONE); - summons.DespawnAll(); + _Reset(); timer1 = MalygosIntroIntervals[4]; timer2 = INTRO_MOVEMENT_INTERVAL; @@ -226,11 +217,7 @@ struct boss_malygos : public ScriptedAI me->SetAnimTier(AnimTier::Fly); - if (pInstance) - { - pInstance->SetData(DATA_ENCOUNTER_STATUS, NOT_STARTED); - pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_YOU_DONT_HAVE_AN_ENTERNITY_EVENT); - } + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_YOU_DONT_HAVE_AN_ENTERNITY_EVENT); } void MovementInform(uint32 type, uint32 id) override @@ -305,14 +292,10 @@ struct boss_malygos : public ScriptedAI void JustEngagedWith(Unit* /*who*/) override { + _JustEngagedWith(); events.Reset(); - DoZoneInCombat(); - Talk(SAY_PHASE_1); - events.RescheduleEvent(EVENT_INTRO_MOVE_CENTER, 0ms, 1); - if (pInstance) - pInstance->SetData(DATA_ENCOUNTER_STATUS, IN_PROGRESS); } void AttackStart(Unit* victim) override @@ -372,8 +355,7 @@ struct boss_malygos : public ScriptedAI break; case EVENT_INTRO_MOVE_CENTER: { - if (pInstance) - pInstance->SetData(DATA_SET_IRIS_INACTIVE, 0); + instance->SetData(DATA_SET_IRIS_INACTIVE, 0); summons.DespawnAll(); me->InterruptNonMeleeSpells(true); me->RemoveAllAuras(); @@ -392,11 +374,8 @@ struct boss_malygos : public ScriptedAI } case EVENT_START_FIGHT: { - if (pInstance) - { - pInstance->SetData(DATA_HIDE_IRIS_AND_PORTAL, 0); - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_YOU_DONT_HAVE_AN_ENTERNITY_EVENT); - } + instance->SetData(DATA_HIDE_IRIS_AND_PORTAL, 0); + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_YOU_DONT_HAVE_AN_ENTERNITY_EVENT); me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED); if (Unit* target = me->SelectNearestTarget(250.0f)) { @@ -689,19 +668,16 @@ struct boss_malygos : public ScriptedAI me->GetThreatMgr().ClearAllThreat(); // players on vehicle are unattackable -> leads to EnterEvadeMode() because target is not acceptable! - // mount players: - Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); - if (!PlayerList.IsEmpty()) - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player* player = i->GetSource()) - { - sScriptMgr->AnticheatSetUnderACKmount(player); + me->GetMap()->DoForAllPlayers([&](Player* player) + { + if (player->IsAlive() && !player->IsGameMaster()) + { + sScriptMgr->AnticheatSetUnderACKmount(player); + player->CastSpell(player, SPELL_SUMMON_RED_DRAGON_BUDDY, true); + } + }); - if (!player->IsAlive() || player->IsGameMaster()) - continue; - - player->CastSpell(player, SPELL_SUMMON_RED_DRAGON_BUDDY, true); - } + DoZoneInCombat(); events.RescheduleEvent(EVENT_SAY_PHASE_3_INTRO, 3s, 1); } @@ -744,12 +720,9 @@ struct boss_malygos : public ScriptedAI void JustDied(Unit* /*killer*/) override { + _JustDied(); Talk(SAY_DEATH); - if (pInstance) - { - pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, NPC_MALYGOS, 1); - pInstance->SetData(DATA_ENCOUNTER_STATUS, DONE); - } + instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, NPC_MALYGOS, 1); } void KilledUnit(Unit* victim) override diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h index 77a4f7c46..2b3ddfd38 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h @@ -24,6 +24,8 @@ #define DataHeader "EOE" #define EyeOfEternityScriptName "instance_eye_of_eternity" +uint32 const EncounterCount = 1; + enum Objects { GO_NEXUS_PLATFORM = 193070, @@ -52,8 +54,8 @@ enum NPCs enum Data { + DATA_MALYGOS = 0, DATA_IRIS_ACTIVATED, - DATA_ENCOUNTER_STATUS, DATA_SET_IRIS_INACTIVE, DATA_HIDE_IRIS_AND_PORTAL, DATA_MALYGOS_GUID, @@ -87,6 +89,11 @@ enum eAchiev ACHIEV_YOU_DONT_HAVE_AN_ENTERNITY_EVENT = 20387, }; +enum EoEMisc : uint32 +{ + EVENT_IRIS_ACTIVATED = 20158 +}; + /*** POSITIONS/WAYPOINTS BELOW ***/ #define INTRO_MOVEMENT_INTERVAL 25000 diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp index fea436c4b..42788ec50 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp @@ -26,18 +26,10 @@ class instance_eye_of_eternity : public InstanceMapScript public: instance_eye_of_eternity() : InstanceMapScript("instance_eye_of_eternity", MAP_THE_EYE_OF_ETERNITY) { } - InstanceScript* GetInstanceScript(InstanceMap* pMap) const override - { - return new instance_eye_of_eternity_InstanceMapScript(pMap); - } - struct instance_eye_of_eternity_InstanceMapScript : public InstanceScript { instance_eye_of_eternity_InstanceMapScript(Map* pMap) : InstanceScript(pMap) { Initialize(); } - uint32 EncounterStatus; - std::string str_data; - ObjectGuid NPC_MalygosGUID; ObjectGuid GO_IrisGUID; ObjectGuid GO_ExitPortalGUID; @@ -46,34 +38,24 @@ public: void Initialize() override { - EncounterStatus = NOT_STARTED; - + SetHeaders(DataHeader); + SetBossNumber(EncounterCount); bPokeAchiev = false; } - bool IsEncounterInProgress() const override - { - return EncounterStatus == IN_PROGRESS; - } - void OnPlayerEnter(Player* player) override { - if (EncounterStatus == DONE) + if (GetBossState(DATA_MALYGOS) == DONE) { // destroy platform, hide iris (actually ensure, done at loading, but doesn't always work - ProcessEvent(nullptr, 20158); + ProcessEvent(nullptr, EVENT_IRIS_ACTIVATED); if (GameObject* go = instance->GetGameObject(GO_IrisGUID)) if (go->GetPhaseMask() != 2) go->SetPhaseMask(2, true); // no floor, so put players on drakes - if (player) - { - if (!player->IsAlive()) - return; - + if (player && player->IsAlive()) player->CastSpell(player, SPELL_SUMMON_RED_DRAGON_BUDDY, true); - } } } @@ -94,59 +76,34 @@ public: case GO_IRIS_N: case GO_IRIS_H: GO_IrisGUID = go->GetGUID(); + + if (GetBossState(DATA_MALYGOS) == DONE) + go->SetPhaseMask(2, true); break; case GO_EXIT_PORTAL: GO_ExitPortalGUID = go->GetGUID(); break; case GO_NEXUS_PLATFORM: GO_PlatformGUID = go->GetGUID(); + if (GetBossState(DATA_MALYGOS) == DONE) + { + go->ModifyHealth(-6500000); // We have HP 6 million in the database... So we have to do at least that + go->EnableCollision(false); + } break; } } - void SetData(uint32 type, uint32 data) override + void SetData(uint32 type, uint32 /*data*/) override { switch (type) { case DATA_IRIS_ACTIVATED: - if (EncounterStatus == NOT_STARTED) + if (GetBossState(DATA_MALYGOS) == NOT_STARTED) if (Creature* c = instance->GetCreature(NPC_MalygosGUID)) if (Player* plr = c->SelectNearestPlayer(250.0f)) c->AI()->AttackStart(plr); break; - case DATA_ENCOUNTER_STATUS: - EncounterStatus = data; - switch (data) - { - case NOT_STARTED: - bPokeAchiev = false; - if (GameObject* go = instance->GetGameObject(GO_IrisGUID)) - { - go->SetPhaseMask(1, true); - HandleGameObject(GO_IrisGUID, false, go); - } - if (GameObject* go = instance->GetGameObject(GO_ExitPortalGUID)) - go->SetPhaseMask(1, true); - if (GameObject* go = instance->GetGameObject(GO_PlatformGUID)) - { - go->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, nullptr, true); - go->EnableCollision(true); - } - break; - case IN_PROGRESS: - bPokeAchiev = (instance->GetPlayersCountExceptGMs() < (instance->GetSpawnMode() == 0 ? (uint32)9 : (uint32)21)); - break; - case DONE: - bPokeAchiev = false; - if (GameObject* go = instance->GetGameObject(GO_ExitPortalGUID)) - go->SetPhaseMask(1, true); - if (Creature* c = instance->GetCreature(NPC_MalygosGUID)) - if (c->SummonCreature(NPC_ALEXSTRASZA, 798.0f, 1268.0f, 299.0f, 2.45f, TEMPSUMMON_TIMED_DESPAWN, 604800000)) - break; - } - if (data == DONE) - SaveToDB(); - break; case DATA_SET_IRIS_INACTIVE: if (GameObject* go = instance->GetGameObject(GO_IrisGUID)) { @@ -164,6 +121,49 @@ public: } } + bool SetBossState(uint32 type, EncounterState state) override + { + if (!InstanceScript::SetBossState(type, state)) + return false; + + if (type == DATA_MALYGOS) + { + switch (state) + { + case NOT_STARTED: + bPokeAchiev = false; + if (GameObject* go = instance->GetGameObject(GO_IrisGUID)) + { + go->SetPhaseMask(1, true); + HandleGameObject(GO_IrisGUID, false, go); + } + if (GameObject* go = instance->GetGameObject(GO_ExitPortalGUID)) + go->SetPhaseMask(1, true); + if (GameObject* go = instance->GetGameObject(GO_PlatformGUID)) + { + go->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, nullptr, true); + go->EnableCollision(true); + } + break; + case IN_PROGRESS: + bPokeAchiev = (instance->GetPlayersCountExceptGMs() < (instance->GetSpawnMode() == 0 ? (uint32)9 : (uint32)21)); + break; + case DONE: + bPokeAchiev = false; + if (GameObject* go = instance->GetGameObject(GO_ExitPortalGUID)) + go->SetPhaseMask(1, true); + if (Creature* c = instance->GetCreature(NPC_MalygosGUID)) + if (c->SummonCreature(NPC_ALEXSTRASZA, 798.0f, 1268.0f, 299.0f, 2.45f, TEMPSUMMON_TIMED_DESPAWN, 604800000)) + break; + break; + default: + break; + } + } + + return true; + } + ObjectGuid GetGuidData(uint32 type) const override { switch (type) @@ -177,40 +177,13 @@ public: void ProcessEvent(WorldObject* /*unit*/, uint32 eventId) override { - switch (eventId) - { - case 20158: - if (GameObject* go = instance->GetGameObject(GO_PlatformGUID)) - if (Creature* c = instance->GetCreature(NPC_MalygosGUID)) - { - go->ModifyHealth(-6500000, c); // We have HP 6 million in the database... So we have to do at least that - go->EnableCollision(false); - } - break; - } - } - - void ReadSaveDataMore(std::istringstream& data) override - { - data >> EncounterStatus; - - switch (EncounterStatus) - { - case IN_PROGRESS: - EncounterStatus = NOT_STARTED; - break; - case DONE: - // destroy platform, hide iris - ProcessEvent(nullptr, 20158); - if (GameObject* go = instance->GetGameObject(GO_IrisGUID)) - go->SetPhaseMask(2, true); - break; - } - } - - void WriteSaveDataMore(std::ostringstream& data) override - { - data << EncounterStatus; + if (eventId == EVENT_IRIS_ACTIVATED) + if (GameObject* go = instance->GetGameObject(GO_PlatformGUID)) + if (Creature* c = instance->GetCreature(NPC_MalygosGUID)) + { + go->ModifyHealth(-6500000, c); // We have HP 6 million in the database... So we have to do at least that + go->EnableCollision(false); + } } bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* source, Unit const* /*target*/, uint32 /*miscvalue1*/) override @@ -227,6 +200,11 @@ public: return false; } }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const override + { + return new instance_eye_of_eternity_InstanceMapScript(map); + } }; void AddSC_instance_eye_of_eternity()