From 4c1e559f5428e0fc7672d17bc96e26578472f0ed Mon Sep 17 00:00:00 2001 From: Andrew <47818697+Nyeriah@users.noreply.github.com> Date: Tue, 10 Feb 2026 00:27:18 -0300 Subject: [PATCH] refactor(Scripts/EoE): Modernize scripts (#24634) --- .../Nexus/EyeOfEternity/boss_malygos.cpp | 530 ++++++++---------- .../Nexus/EyeOfEternity/eye_of_eternity.h | 26 +- .../instance_eye_of_eternity.cpp | 325 +++++------ 3 files changed, 402 insertions(+), 479 deletions(-) diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 744b60477..1ed35c6e6 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -17,6 +17,7 @@ #include "CombatAI.h" #include "CreatureScript.h" +#include "GameObjectAI.h" #include "GameObjectScript.h" #include "MoveSplineInit.h" #include "Opcodes.h" @@ -177,7 +178,6 @@ enum Phases #define MAX_NEXUS_LORDS DUNGEON_MODE(2, 4) #define MAX_SCIONS_OF_ETERNITY DUNGEON_MODE(4, 8) -#define AREA_EYE_OF_ETERNITY 4500 enum MalygosLightOverrides { @@ -211,6 +211,7 @@ struct boss_malygos : public BossAI IntroCounter = 0; bLockHealthCheck = false; + SetInvincibility(true); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED); me->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE); @@ -222,72 +223,70 @@ struct boss_malygos : public BossAI void MovementInform(uint32 type, uint32 id) override { - if (type == POINT_MOTION_TYPE) - { - switch (id) - { - case MI_POINT_INTRO_SIDE_0: - case MI_POINT_INTRO_SIDE_1: - case MI_POINT_INTRO_SIDE_2: - case MI_POINT_INTRO_SIDE_3: - { - float angle = me->GetOrientation(); - float dist = 75.0f; - if (Creature* c = me->SummonCreature(NPC_PORTAL, me->GetPositionX() + cos(angle) * dist, me->GetPositionY() + std::sin(angle) * dist, me->GetPositionZ(), FourSidesPos[id].GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 13000)) - me->CastSpell(c, SPELL_PORTAL_BEAM, false); - timer2 = INTRO_MOVEMENT_INTERVAL - 10000; - } - break; + if (type != POINT_MOTION_TYPE) + return; - case MI_POINT_INTRO_CENTER_AIR: - events.RescheduleEvent(EVENT_INTRO_LAND, 0ms, 1); - break; - case MI_POINT_VORTEX_CENTER: - if (Creature* c = me->SummonCreature(NPC_WORLD_TRIGGER_LAOI, CenterPos, TEMPSUMMON_TIMED_DESPAWN, 15000)) - c->CastSpell(c, SPELL_VORTEX_VISUAL, true); - events.RescheduleEvent(EVENT_START_VORTEX_REAL, 1s, 1); - break; - case MI_POINT_CENTER_GROUND_PH_2: - events.RescheduleEvent(EVENT_START_PHASE_2_FLY_UP, 0ms, 1); - break; - case MI_POINT_CIRCLE_OUTSIDE_PH_2: - events.RescheduleEvent(EVENT_RESUME_FLYING_CIRCLES_PH_2, 0ms, 1); - break; - case MI_POINT_SURGE_OF_POWER_CENTER: - events.RescheduleEvent(EVENT_SURGE_OF_POWER_WARNING, 0ms, 1); - break; - case MI_POINT_INTRO_LAND: - me->SetDisableGravity(false); - events.RescheduleEvent(EVENT_START_FIGHT, 0ms, 1); - break; - case MI_POINT_VORTEX_TAKEOFF: - events.RescheduleEvent(EVENT_VORTEX_FLY_TO_CENTER, 0ms, 1); - break; - case MI_POINT_VORTEX_LAND: - me->SetDisableGravity(false); - events.RescheduleEvent(EVENT_VORTEX_LAND_1, 0ms, 1); - break; - case MI_POINT_CENTER_AIR_PH_2: - me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_ARCANE_RUNES, 5s); - break; - case MI_POINT_PH_3_FIGHT_POSITION: - events.RescheduleEvent(EVENT_START_PHASE_3, 6s, 1); - break; - } + switch (id) + { + case MI_POINT_INTRO_SIDE_0: + case MI_POINT_INTRO_SIDE_1: + case MI_POINT_INTRO_SIDE_2: + case MI_POINT_INTRO_SIDE_3: + { + float angle = me->GetOrientation(); + float dist = 75.0f; + if (Creature* c = me->SummonCreature(NPC_PORTAL, me->GetPositionX() + cos(angle) * dist, me->GetPositionY() + std::sin(angle) * dist, me->GetPositionZ(), FourSidesPos[id].GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 13000)) + me->CastSpell(c, SPELL_PORTAL_BEAM, false); + timer2 = INTRO_MOVEMENT_INTERVAL - 10000; + } + break; + + case MI_POINT_INTRO_CENTER_AIR: + events.RescheduleEvent(EVENT_INTRO_LAND, 0ms, 1); + break; + case MI_POINT_VORTEX_CENTER: + if (Creature* c = me->SummonCreature(NPC_WORLD_TRIGGER_LAOI, CenterPos, TEMPSUMMON_TIMED_DESPAWN, 15000)) + c->CastSpell(c, SPELL_VORTEX_VISUAL, true); + events.RescheduleEvent(EVENT_START_VORTEX_REAL, 1s, 1); + break; + case MI_POINT_CENTER_GROUND_PH_2: + events.RescheduleEvent(EVENT_START_PHASE_2_FLY_UP, 0ms, 1); + break; + case MI_POINT_CIRCLE_OUTSIDE_PH_2: + events.RescheduleEvent(EVENT_RESUME_FLYING_CIRCLES_PH_2, 0ms, 1); + break; + case MI_POINT_SURGE_OF_POWER_CENTER: + events.RescheduleEvent(EVENT_SURGE_OF_POWER_WARNING, 0ms, 1); + break; + case MI_POINT_INTRO_LAND: + me->SetDisableGravity(false); + events.RescheduleEvent(EVENT_START_FIGHT, 0ms, 1); + break; + case MI_POINT_VORTEX_TAKEOFF: + events.RescheduleEvent(EVENT_VORTEX_FLY_TO_CENTER, 0ms, 1); + break; + case MI_POINT_VORTEX_LAND: + me->SetDisableGravity(false); + events.RescheduleEvent(EVENT_VORTEX_LAND_1, 0ms, 1); + break; + case MI_POINT_CENTER_AIR_PH_2: + me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_ARCANE_RUNES, 5s); + break; + case MI_POINT_PH_3_FIGHT_POSITION: + events.RescheduleEvent(EVENT_START_PHASE_3, 6s, 1); + break; } } void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { - if (spell->Id == SPELL_POWER_SPARK_MALYGOS_BUFF) - { - if (!bLockHealthCheck) - { - Talk(SAY_BUFFED_BY_SPARK); - } - else - me->RemoveAura(SPELL_POWER_SPARK_MALYGOS_BUFF); - } + if (spell->Id != SPELL_POWER_SPARK_MALYGOS_BUFF) + return; + + if (!bLockHealthCheck) + Talk(SAY_BUFFED_BY_SPARK); + else + me->RemoveAura(SPELL_POWER_SPARK_MALYGOS_BUFF); } void JustEngagedWith(Unit* /*who*/) override @@ -317,13 +316,9 @@ struct boss_malygos : public BossAI } } - void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override + void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask) override { - if (damage >= me->GetHealth() && !me->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE)) // allow dying only in phase 3! - { - damage = 0; - return; - } + BossAI::DamageTaken(attacker, damage, damagetype, damageSchoolMask); if (!bLockHealthCheck && me->HealthBelowPctDamaged(50, damage)) { @@ -351,7 +346,6 @@ struct boss_malygos : public BossAI case EVENT_BERSERK: me->CastSpell(me, SPELL_BERSERK, true); Talk(EMOTE_BERSERK); - break; case EVENT_INTRO_MOVE_CENTER: { @@ -368,10 +362,8 @@ struct boss_malygos : public BossAI break; } case EVENT_INTRO_LAND: - { me->GetMotionMaster()->MovePoint(MI_POINT_INTRO_LAND, me->GetPositionX(), me->GetPositionY(), CenterPos.GetPositionZ(), FORCED_MOVEMENT_RUN, 0.f, 0.f, true, true, MOTION_SLOT_ACTIVE, AnimTier::Ground); break; - } case EVENT_START_FIGHT: { instance->SetData(DATA_HIDE_IRIS_AND_PORTAL, 0); @@ -406,7 +398,7 @@ struct boss_malygos : public BossAI c->CastSpell(c, SPELL_PORTAL_BEAM, false); if (Creature* c = me->SummonCreature(NPC_POWER_SPARK, FourSidesPos[random], TEMPSUMMON_MANUAL_DESPAWN, 0)) { - c->AI()->DoAction(1); + c->AI()->DoAction(ACTION_POWER_SPARK_FOLLOW); c->AI()->Talk(EMOTE_POWER_SPARK); } @@ -418,7 +410,7 @@ struct boss_malygos : public BossAI bLockHealthCheck = true; Talk(SAY_MAGIC_BLAST); EntryCheckPredicate pred(NPC_POWER_SPARK); - summons.DoAction(2, pred); // stop following + summons.DoAction(ACTION_POWER_SPARK_STOP, pred); me->SetUnitFlag(UNIT_FLAG_PACIFIED); me->SendMeleeAttackStop(me->GetVictim()); @@ -452,52 +444,49 @@ struct boss_malygos : public BossAI { vp->SetDisableGravity(true); - Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); - if (!PlayerList.IsEmpty()) - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player* pPlayer = i->GetSource()) + me->GetMap()->DoForAllPlayers([&](Player* pPlayer) + { + if (!pPlayer->IsAlive() || pPlayer->IsGameMaster()) + return; + + Position plrpos; + float playerAngle = CenterPos.GetAngle(pPlayer); + plrpos.m_positionX = CenterPos.GetPositionX() + cos(playerAngle) * 5.0f; + plrpos.m_positionY = CenterPos.GetPositionY() + std::sin(playerAngle) * 5.0f; + plrpos.m_positionZ = CenterPos.GetPositionZ() + 18.0f; + plrpos.SetOrientation(plrpos.GetAngle(&CenterPos)); + + if (Creature* c = me->SummonCreature(NPC_VORTEX, plrpos, TEMPSUMMON_TIMED_DESPAWN, 15000)) + { + pPlayer->CastSpell(pPlayer, SPELL_FREEZE_ANIM, true); + pPlayer->CastSpell(c, SPELL_VORTEX_CONTROL_VEHICLE, true); + if (!pPlayer->GetVehicle()) // didn't work somehow, try again with a different way, if fails - break { - if (!pPlayer->IsAlive() || pPlayer->IsGameMaster()) - continue; - - Position plrpos; - float playerAngle = CenterPos.GetAngle(pPlayer); - plrpos.m_positionX = CenterPos.GetPositionX() + cos(playerAngle) * 5.0f; - plrpos.m_positionY = CenterPos.GetPositionY() + std::sin(playerAngle) * 5.0f; - plrpos.m_positionZ = CenterPos.GetPositionZ() + 18.0f; - plrpos.SetOrientation(plrpos.GetAngle(&CenterPos)); - - if (Creature* c = me->SummonCreature(NPC_VORTEX, plrpos, TEMPSUMMON_TIMED_DESPAWN, 15000)) - { - pPlayer->CastSpell(pPlayer, SPELL_FREEZE_ANIM, true); - pPlayer->CastSpell(c, SPELL_VORTEX_CONTROL_VEHICLE, true); - if (!pPlayer->GetVehicle()) // didn't work somehow, try again with a different way, if fails - break - { - pPlayer->EnterVehicle(c, 0); - if (!pPlayer->GetVehicle()) - continue; - } - //pPlayer->ClearUnitState(UNIT_STATE_ONVEHICLE); - - Movement::MoveSplineInit init(pPlayer); // TODO: has to be removed and handled with vehicle exit and vehicle enter code - init.MoveTo(CenterPos.GetPositionX(), CenterPos.GetPositionY(), CenterPos.GetPositionZ()); - init.SetFacing(pPlayer->GetOrientation()); - init.SetTransportExit(); - init.Launch(); - - pPlayer->SetUnitMovementFlags(MOVEMENTFLAG_NONE); - pPlayer->SetDisableGravity(true); - - WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8); - data << pPlayer->GetPackGUID(); - pPlayer->SendMessageToSet(&data, true); - - sScriptMgr->AnticheatSetUnderACKmount(pPlayer); - - pPlayer->SetGuidValue(PLAYER_FARSIGHT, vp->GetGUID()); - c->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); - } + pPlayer->EnterVehicle(c, 0); + if (!pPlayer->GetVehicle()) + return; } + //pPlayer->ClearUnitState(UNIT_STATE_ONVEHICLE); + + Movement::MoveSplineInit init(pPlayer); // TODO: has to be removed and handled with vehicle exit and vehicle enter code + init.MoveTo(CenterPos.GetPositionX(), CenterPos.GetPositionY(), CenterPos.GetPositionZ()); + init.SetFacing(pPlayer->GetOrientation()); + init.SetTransportExit(); + init.Launch(); + + pPlayer->SetUnitMovementFlags(MOVEMENTFLAG_NONE); + pPlayer->SetDisableGravity(true); + + WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8); + data << pPlayer->GetPackGUID(); + pPlayer->SendMessageToSet(&data, true); + + sScriptMgr->AnticheatSetUnderACKmount(pPlayer); + + pPlayer->SetGuidValue(PLAYER_FARSIGHT, vp->GetGUID()); + c->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + } + }); } events.RescheduleEvent(EVENT_VORTEX_LAND_0, 11s, 1); @@ -505,19 +494,14 @@ struct boss_malygos : public BossAI } case EVENT_VORTEX_LAND_0: me->GetMotionMaster()->MovePoint(MI_POINT_VORTEX_LAND, CenterPos, FORCED_MOVEMENT_RUN, 0.f, true, true, AnimTier::Ground); - break; case EVENT_VORTEX_LAND_1: { bLockHealthCheck = false; EntryCheckPredicate pred(NPC_POWER_SPARK); - summons.DoAction(1, pred); // resume following + summons.DoAction(ACTION_POWER_SPARK_FOLLOW, pred); me->RemoveUnitFlag(UNIT_FLAG_PACIFIED); - if (Unit* target = me->GetVictim()) - { - AttackStart(target); - me->GetMotionMaster()->MoveChase(target); - } + me->ResumeChasingVictim(); events.RescheduleEvent(EVENT_START_VORTEX_0, 60s, 1); break; } @@ -533,7 +517,6 @@ struct boss_malygos : public BossAI events.CancelEventGroup(1); // don't cancel berserk (group 0) break; case EVENT_START_PHASE_2_FLY_UP: - { me->SendMeleeAttackStop(me->GetVictim()); me->GetMotionMaster()->MoveIdle(); me->DisableSpline(); @@ -541,7 +524,6 @@ struct boss_malygos : public BossAI me->GetMotionMaster()->MovePoint(MI_POINT_CENTER_AIR_PH_2, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 32.0f, FORCED_MOVEMENT_RUN, 0.f, 0.f, true, true, MOTION_SLOT_ACTIVE, AnimTier::Fly); events.RescheduleEvent(EVENT_START_PHASE_2_MOVE_TO_SIDE, 22s + 500ms, 1); break; - } case EVENT_START_PHASE_2_MOVE_TO_SIDE: Talk(SAY_PHASE_2); me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED); @@ -559,7 +541,7 @@ struct boss_malygos : public BossAI if (Creature* c = me->SummonCreature(NPC_NEXUS_LORD, *disk, TEMPSUMMON_MANUAL_DESPAWN, 0)) { c->EnterVehicle(disk, 0); - disk->AI()->DoAction(1); // start moving + disk->AI()->DoAction(ACTION_DISK_START_MOVING); } } for (int i = 0; i < MAX_SCIONS_OF_ETERNITY; i++) @@ -570,7 +552,7 @@ struct boss_malygos : public BossAI if (Creature* c = me->SummonCreature(NPC_SCION_OF_ETERNITY, *disk, TEMPSUMMON_MANUAL_DESPAWN, 0)) { c->EnterVehicle(disk, 0); - disk->AI()->DoAction(1); // start moving + disk->AI()->DoAction(ACTION_DISK_START_MOVING); } } @@ -628,7 +610,6 @@ struct boss_malygos : public BossAI me->SetTarget(); break; case EVENT_CHECK_TRASH_DEAD: - { if (me->FindNearestCreature(NPC_SCION_OF_ETERNITY, 250.0f, true) || me->FindNearestCreature(NPC_NEXUS_LORD, 250.0f, true)) events.Repeat(3s); else @@ -646,8 +627,7 @@ struct boss_malygos : public BossAI events.RescheduleEvent(EVENT_LIGHT_DIMENSION_CHANGE, 1s, 1); events.RescheduleEvent(EVENT_DESTROY_PLATFORM_0, 10s, 1); } - } - break; + break; case EVENT_LIGHT_DIMENSION_CHANGE: me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_CHANGE_DIMENSIONS, 2s); break; @@ -687,6 +667,7 @@ struct boss_malygos : public BossAI break; case EVENT_START_PHASE_3: events.SetPhase(PHASE_THREE); + SetInvincibility(false); me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_OBSCURE_ARCANE_RUNES, 1s); me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); me->SetUnitFlag(UNIT_FLAG_PACIFIED | UNIT_FLAG_DISABLE_MOVE); @@ -800,18 +781,17 @@ struct boss_malygos : public BossAI #define VORTEX_DEFAULT_DIFF 250 #define VORTEX_TRAVEL_TIME 3000 -//#define VORTEX_RADIUS 25.0f struct npc_vortex_ride : public VehicleAI { npc_vortex_ride(Creature* pCreature) : VehicleAI(pCreature) { - VORTEX_RADIUS = urand(22, 28); + vortexRadius = urand(22, 28); float h = urand(15, 30); float angle = CenterPos.GetAngle(me); Position pos; - pos.m_positionX = CenterPos.GetPositionX() + VORTEX_RADIUS * cos(angle); - pos.m_positionY = CenterPos.GetPositionY() + VORTEX_RADIUS * std::sin(angle); + pos.m_positionX = CenterPos.GetPositionX() + vortexRadius * cos(angle); + pos.m_positionY = CenterPos.GetPositionY() + vortexRadius * std::sin(angle); pos.m_positionZ = CenterPos.GetPositionZ() + h; pos.SetOrientation(pos.GetAngle(&CenterPos)); me->SetPosition(pos); @@ -823,29 +803,26 @@ struct npc_vortex_ride : public VehicleAI uint32 timer; uint32 despawnTimer; bool bUpdatedFlying; - float VORTEX_RADIUS; + float vortexRadius; void PassengerBoarded(Unit* pass, int8 /*seat*/, bool apply) override { - if (pass && !apply && pass->IsPlayer()) - { - Player* plr = pass->ToPlayer(); - float speed = plr->GetDistance(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()) / (1.0f * 0.001f); - plr->SetDisableGravity(false); // packet only would lead to issues elsewhere - plr->GetMotionMaster()->MoveCharge(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), speed); - plr->RemoveAura(SPELL_FREEZE_ANIM); - plr->SetGuidValue(PLAYER_FARSIGHT, ObjectGuid::Empty); + if (!pass || apply || !pass->IsPlayer()) + return; - sScriptMgr->AnticheatSetCanFlybyServer(plr, false); - sScriptMgr->AnticheatSetUnderACKmount(plr); - } + Player* plr = pass->ToPlayer(); + float speed = plr->GetDistance(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()) / (1.0f * 0.001f); + plr->SetDisableGravity(false); // packet only would lead to issues elsewhere + plr->GetMotionMaster()->MoveCharge(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), speed); + plr->RemoveAura(SPELL_FREEZE_ANIM); + plr->SetGuidValue(PLAYER_FARSIGHT, ObjectGuid::Empty); + + sScriptMgr->AnticheatSetCanFlybyServer(plr, false); + sScriptMgr->AnticheatSetUnderACKmount(plr); } void UpdateAI(uint32 diff) override { - /* here: if player has some aura that should make him exit vehicle (eg. ice block) -> exit - or make it another way (dunno how) */ - if (despawnTimer <= diff) { despawnTimer = 0; @@ -865,21 +842,23 @@ struct npc_vortex_ride : public VehicleAI float newangle = angle + 2 * M_PI / ((float)VORTEX_TRAVEL_TIME / VORTEX_DEFAULT_DIFF); if (newangle >= 2 * M_PI) newangle -= 2 * M_PI; - float newx = CenterPos.GetPositionX() + VORTEX_RADIUS * cos(newangle); - float newy = CenterPos.GetPositionY() + VORTEX_RADIUS * std::sin(newangle); + float newx = CenterPos.GetPositionX() + vortexRadius * cos(newangle); + float newy = CenterPos.GetPositionY() + vortexRadius * std::sin(newangle); float arcangle = me->GetAngle(newx, newy); float dist = 2 * me->GetDistance2d(newx, newy); - if (me->GetVehicleKit()) if (Unit* pass = me->GetVehicleKit()->GetPassenger(0)) if (Player* plr = pass->ToPlayer()) - { - if (!bUpdatedFlying && timer) - { - bUpdatedFlying = true; - plr->SetDisableGravity(true); - } + if (me->GetVehicleKit()) + if (Unit* pass = me->GetVehicleKit()->GetPassenger(0)) + if (Player* plr = pass->ToPlayer()) + { + if (!bUpdatedFlying && timer) + { + bUpdatedFlying = true; + plr->SetDisableGravity(true); + } - plr->SendMonsterMove(me->GetPositionX() + dist * cos(arcangle), me->GetPositionY() + dist * std::sin(arcangle), me->GetPositionZ(), VORTEX_DEFAULT_DIFF * 2, SPLINEFLAG_FLYING); - me->Relocate(newx, newy); - } + plr->SendMonsterMove(me->GetPositionX() + dist * cos(arcangle), me->GetPositionY() + dist * std::sin(arcangle), me->GetPositionZ(), VORTEX_DEFAULT_DIFF * 2, SPLINEFLAG_FLYING); + me->Relocate(newx, newy); + } timer = (diff - timer <= VORTEX_DEFAULT_DIFF) ? VORTEX_DEFAULT_DIFF - (diff - timer) : 0; } @@ -910,10 +889,10 @@ struct npc_power_spark : public NullCreatureAI { switch (param) { - case 1: + case ACTION_POWER_SPARK_FOLLOW: MoveTimer = 1; break; - case 2: + case ACTION_POWER_SPARK_STOP: MoveTimer = 0; me->GetMotionMaster()->MoveIdle(); me->DisableSpline(); @@ -924,21 +903,21 @@ struct npc_power_spark : public NullCreatureAI void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override { - if (damage >= me->GetHealth()) - { - damage = 0; - if (!me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) - { - MoveTimer = 0; - me->GetMotionMaster()->MoveIdle(); - me->DisableSpline(); - me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), CenterPos.GetPositionZ(), FORCED_MOVEMENT_NONE, 100.0f); - me->ReplaceAllUnitFlags(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); - me->RemoveAura(SPELL_POWER_SPARK_VISUAL); - me->CastSpell(me, SPELL_POWER_SPARK_GROUND_BUFF, true); - me->DespawnOrUnsummon(60s); - } - } + if (damage < me->GetHealth()) + return; + + damage = 0; + if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) + return; + + MoveTimer = 0; + me->GetMotionMaster()->MoveIdle(); + me->DisableSpline(); + me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), CenterPos.GetPositionZ(), FORCED_MOVEMENT_NONE, 100.0f); + me->ReplaceAllUnitFlags(UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); + me->RemoveAura(SPELL_POWER_SPARK_VISUAL); + me->CastSpell(me, SPELL_POWER_SPARK_GROUND_BUFF, true); + me->DespawnOrUnsummon(60s); } void UpdateAI(uint32 diff) override @@ -981,22 +960,24 @@ struct npc_nexus_lord : public ScriptedAI npc_nexus_lord(Creature* pCreature) : ScriptedAI(pCreature) { me->SetReactState(REACT_PASSIVE); - pInstance = me->GetInstanceScript(); timer = 0; - events.Reset(); - events.RescheduleEvent(EVENT_TELEPORT_VISUAL, 0ms); + me->CastSpell(me, SPELL_TELEPORT_VISUAL, true); } - InstanceScript* pInstance; - EventMap events; uint16 timer; void JustEngagedWith(Unit* /*who*/) override { DoZoneInCombat(); - events.Reset(); - events.RescheduleEvent(EVENT_NEXUS_LORD_ARCANE_SHOCK, 3s, 10s); - events.RescheduleEvent(EVENT_NEXUS_LORD_HASTE, 8s, 14s); + ScheduleTimedEvent(3s, 10s, [&] + { + if (Unit* victim = me->GetVictim()) + me->CastSpell(victim, SPELL_ARCANE_SHOCK); + }, 10s, 15s); + ScheduleTimedEvent(8s, 14s, [&] + { + me->CastSpell(me, SPELL_HASTE); + }, 20s, 30s); } void AttackStart(Unit* victim) override @@ -1025,28 +1006,10 @@ struct npc_nexus_lord : public ScriptedAI timer -= diff; } - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) + scheduler.Update(diff, [this] { - case 0: - break; - case EVENT_TELEPORT_VISUAL: - me->CastSpell(me, SPELL_TELEPORT_VISUAL, true); - break; - case EVENT_NEXUS_LORD_ARCANE_SHOCK: - if (Unit* victim = me->GetVictim()) - me->CastSpell(victim, SPELL_ARCANE_SHOCK); - events.Repeat(10s, 15s); - break; - case EVENT_NEXUS_LORD_HASTE: - me->CastSpell(me, SPELL_HASTE); - events.Repeat(20s, 30s); - break; - } + return me->HasUnitState(UNIT_STATE_CASTING); + }); DoMeleeAttackIfReady(); } @@ -1063,53 +1026,27 @@ struct npc_scion_of_eternity : public ScriptedAI npc_scion_of_eternity(Creature* pCreature) : ScriptedAI(pCreature) { me->SetReactState(REACT_PASSIVE); - pInstance = me->GetInstanceScript(); - events.Reset(); - events.RescheduleEvent(EVENT_TELEPORT_VISUAL, 0ms); - events.RescheduleEvent(EVENT_SCION_OF_ETERNITY_ARCANE_BARRAGE, 20s, 25s); - } - - InstanceScript* pInstance; - EventMap events; - - void UpdateAI(uint32 diff) override - { - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case 0: - break; - case EVENT_TELEPORT_VISUAL: - me->CastSpell(me, SPELL_TELEPORT_VISUAL, true); - break; - case EVENT_SCION_OF_ETERNITY_ARCANE_BARRAGE: + me->CastSpell(me, SPELL_TELEPORT_VISUAL, true); + ScheduleTimedEvent(20s, 25s, [&] { GuidVector guids; - Map::PlayerList const& PlayerList = me->GetMap()->GetPlayers(); - if (!PlayerList.IsEmpty()) - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player* pPlayer = i->GetSource()) - { - if (pPlayer->IsAlive()) - { - if (!pPlayer->GetVehicle()) - { - guids.push_back(pPlayer->GetGUID()); - } - } - } + me->GetMap()->DoForAllPlayers([&](Player* pPlayer) + { + if (pPlayer->IsAlive() && !pPlayer->GetVehicle()) + guids.push_back(pPlayer->GetGUID()); + }); if (!guids.empty()) if (Player* plr = ObjectAccessor::GetPlayer(*me, guids.at(urand(0, guids.size() - 1)))) me->CastSpell(plr, SPELL_SCION_ARCANE_BARRAGE); + }, 5s, 8s); + } - events.Repeat(5s, 8s); - } - break; - } + void UpdateAI(uint32 diff) override + { + scheduler.Update(diff, [this] + { + return me->HasUnitState(UNIT_STATE_CASTING); + }); } void JustDied(Unit* killer) override @@ -1130,11 +1067,9 @@ struct npc_hover_disk : public VehicleAI { npc_hover_disk(Creature* pCreature) : VehicleAI(pCreature) { - pInstance = me->GetInstanceScript(); events.Reset(); } - InstanceScript* pInstance; EventMap events; void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override @@ -1209,7 +1144,7 @@ struct npc_hover_disk : public VehicleAI { switch (param) { - case 1: // move to next point + case ACTION_DISK_START_MOVING: if (Vehicle* v = me->GetVehicleKit()) if (Unit* pass = v->GetPassenger(0)) switch (pass->GetEntry()) @@ -1248,7 +1183,7 @@ struct npc_hover_disk : public VehicleAI case 0: break; case EVENT_DISK_MOVE_NEXT_POINT: - DoAction(1); + DoAction(ACTION_DISK_START_MOVING); break; } } @@ -1261,48 +1196,37 @@ struct npc_alexstrasza : public ScriptedAI { npc_alexstrasza(Creature* pCreature) : ScriptedAI(pCreature) { - events.Reset(); - events.ScheduleEvent(1, 9s); me->SetCanFly(true); me->SetDisableGravity(true); - } - EventMap events; + ScheduleUniqueTimedEvent(9s, [&] + { + me->CastSpell(AlexstraszaGiftPos.GetPositionX(), AlexstraszaGiftPos.GetPositionY(), AlexstraszaGiftPos.GetPositionZ(), SPELL_ALEXSTRASZA_GIFT, true); + if (GameObject* chest = me->SummonGameObject(ALEXSTRASZA_GIFT, AlexstraszaGiftPos.GetPositionX(), AlexstraszaGiftPos.GetPositionY(), AlexstraszaGiftPos.GetPositionZ(), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0)) + chest->SetLootRecipient(me->GetMap()); + + if (GameObject* heart = me->SummonGameObject(HEART_OF_MAGIC, HeartOfMagicPos.GetPositionX(), HeartOfMagicPos.GetPositionY(), HeartOfMagicPos.GetPositionZ(), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0)) + heart->SetLootRecipient(me->GetMap()); + + Talk(SAY_ALEXSTRASZA_ONE); + ScheduleUniqueTimedEvent(6s, [&] + { + Talk(SAY_ALEXSTRASZA_TWO); + ScheduleUniqueTimedEvent(5s, [&] + { + Talk(SAY_ALEXSTRASZA_THREE); + ScheduleUniqueTimedEvent(22s, [&] + { + Talk(SAY_ALEXSTRASZA_FOUR); + }, EVENT_ALEXSTRASZA_SAY_FOUR); + }, EVENT_ALEXSTRASZA_SAY_THREE); + }, EVENT_ALEXSTRASZA_SAY_TWO); + }, EVENT_ALEXSTRASZA_GIFT); + } void UpdateAI(uint32 diff) override { - events.Update(diff); - switch (events.ExecuteEvent()) - { - case 0: - break; - case 1: - me->CastSpell(773.98f, 1285.97f, 266.254f, SPELL_ALEXSTRASZA_GIFT, true); - if (GameObject* chest = me->SummonGameObject(ALEXSTRASZA_GIFT, 773.98f, 1285.97f, 266.254f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0)) - { - chest->SetLootRecipient(me->GetMap()); - } - - if (GameObject* heart = me->SummonGameObject(HEART_OF_MAGIC, 773.98f, 1275.97f, 266.254f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0)) - { - heart->SetLootRecipient(me->GetMap()); - } - - Talk(SAY_ALEXSTRASZA_ONE); - events.RescheduleEvent(2, 6s); - break; - case 2: - Talk(SAY_ALEXSTRASZA_TWO); - events.RescheduleEvent(3, 5s); - break; - case 3: - Talk(SAY_ALEXSTRASZA_THREE); - events.RescheduleEvent(4, 22s); - break; - case 4: - Talk(SAY_ALEXSTRASZA_FOUR); - break; - } + scheduler.Update(diff); } void MoveInLineOfSight(Unit* /*who*/) override {} @@ -1315,14 +1239,14 @@ struct npc_eoe_wyrmrest_skytalon : public VehicleAI void IsSummonedBy(WorldObject* summoner) override { - if (summoner && summoner->IsPlayer()) - { - ObjectGuid summonerGUID = summoner->GetGUID(); - me->m_Events.AddEventAtOffset([summonerGUID, this] { - if (Player* rider = ObjectAccessor::GetPlayer(*me, summonerGUID)) - DoCast(rider, SPELL_RIDE_RED_DRAGON, true); - }, 2s); - } + if (!summoner || !summoner->IsPlayer()) + return; + + ObjectGuid summonerGUID = summoner->GetGUID(); + me->m_Events.AddEventAtOffset([summonerGUID, this] { + if (Player* rider = ObjectAccessor::GetPlayer(*me, summonerGUID)) + DoCast(rider, SPELL_RIDE_RED_DRAGON, true); + }, 2s); } void PassengerBoarded(Unit* pass, int8 /*seat*/, bool apply) override @@ -1346,17 +1270,13 @@ struct npc_eoe_wyrmrest_skytalon : public VehicleAI } }; -class go_the_focusing_iris : public GameObjectScript +struct go_the_focusing_iris : public GameObjectAI { -public: - go_the_focusing_iris() : GameObjectScript("go_the_focusing_iris") { } + go_the_focusing_iris(GameObject* go) : GameObjectAI(go) { } - bool OnGossipHello(Player* user, GameObject* go) override + bool GossipHello(Player* /*user*/, bool /*reportUse*/) override { - if (!user || !go) - return true; - - if (InstanceScript* pInstance = go->GetInstanceScript()) + if (InstanceScript* pInstance = me->GetInstanceScript()) pInstance->SetData(DATA_IRIS_ACTIVATED, 0); return true; @@ -1455,7 +1375,7 @@ void AddSC_boss_malygos() RegisterEoECreatureAI(npc_power_spark); RegisterEoECreatureAI(npc_vortex_ride); RegisterEoECreatureAI(npc_alexstrasza); - new go_the_focusing_iris(); + RegisterGameObjectAI(go_the_focusing_iris); RegisterEoECreatureAI(npc_nexus_lord); RegisterEoECreatureAI(npc_scion_of_eternity); RegisterEoECreatureAI(npc_hover_disk); 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 2b3ddfd38..bbbdc5779 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h @@ -18,7 +18,6 @@ #ifndef DEF_EYE_OF_ETERNITY_H #define DEF_EYE_OF_ETERNITY_H -#include "Chat.h" #include "CreatureAIImpl.h" #define DataHeader "EOE" @@ -91,13 +90,29 @@ enum eAchiev enum EoEMisc : uint32 { - EVENT_IRIS_ACTIVATED = 20158 + AREA_EYE_OF_ETERNITY = 4500, + EVENT_IRIS_ACTIVATED = 20158, + PLATFORM_DESTROY_DAMAGE = 6500000, + INTRO_MOVEMENT_INTERVAL = 25000, +}; + +enum EoEActions +{ + ACTION_POWER_SPARK_FOLLOW = 1, + ACTION_POWER_SPARK_STOP = 2, + ACTION_DISK_START_MOVING = 1, +}; + +enum AlexstraszaEvents +{ + EVENT_ALEXSTRASZA_GIFT = 1, + EVENT_ALEXSTRASZA_SAY_TWO = 2, + EVENT_ALEXSTRASZA_SAY_THREE = 3, + EVENT_ALEXSTRASZA_SAY_FOUR = 4, }; /*** POSITIONS/WAYPOINTS BELOW ***/ -#define INTRO_MOVEMENT_INTERVAL 25000 - const Position CenterPos = {754.395f, 1301.27f, 266.10f, 0.0f}; const Position FourSidesPos[] = @@ -110,6 +125,9 @@ const Position FourSidesPos[] = const Position Phase2NorthPos = {837.22f, 1301.676f, 296.10f, M_PI}; +const Position AlexstraszaGiftPos = {773.98f, 1285.97f, 266.254f, 0.0f}; +const Position HeartOfMagicPos = {773.98f, 1275.97f, 266.254f, 0.0f}; + const uint32 MalygosIntroIntervals[] = {18000, 19000, 21000, 18000, 15000}; template 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 42788ec50..590836726 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 @@ -21,193 +21,178 @@ #include "Vehicle.h" #include "eye_of_eternity.h" -class instance_eye_of_eternity : public InstanceMapScript +struct instance_eye_of_eternity : public InstanceScript { -public: - instance_eye_of_eternity() : InstanceMapScript("instance_eye_of_eternity", MAP_THE_EYE_OF_ETERNITY) { } + instance_eye_of_eternity(Map* pMap) : InstanceScript(pMap) { Initialize(); } - struct instance_eye_of_eternity_InstanceMapScript : public InstanceScript + ObjectGuid NPC_MalygosGUID; + ObjectGuid GO_IrisGUID; + ObjectGuid GO_ExitPortalGUID; + ObjectGuid GO_PlatformGUID; + bool bPokeAchiev; + + void Initialize() override { - instance_eye_of_eternity_InstanceMapScript(Map* pMap) : InstanceScript(pMap) { Initialize(); } + SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + bPokeAchiev = false; + } - ObjectGuid NPC_MalygosGUID; - ObjectGuid GO_IrisGUID; - ObjectGuid GO_ExitPortalGUID; - ObjectGuid GO_PlatformGUID; - bool bPokeAchiev; + void OnPlayerEnter(Player* player) override + { + if (GetBossState(DATA_MALYGOS) != DONE) + return; - void Initialize() override + ProcessEvent(nullptr, EVENT_IRIS_ACTIVATED); + if (GameObject* go = instance->GetGameObject(GO_IrisGUID)) + if (go->GetPhaseMask() != 2) + go->SetPhaseMask(2, true); + + if (player && player->IsAlive()) + player->CastSpell(player, SPELL_SUMMON_RED_DRAGON_BUDDY, true); + } + + void OnCreatureCreate(Creature* creature) override + { + switch (creature->GetEntry()) { - SetHeaders(DataHeader); - SetBossNumber(EncounterCount); - bPokeAchiev = false; + case NPC_MALYGOS: + NPC_MalygosGUID = creature->GetGUID(); + break; } + } - void OnPlayerEnter(Player* player) override + void OnGameObjectCreate(GameObject* go) override + { + switch (go->GetEntry()) { - if (GetBossState(DATA_MALYGOS) == DONE) - { - // destroy platform, hide iris (actually ensure, done at loading, but doesn't always work - 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 && player->IsAlive()) - player->CastSpell(player, SPELL_SUMMON_RED_DRAGON_BUDDY, true); - } - } - - void OnCreatureCreate(Creature* creature) override - { - switch (creature->GetEntry()) - { - case NPC_MALYGOS: - NPC_MalygosGUID = creature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* go) override - { - switch (go->GetEntry()) - { - 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 - { - switch (type) - { - case DATA_IRIS_ACTIVATED: - 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_SET_IRIS_INACTIVE: - if (GameObject* go = instance->GetGameObject(GO_IrisGUID)) - { - HandleGameObject(GO_IrisGUID, true, go); - if (Creature* c = go->SummonCreature(NPC_WORLD_TRIGGER_LAOI, *go, TEMPSUMMON_TIMED_DESPAWN, 10000)) - c->CastSpell(c, SPELL_IRIS_ACTIVATED, true); - } - break; - case DATA_HIDE_IRIS_AND_PORTAL: - if (GameObject* go = instance->GetGameObject(GO_IrisGUID)) - go->SetPhaseMask(2, true); - if (GameObject* go = instance->GetGameObject(GO_ExitPortalGUID)) - go->SetPhaseMask(2, true); - break; - } - } - - bool SetBossState(uint32 type, EncounterState state) override - { - if (!InstanceScript::SetBossState(type, state)) - return false; - - if (type == DATA_MALYGOS) - { - switch (state) + 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) { - 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; + go->ModifyHealth(-int32(PLATFORM_DESTROY_DAMAGE)); + go->EnableCollision(false); } - } - - return true; + break; } + } - ObjectGuid GetGuidData(uint32 type) const override - { - switch (type) - { - case DATA_MALYGOS_GUID: - return NPC_MalygosGUID; - } - - return ObjectGuid::Empty; - } - - void ProcessEvent(WorldObject* /*unit*/, uint32 eventId) override - { - 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 - { - switch (criteria_id) - { - case ACHIEV_CRITERIA_A_POKE_IN_THE_EYE_10: - case ACHIEV_CRITERIA_A_POKE_IN_THE_EYE_25: - return bPokeAchiev; - case ACHIEV_CRITERIA_DENYIN_THE_SCION_10: - case ACHIEV_CRITERIA_DENYIN_THE_SCION_25: - return (source && source->GetVehicle() && source->GetVehicle()->GetVehicleInfo()->m_ID == 224); - } - return false; - } - }; - - InstanceScript* GetInstanceScript(InstanceMap* map) const override + void SetData(uint32 type, uint32 /*data*/) override { - return new instance_eye_of_eternity_InstanceMapScript(map); + switch (type) + { + case DATA_IRIS_ACTIVATED: + 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_SET_IRIS_INACTIVE: + if (GameObject* go = instance->GetGameObject(GO_IrisGUID)) + { + HandleGameObject(GO_IrisGUID, true, go); + if (Creature* c = go->SummonCreature(NPC_WORLD_TRIGGER_LAOI, *go, TEMPSUMMON_TIMED_DESPAWN, 10000)) + c->CastSpell(c, SPELL_IRIS_ACTIVATED, true); + } + break; + case DATA_HIDE_IRIS_AND_PORTAL: + if (GameObject* go = instance->GetGameObject(GO_IrisGUID)) + go->SetPhaseMask(2, true); + if (GameObject* go = instance->GetGameObject(GO_ExitPortalGUID)) + go->SetPhaseMask(2, true); + break; + } + } + + 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)) + c->SummonCreature(NPC_ALEXSTRASZA, 798.0f, 1268.0f, 299.0f, 2.45f, TEMPSUMMON_MANUAL_DESPAWN); + break; + default: + break; + } + } + + return true; + } + + ObjectGuid GetGuidData(uint32 type) const override + { + switch (type) + { + case DATA_MALYGOS_GUID: + return NPC_MalygosGUID; + } + + return ObjectGuid::Empty; + } + + void ProcessEvent(WorldObject* /*unit*/, uint32 eventId) override + { + if (eventId == EVENT_IRIS_ACTIVATED) + if (GameObject* go = instance->GetGameObject(GO_PlatformGUID)) + if (Creature* c = instance->GetCreature(NPC_MalygosGUID)) + { + go->ModifyHealth(-int32(PLATFORM_DESTROY_DAMAGE), c); + go->EnableCollision(false); + } + } + + bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* source, Unit const* /*target*/, uint32 /*miscvalue1*/) override + { + switch (criteria_id) + { + case ACHIEV_CRITERIA_A_POKE_IN_THE_EYE_10: + case ACHIEV_CRITERIA_A_POKE_IN_THE_EYE_25: + return bPokeAchiev; + case ACHIEV_CRITERIA_DENYIN_THE_SCION_10: + case ACHIEV_CRITERIA_DENYIN_THE_SCION_25: + return source && source->GetVehicle() && source->GetVehicle()->GetVehicleInfo()->m_ID == 224; + } + return false; } }; void AddSC_instance_eye_of_eternity() { - new instance_eye_of_eternity(); + RegisterInstanceScript(instance_eye_of_eternity, MAP_THE_EYE_OF_ETERNITY); }