diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 813349aea..d77608b47 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -188,1278 +188,1189 @@ enum MalygosLightOverrides LIGHT_OBSCURE_ARCANE_RUNES = 1825, }; -class boss_malygos : public CreatureScript +struct boss_malygos : public ScriptedAI { -public: - boss_malygos() : CreatureScript("boss_malygos") { } - - CreatureAI* GetAI(Creature* pCreature) const override + boss_malygos(Creature* c) : ScriptedAI(c), summons(me) { - return GetEyeOfEternityAI(pCreature); + pInstance = me->GetInstanceScript(); } - struct boss_malygosAI : public ScriptedAI + InstanceScript* pInstance; + EventMap events; + SummonList summons; + + uint32 timer1, timer2; + uint8 IntroCounter; + bool bLockHealthCheck; + + void InitializeAI() override { - boss_malygosAI(Creature* c) : ScriptedAI(c), summons(me) + me->SetDisableGravity(true); + Reset(); + } + + void Reset() override + { + events.Reset(); + events.SetPhase(PHASE_NONE); + summons.DespawnAll(); + + timer1 = MalygosIntroIntervals[4]; + timer2 = INTRO_MOVEMENT_INTERVAL; + IntroCounter = 0; + bLockHealthCheck = false; + + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED); + me->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE); + + me->SetAnimTier(AnimTier::Fly); + + if (pInstance) { - pInstance = me->GetInstanceScript(); + pInstance->SetData(DATA_ENCOUNTER_STATUS, NOT_STARTED); + pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_YOU_DONT_HAVE_AN_ENTERNITY_EVENT); + } + } + + 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; + + 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); + } + } + + void JustEngagedWith(Unit* /*who*/) override + { + 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 + { + if (!victim) + return; + + if (me->GetVictim() && me->GetVictim()->GetGUID() == victim->GetGUID() && !me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED)) + { + if (!me->GetGuidValue(UNIT_FIELD_TARGET)) + me->SetTarget(victim->GetGUID()); + } + else if (me->Attack(victim, true)) + { + if (!me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED)) + me->GetMotionMaster()->MoveChase(victim); + else + me->SetTarget(); + } + } + + void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override + { + if (damage >= me->GetHealth() && !me->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE)) // allow dying only in phase 3! + { + damage = 0; + return; } - InstanceScript* pInstance; - EventMap events; - SummonList summons; - - uint32 timer1, timer2; - uint8 IntroCounter; - bool bLockHealthCheck; - - void InitializeAI() override + if (!bLockHealthCheck && me->HealthBelowPctDamaged(50, damage)) { - me->SetDisableGravity(true); - Reset(); + bLockHealthCheck = true; + events.RescheduleEvent(EVENT_START_PHASE_2, 0ms, 1); } + } - void Reset() override + void UpdateAI(uint32 diff) override + { + HandleIntroSpeech(diff); + + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) { - events.Reset(); - events.SetPhase(PHASE_NONE); + case 0: + break; + case EVENT_BERSERK: + me->CastSpell(me, SPELL_BERSERK, true); + Talk(EMOTE_BERSERK); + + break; + case EVENT_INTRO_MOVE_CENTER: + { + if (pInstance) + pInstance->SetData(DATA_SET_IRIS_INACTIVE, 0); summons.DespawnAll(); - - timer1 = MalygosIntroIntervals[4]; - timer2 = INTRO_MOVEMENT_INTERVAL; - IntroCounter = 0; - bLockHealthCheck = false; - - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED); - me->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE); - - me->SetAnimTier(AnimTier::Fly); - + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + float angle = CenterPos.GetAngle(me); + float x = CenterPos.GetPositionX() + cos(angle) * 35.0f; + float y = CenterPos.GetPositionY() + std::sin(angle) * 35.0f; + float z = FourSidesPos[0].GetPositionZ(); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); + me->GetMotionMaster()->MovePoint(MI_POINT_INTRO_CENTER_AIR, x, y, z); + 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: + { if (pInstance) { - pInstance->SetData(DATA_ENCOUNTER_STATUS, NOT_STARTED); - pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_YOU_DONT_HAVE_AN_ENTERNITY_EVENT); + pInstance->SetData(DATA_HIDE_IRIS_AND_PORTAL, 0); + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_YOU_DONT_HAVE_AN_ENTERNITY_EVENT); } - } - - void MovementInform(uint32 type, uint32 id) override - { - if (type == POINT_MOTION_TYPE) + me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED); + if (Unit* target = me->SelectNearestTarget(250.0f)) { - 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; - } + AttackStart(target); + me->GetMotionMaster()->MoveChase(target); } - } - void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override + events.SetPhase(PHASE_ONE); + events.RescheduleEvent(EVENT_BERSERK, 10min, 0); + events.RescheduleEvent(EVENT_SPELL_ARCANE_BREATH, 9s, 12s, 1); + events.RescheduleEvent(EVENT_SPELL_ARCANE_STORM, 2s, 5s, 1); + events.RescheduleEvent(EVENT_SUMMON_POWER_SPARK, 10s, 15s, 1); + events.RescheduleEvent(EVENT_START_VORTEX_0, 30s, 1); + break; + } + case EVENT_SPELL_ARCANE_BREATH: + me->CastSpell(me->GetVictim(), SPELL_ARCANE_BREATH, false); + events.Repeat(12s, 15s); + break; + case EVENT_SPELL_ARCANE_STORM: + me->CastCustomSpell(SPELL_ARCANE_STORM, SPELLVALUE_MAX_TARGETS, DUNGEON_MODE(5, 12), me, true); + events.Repeat(10s, 15s); + break; + case EVENT_SUMMON_POWER_SPARK: { - if (spell->Id == SPELL_POWER_SPARK_MALYGOS_BUFF) + uint8 random = urand(0, 3); + if (Creature* c = me->SummonCreature(NPC_PORTAL, FourSidesPos[random], TEMPSUMMON_TIMED_DESPAWN, 6000)) + c->CastSpell(c, SPELL_PORTAL_BEAM, false); + if (Creature* c = me->SummonCreature(NPC_POWER_SPARK, FourSidesPos[random], TEMPSUMMON_MANUAL_DESPAWN, 0)) { - if (!bLockHealthCheck) - { - Talk(SAY_BUFFED_BY_SPARK); - } - else - me->RemoveAura(SPELL_POWER_SPARK_MALYGOS_BUFF); - } - } - - void JustEngagedWith(Unit* /*who*/) override - { - 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 - { - if (!victim) - return; - - if (me->GetVictim() && me->GetVictim()->GetGUID() == victim->GetGUID() && !me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED)) - { - if (!me->GetGuidValue(UNIT_FIELD_TARGET)) - me->SetTarget(victim->GetGUID()); - } - else if (me->Attack(victim, true)) - { - if (!me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED)) - me->GetMotionMaster()->MoveChase(victim); - else - me->SetTarget(); - } - } - - void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override - { - if (damage >= me->GetHealth() && !me->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE)) // allow dying only in phase 3! - { - damage = 0; - return; + c->AI()->DoAction(1); + c->AI()->Talk(EMOTE_POWER_SPARK); } - if (!bLockHealthCheck && me->HealthBelowPctDamaged(50, damage)) - { - bLockHealthCheck = true; - events.RescheduleEvent(EVENT_START_PHASE_2, 0ms, 1); - } + events.Repeat(20s, 30s); } - - void UpdateAI(uint32 diff) override + break; + case EVENT_START_VORTEX_0: { - HandleIntroSpeech(diff); + bLockHealthCheck = true; + Talk(SAY_MAGIC_BLAST); + EntryCheckPredicate pred(NPC_POWER_SPARK); + summons.DoAction(2, pred); // stop following + me->SetUnitFlag(UNIT_FLAG_PACIFIED); - if (!UpdateVictim()) - return; + me->SendMeleeAttackStop(me->GetVictim()); + me->SetTarget(); - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case 0: - break; - case EVENT_BERSERK: - me->CastSpell(me, SPELL_BERSERK, true); - Talk(EMOTE_BERSERK); - - break; - case EVENT_INTRO_MOVE_CENTER: - { - if (pInstance) - pInstance->SetData(DATA_SET_IRIS_INACTIVE, 0); - summons.DespawnAll(); - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - float angle = CenterPos.GetAngle(me); - float x = CenterPos.GetPositionX() + cos(angle) * 35.0f; - float y = CenterPos.GetPositionY() + std::sin(angle) * 35.0f; - float z = FourSidesPos[0].GetPositionZ(); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); - me->GetMotionMaster()->MovePoint(MI_POINT_INTRO_CENTER_AIR, x, y, z); - 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: - { - if (pInstance) - { - pInstance->SetData(DATA_HIDE_IRIS_AND_PORTAL, 0); - pInstance->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)) - { - AttackStart(target); - me->GetMotionMaster()->MoveChase(target); - } - - events.SetPhase(PHASE_ONE); - events.RescheduleEvent(EVENT_BERSERK, 10min, 0); - events.RescheduleEvent(EVENT_SPELL_ARCANE_BREATH, 9s, 12s, 1); - events.RescheduleEvent(EVENT_SPELL_ARCANE_STORM, 2s, 5s, 1); - events.RescheduleEvent(EVENT_SUMMON_POWER_SPARK, 10s, 15s, 1); - events.RescheduleEvent(EVENT_START_VORTEX_0, 30s, 1); - break; - } - case EVENT_SPELL_ARCANE_BREATH: - me->CastSpell(me->GetVictim(), SPELL_ARCANE_BREATH, false); - events.Repeat(12s, 15s); - break; - case EVENT_SPELL_ARCANE_STORM: - me->CastCustomSpell(SPELL_ARCANE_STORM, SPELLVALUE_MAX_TARGETS, DUNGEON_MODE(5, 12), me, true); - events.Repeat(10s, 15s); - break; - case EVENT_SUMMON_POWER_SPARK: - { - uint8 random = urand(0, 3); - if (Creature* c = me->SummonCreature(NPC_PORTAL, FourSidesPos[random], TEMPSUMMON_TIMED_DESPAWN, 6000)) - 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()->Talk(EMOTE_POWER_SPARK); - } - - events.Repeat(20s, 30s); - } - break; - case EVENT_START_VORTEX_0: - { - bLockHealthCheck = true; - Talk(SAY_MAGIC_BLAST); - EntryCheckPredicate pred(NPC_POWER_SPARK); - summons.DoAction(2, pred); // stop following - me->SetUnitFlag(UNIT_FLAG_PACIFIED); - - me->SendMeleeAttackStop(me->GetVictim()); - me->SetTarget(); - - me->GetMotionMaster()->MoveIdle(); - me->StopMoving(); - me->SetDisableGravity(true); - me->GetMotionMaster()->MovePoint(MI_POINT_VORTEX_TAKEOFF, me->GetPositionX(), me->GetPositionY(), CenterPos.GetPositionZ() + 20.0f, FORCED_MOVEMENT_RUN, 0.f, 0.f, true, true, MOTION_SLOT_ACTIVE, AnimTier::Fly); - - events.DelayEvents(25s, 1); // don't delay berserk (group 0) - } - break; - case EVENT_VORTEX_FLY_TO_CENTER: - me->GetMotionMaster()->MovePoint(MI_POINT_VORTEX_CENTER, CenterPos.GetPositionX(), CenterPos.GetPositionY(), CenterPos.GetPositionZ() + 20.0f); - break; - case EVENT_START_VORTEX_REAL: - { - me->SendMeleeAttackStop(me->GetVictim()); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_CUSTOM_SPELL_01); - me->HandleEmoteCommand(EMOTE_STATE_CUSTOM_SPELL_01); - - Position pos; - float angle = (me->GetOrientation() >= M_PI / 4 ? me->GetOrientation() - M_PI / 4 : 7 * M_PI / 4 + me->GetOrientation()); - pos.m_positionX = CenterPos.GetPositionX() + cos(angle) * 40.0f; - pos.m_positionY = CenterPos.GetPositionY() + std::sin(angle) * 40.0f; - pos.m_positionZ = CenterPos.GetPositionZ() + 20.0f; - pos.SetOrientation(pos.GetAngle(&CenterPos)); - - if (Creature* vp = me->SummonCreature(NPC_WORLD_TRIGGER_LAOI, pos, TEMPSUMMON_TIMED_DESPAWN, 14000)) - { - 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()) - { - 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); - } - } - } - - events.RescheduleEvent(EVENT_VORTEX_LAND_0, 11s, 1); - break; - } - 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 - me->RemoveUnitFlag(UNIT_FLAG_PACIFIED); - if (Unit* target = me->GetVictim()) - { - AttackStart(target); - me->GetMotionMaster()->MoveChase(target); - } - events.RescheduleEvent(EVENT_START_VORTEX_0, 60s, 1); - break; - } - case EVENT_START_PHASE_2: - events.SetPhase(PHASE_TWO); - Talk(SAY_END_P1); - me->SetUnitFlag(UNIT_FLAG_PACIFIED); - me->SendMeleeAttackStop(); - me->SetTarget(); - me->GetMotionMaster()->MoveIdle(); - me->DisableSpline(); - me->GetMotionMaster()->MovePoint(MI_POINT_CENTER_GROUND_PH_2, CenterPos); - 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(); - me->SetDisableGravity(true); - 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); - me->GetMotionMaster()->MovePoint(MI_POINT_CIRCLE_OUTSIDE_PH_2, Phase2NorthPos); - events.RescheduleEvent(EVENT_SPELL_ARCANE_STORM, 12s, 15s, 1); - events.RescheduleEvent(EVENT_SPELL_ARCANE_OVERLOAD, 8s, 1); - events.RescheduleEvent(EVENT_MOVE_TO_SURGE_OF_POWER, 55s, 1); - events.RescheduleEvent(EVENT_CHECK_TRASH_DEAD, 3s, 1); - - for (int i = 0; i < MAX_NEXUS_LORDS; i++) - { - float dist = 22.0f; - float angle = M_PI / 2 + ((float)i / MAX_NEXUS_LORDS) * 2 * M_PI; - if (Creature* disk = me->SummonCreature(NPC_HOVER_DISK, CenterPos.GetPositionX() + cos(angle) * dist, CenterPos.GetPositionY() + std::sin(angle) * dist, CenterPos.GetPositionZ() + 30.0f, 0.0f, TEMPSUMMON_MANUAL_DESPAWN, 0)) - if (Creature* c = me->SummonCreature(NPC_NEXUS_LORD, *disk, TEMPSUMMON_MANUAL_DESPAWN, 0)) - { - c->EnterVehicle(disk, 0); - disk->AI()->DoAction(1); // start moving - } - } - for (int i = 0; i < MAX_SCIONS_OF_ETERNITY; i++) - { - float dist = 30.0f; - float angle = 0.0f + ((float)i / MAX_SCIONS_OF_ETERNITY) * 2 * M_PI; - if (Creature* disk = me->SummonCreature(NPC_HOVER_DISK, CenterPos.GetPositionX() + cos(angle) * dist, CenterPos.GetPositionY() + std::sin(angle) * dist, CenterPos.GetPositionZ() + 30.0f, 0.0f, TEMPSUMMON_MANUAL_DESPAWN, 0)) - if (Creature* c = me->SummonCreature(NPC_SCION_OF_ETERNITY, *disk, TEMPSUMMON_MANUAL_DESPAWN, 0)) - { - c->EnterVehicle(disk, 0); - disk->AI()->DoAction(1); // start moving - } - } - - break; - case EVENT_SPELL_ARCANE_OVERLOAD: - { - me->GetMotionMaster()->MoveIdle(); - me->StopMoving(); - float dist = urand(5, 30); - float angle = rand_norm() * 2 * M_PI; - float posx = CenterPos.GetPositionX() + cos(angle) * dist; - float posy = CenterPos.GetPositionY() + std::sin(angle) * dist; - me->SetFacingTo(me->GetAngle(posx, posy)); - me->CastSpell(posx, posy, CenterPos.GetPositionZ() + 1.5f, SPELL_ARCANE_OVERLOAD, true); - events.Repeat(15s); - events.RescheduleEvent(EVENT_RESUME_FLYING_CIRCLES_PH_2, 3s, 1); - } - break; - case EVENT_RESUME_FLYING_CIRCLES_PH_2: - { - float angle = CenterPos.GetAngle(me); - float dist = Phase2NorthPos.GetExactDist2d(&CenterPos); - float newangle = angle + 0.5f; - if (newangle >= 2 * M_PI) newangle -= 2 * M_PI; - me->GetMotionMaster()->MovePoint(MI_POINT_CIRCLE_OUTSIDE_PH_2, CenterPos.GetPositionX() + cos(newangle)*dist, CenterPos.GetPositionY() + std::sin(newangle)*dist, Phase2NorthPos.GetPositionZ()); - } - break; - case EVENT_MOVE_TO_SURGE_OF_POWER: - { - Talk(SAY_DEEP_BREATH); - float angle = CenterPos.GetAngle(me); - me->GetMotionMaster()->MoveIdle(); - me->StopMoving(); - me->GetMotionMaster()->MovePoint(MI_POINT_SURGE_OF_POWER_CENTER, CenterPos.GetPositionX() + cos(angle) * 10.0f, CenterPos.GetPositionY() + std::sin(angle) * 10.0f, Phase2NorthPos.GetPositionZ()); - events.CancelEventGroup(1); // everything beside berserk - } - break; - case EVENT_SURGE_OF_POWER_WARNING: - Talk(EMOTE_SURGE_OF_POWER_WARNING_P2); - events.RescheduleEvent(EVENT_SPELL_SURGE_OF_POWER, 1500ms, 1); - break; - case EVENT_SPELL_SURGE_OF_POWER: - if (Creature* c = me->SummonCreature(NPC_SURGE_OF_POWER, CenterPos, TEMPSUMMON_TIMED_DESPAWN, 10000)) - me->CastSpell(c, SPELL_SURGE_OF_POWER, false); - Talk(SAY_SURGE_OF_POWER); - events.RescheduleEvent(EVENT_CLEAR_TARGET, 10s, 1); - events.RescheduleEvent(EVENT_RESUME_FLYING_CIRCLES_PH_2, 10s, 1); - events.RescheduleEvent(EVENT_SPELL_ARCANE_STORM, 17s, 25s, 1); - events.RescheduleEvent(EVENT_SPELL_ARCANE_OVERLOAD, 16s, 1); - events.RescheduleEvent(EVENT_MOVE_TO_SURGE_OF_POWER, 65s, 1); - events.RescheduleEvent(EVENT_CHECK_TRASH_DEAD, 3s, 1); - break; - case EVENT_CLEAR_TARGET: - me->SendMeleeAttackStop(); - 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 - { - me->SendMeleeAttackStop(); - me->SetTarget(); - events.CancelEventGroup(1); - summons.DespawnAll(); - // start phase 3 - Talk(SAY_END_P2); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->StopMoving(); - me->GetMotionMaster()->MovePoint(MI_POINT_START_PH_3, CenterPos.GetPositionX(), CenterPos.GetPositionY(), CenterPos.GetPositionZ() + 70.0f); - events.RescheduleEvent(EVENT_LIGHT_DIMENSION_CHANGE, 1s, 1); - events.RescheduleEvent(EVENT_DESTROY_PLATFORM_0, 10s, 1); - } - } - break; - case EVENT_LIGHT_DIMENSION_CHANGE: - me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_CHANGE_DIMENSIONS, 2s); - break; - case EVENT_DESTROY_PLATFORM_0: - if (Creature* c = me->SummonCreature(NPC_WORLD_TRIGGER_LAOI, CenterPos, TEMPSUMMON_TIMED_DESPAWN, 3000)) - { - c->SetFaction(me->GetFaction()); - c->CastSpell(c, SPELL_DESTROY_PLATFORM_VISUAL, true); - c->CastSpell(c, SPELL_DESTROY_PLATFORM_EFFECT, false); - } - me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_OBSCURE_SPACE, 1s); - events.RescheduleEvent(EVENT_MOVE_TO_PHASE_3_POSITION, 2s, 1); - break; - case EVENT_MOVE_TO_PHASE_3_POSITION: - { - me->SendMeleeAttackStop(me->GetVictim()); - me->GetMotionMaster()->MovePoint(MI_POINT_PH_3_FIGHT_POSITION, CenterPos.GetPositionX(), CenterPos.GetPositionY(), CenterPos.GetPositionZ() - 5.0f, FORCED_MOVEMENT_RUN, 0.f, 0.f, true, true, MOTION_SLOT_ACTIVE, AnimTier::Fly); - - 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); - - if (!player->IsAlive() || player->IsGameMaster()) - continue; - - player->CastSpell(player, SPELL_SUMMON_RED_DRAGON_BUDDY, true); - } - - events.RescheduleEvent(EVENT_SAY_PHASE_3_INTRO, 3s, 1); - } - break; - case EVENT_SAY_PHASE_3_INTRO: - Talk(SAY_INTRO_PHASE_3); - break; - case EVENT_START_PHASE_3: - events.SetPhase(PHASE_THREE); - 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); - if (Unit* target = me->GetVictim()) - AttackStart(target); - events.RescheduleEvent(EVENT_SPELL_ARCANE_PULSE, 0ms, 1); - events.RescheduleEvent(EVENT_SPELL_STATIC_FIELD, 1s, 4s, 1); - events.RescheduleEvent(EVENT_SPELL_PH3_SURGE_OF_POWER, 4s, 7s, 1); - events.RescheduleEvent(EVENT_SPELL_ARCANE_STORM, 12s, 15s, 1); - break; - case EVENT_SPELL_ARCANE_PULSE: - me->CastSpell(me, SPELL_ARCANE_PULSE, true); - events.Repeat(3s); - break; - case EVENT_SPELL_STATIC_FIELD: - if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 200.0f, false)) - { - me->SetFacingToObject(target); - me->CastSpell(target, SPELL_STATIC_FIELD_MAIN, true); - } - events.Repeat(12s); - break; - case EVENT_SPELL_PH3_SURGE_OF_POWER: - me->CastSpell((Unit*)nullptr, SPELL_PH3_SURGE_OF_POWER, false); - events.Repeat(7s); - break; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); - if (pInstance) - { - pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, NPC_MALYGOS, 1); - pInstance->SetData(DATA_ENCOUNTER_STATUS, DONE); - } - } - - void KilledUnit(Unit* victim) override - { - if (victim && victim->GetGUID() == me->GetGUID()) - return; - - if (events.IsInPhase(PHASE_ONE)) - Talk(SAY_SLAY_P1); - else if (events.IsInPhase(PHASE_TWO)) - Talk(SAY_SLAY_P2); - else - Talk(SAY_SLAY_P3); - } - - void JustSummoned(Creature* summon) override - { - if (!summon) - return; - summons.Summon(summon); - switch (summon->GetEntry()) - { - case NPC_ARCANE_OVERLOAD: - summon->CastSpell(summon, SPELL_ARCANE_OVERLOAD_DMG, true); - summon->DespawnOrUnsummon(45s); - break; - case NPC_STATIC_FIELD: - summon->DespawnOrUnsummon(20s); - break; - } - } - - void MoveInLineOfSight(Unit* /*who*/) override {} - - void EnterEvadeMode(EvadeReason why) override - { + me->GetMotionMaster()->MoveIdle(); + me->StopMoving(); me->SetDisableGravity(true); - me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_GET_DEFAULT_FOR_MAP, 1s); + me->GetMotionMaster()->MovePoint(MI_POINT_VORTEX_TAKEOFF, me->GetPositionX(), me->GetPositionY(), CenterPos.GetPositionZ() + 20.0f, FORCED_MOVEMENT_RUN, 0.f, 0.f, true, true, MOTION_SLOT_ACTIVE, AnimTier::Fly); - me->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE); - ScriptedAI::EnterEvadeMode(why); + events.DelayEvents(25s, 1); // don't delay berserk (group 0) + } + break; + case EVENT_VORTEX_FLY_TO_CENTER: + me->GetMotionMaster()->MovePoint(MI_POINT_VORTEX_CENTER, CenterPos.GetPositionX(), CenterPos.GetPositionY(), CenterPos.GetPositionZ() + 20.0f); + break; + case EVENT_START_VORTEX_REAL: + { + me->SendMeleeAttackStop(me->GetVictim()); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_CUSTOM_SPELL_01); + me->HandleEmoteCommand(EMOTE_STATE_CUSTOM_SPELL_01); + + Position pos; + float angle = (me->GetOrientation() >= M_PI / 4 ? me->GetOrientation() - M_PI / 4 : 7 * M_PI / 4 + me->GetOrientation()); + pos.m_positionX = CenterPos.GetPositionX() + cos(angle) * 40.0f; + pos.m_positionY = CenterPos.GetPositionY() + std::sin(angle) * 40.0f; + pos.m_positionZ = CenterPos.GetPositionZ() + 20.0f; + pos.SetOrientation(pos.GetAngle(&CenterPos)); + + if (Creature* vp = me->SummonCreature(NPC_WORLD_TRIGGER_LAOI, pos, TEMPSUMMON_TIMED_DESPAWN, 14000)) + { + 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()) + { + 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); + } + } + } + + events.RescheduleEvent(EVENT_VORTEX_LAND_0, 11s, 1); + break; + } + 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 + me->RemoveUnitFlag(UNIT_FLAG_PACIFIED); + if (Unit* target = me->GetVictim()) + { + AttackStart(target); + me->GetMotionMaster()->MoveChase(target); + } + events.RescheduleEvent(EVENT_START_VORTEX_0, 60s, 1); + break; + } + case EVENT_START_PHASE_2: + events.SetPhase(PHASE_TWO); + Talk(SAY_END_P1); + me->SetUnitFlag(UNIT_FLAG_PACIFIED); + me->SendMeleeAttackStop(); + me->SetTarget(); + me->GetMotionMaster()->MoveIdle(); + me->DisableSpline(); + me->GetMotionMaster()->MovePoint(MI_POINT_CENTER_GROUND_PH_2, CenterPos); + 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(); + me->SetDisableGravity(true); + 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); + me->GetMotionMaster()->MovePoint(MI_POINT_CIRCLE_OUTSIDE_PH_2, Phase2NorthPos); + events.RescheduleEvent(EVENT_SPELL_ARCANE_STORM, 12s, 15s, 1); + events.RescheduleEvent(EVENT_SPELL_ARCANE_OVERLOAD, 8s, 1); + events.RescheduleEvent(EVENT_MOVE_TO_SURGE_OF_POWER, 55s, 1); + events.RescheduleEvent(EVENT_CHECK_TRASH_DEAD, 3s, 1); + + for (int i = 0; i < MAX_NEXUS_LORDS; i++) + { + float dist = 22.0f; + float angle = M_PI / 2 + ((float)i / MAX_NEXUS_LORDS) * 2 * M_PI; + if (Creature* disk = me->SummonCreature(NPC_HOVER_DISK, CenterPos.GetPositionX() + cos(angle) * dist, CenterPos.GetPositionY() + std::sin(angle) * dist, CenterPos.GetPositionZ() + 30.0f, 0.0f, TEMPSUMMON_MANUAL_DESPAWN, 0)) + if (Creature* c = me->SummonCreature(NPC_NEXUS_LORD, *disk, TEMPSUMMON_MANUAL_DESPAWN, 0)) + { + c->EnterVehicle(disk, 0); + disk->AI()->DoAction(1); // start moving + } + } + for (int i = 0; i < MAX_SCIONS_OF_ETERNITY; i++) + { + float dist = 30.0f; + float angle = 0.0f + ((float)i / MAX_SCIONS_OF_ETERNITY) * 2 * M_PI; + if (Creature* disk = me->SummonCreature(NPC_HOVER_DISK, CenterPos.GetPositionX() + cos(angle) * dist, CenterPos.GetPositionY() + std::sin(angle) * dist, CenterPos.GetPositionZ() + 30.0f, 0.0f, TEMPSUMMON_MANUAL_DESPAWN, 0)) + if (Creature* c = me->SummonCreature(NPC_SCION_OF_ETERNITY, *disk, TEMPSUMMON_MANUAL_DESPAWN, 0)) + { + c->EnterVehicle(disk, 0); + disk->AI()->DoAction(1); // start moving + } + } + + break; + case EVENT_SPELL_ARCANE_OVERLOAD: + { + me->GetMotionMaster()->MoveIdle(); + me->StopMoving(); + float dist = urand(5, 30); + float angle = rand_norm() * 2 * M_PI; + float posx = CenterPos.GetPositionX() + cos(angle) * dist; + float posy = CenterPos.GetPositionY() + std::sin(angle) * dist; + me->SetFacingTo(me->GetAngle(posx, posy)); + me->CastSpell(posx, posy, CenterPos.GetPositionZ() + 1.5f, SPELL_ARCANE_OVERLOAD, true); + events.Repeat(15s); + events.RescheduleEvent(EVENT_RESUME_FLYING_CIRCLES_PH_2, 3s, 1); + } + break; + case EVENT_RESUME_FLYING_CIRCLES_PH_2: + { + float angle = CenterPos.GetAngle(me); + float dist = Phase2NorthPos.GetExactDist2d(&CenterPos); + float newangle = angle + 0.5f; + if (newangle >= 2 * M_PI) newangle -= 2 * M_PI; + me->GetMotionMaster()->MovePoint(MI_POINT_CIRCLE_OUTSIDE_PH_2, CenterPos.GetPositionX() + cos(newangle) * dist, CenterPos.GetPositionY() + std::sin(newangle) * dist, Phase2NorthPos.GetPositionZ()); + } + break; + case EVENT_MOVE_TO_SURGE_OF_POWER: + { + Talk(SAY_DEEP_BREATH); + float angle = CenterPos.GetAngle(me); + me->GetMotionMaster()->MoveIdle(); + me->StopMoving(); + me->GetMotionMaster()->MovePoint(MI_POINT_SURGE_OF_POWER_CENTER, CenterPos.GetPositionX() + cos(angle) * 10.0f, CenterPos.GetPositionY() + std::sin(angle) * 10.0f, Phase2NorthPos.GetPositionZ()); + events.CancelEventGroup(1); // everything beside berserk + } + break; + case EVENT_SURGE_OF_POWER_WARNING: + Talk(EMOTE_SURGE_OF_POWER_WARNING_P2); + events.RescheduleEvent(EVENT_SPELL_SURGE_OF_POWER, 1500ms, 1); + break; + case EVENT_SPELL_SURGE_OF_POWER: + if (Creature* c = me->SummonCreature(NPC_SURGE_OF_POWER, CenterPos, TEMPSUMMON_TIMED_DESPAWN, 10000)) + me->CastSpell(c, SPELL_SURGE_OF_POWER, false); + Talk(SAY_SURGE_OF_POWER); + events.RescheduleEvent(EVENT_CLEAR_TARGET, 10s, 1); + events.RescheduleEvent(EVENT_RESUME_FLYING_CIRCLES_PH_2, 10s, 1); + events.RescheduleEvent(EVENT_SPELL_ARCANE_STORM, 17s, 25s, 1); + events.RescheduleEvent(EVENT_SPELL_ARCANE_OVERLOAD, 16s, 1); + events.RescheduleEvent(EVENT_MOVE_TO_SURGE_OF_POWER, 65s, 1); + events.RescheduleEvent(EVENT_CHECK_TRASH_DEAD, 3s, 1); + break; + case EVENT_CLEAR_TARGET: + me->SendMeleeAttackStop(); + 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 + { + me->SendMeleeAttackStop(); + me->SetTarget(); + events.CancelEventGroup(1); + summons.DespawnAll(); + // start phase 3 + Talk(SAY_END_P2); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->StopMoving(); + me->GetMotionMaster()->MovePoint(MI_POINT_START_PH_3, CenterPos.GetPositionX(), CenterPos.GetPositionY(), CenterPos.GetPositionZ() + 70.0f); + events.RescheduleEvent(EVENT_LIGHT_DIMENSION_CHANGE, 1s, 1); + events.RescheduleEvent(EVENT_DESTROY_PLATFORM_0, 10s, 1); + } + } + break; + case EVENT_LIGHT_DIMENSION_CHANGE: + me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_CHANGE_DIMENSIONS, 2s); + break; + case EVENT_DESTROY_PLATFORM_0: + if (Creature* c = me->SummonCreature(NPC_WORLD_TRIGGER_LAOI, CenterPos, TEMPSUMMON_TIMED_DESPAWN, 3000)) + { + c->SetFaction(me->GetFaction()); + c->CastSpell(c, SPELL_DESTROY_PLATFORM_VISUAL, true); + c->CastSpell(c, SPELL_DESTROY_PLATFORM_EFFECT, false); + } + me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_OBSCURE_SPACE, 1s); + events.RescheduleEvent(EVENT_MOVE_TO_PHASE_3_POSITION, 2s, 1); + break; + case EVENT_MOVE_TO_PHASE_3_POSITION: + { + me->SendMeleeAttackStop(me->GetVictim()); + me->GetMotionMaster()->MovePoint(MI_POINT_PH_3_FIGHT_POSITION, CenterPos.GetPositionX(), CenterPos.GetPositionY(), CenterPos.GetPositionZ() - 5.0f, FORCED_MOVEMENT_RUN, 0.f, 0.f, true, true, MOTION_SLOT_ACTIVE, AnimTier::Fly); + + 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); + + if (!player->IsAlive() || player->IsGameMaster()) + continue; + + player->CastSpell(player, SPELL_SUMMON_RED_DRAGON_BUDDY, true); + } + + events.RescheduleEvent(EVENT_SAY_PHASE_3_INTRO, 3s, 1); + } + break; + case EVENT_SAY_PHASE_3_INTRO: + Talk(SAY_INTRO_PHASE_3); + break; + case EVENT_START_PHASE_3: + events.SetPhase(PHASE_THREE); + 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); + if (Unit* target = me->GetVictim()) + AttackStart(target); + events.RescheduleEvent(EVENT_SPELL_ARCANE_PULSE, 0ms, 1); + events.RescheduleEvent(EVENT_SPELL_STATIC_FIELD, 1s, 4s, 1); + events.RescheduleEvent(EVENT_SPELL_PH3_SURGE_OF_POWER, 4s, 7s, 1); + events.RescheduleEvent(EVENT_SPELL_ARCANE_STORM, 12s, 15s, 1); + break; + case EVENT_SPELL_ARCANE_PULSE: + me->CastSpell(me, SPELL_ARCANE_PULSE, true); + events.Repeat(3s); + break; + case EVENT_SPELL_STATIC_FIELD: + if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 200.0f, false)) + { + me->SetFacingToObject(target); + me->CastSpell(target, SPELL_STATIC_FIELD_MAIN, true); + } + events.Repeat(12s); + break; + case EVENT_SPELL_PH3_SURGE_OF_POWER: + me->CastSpell((Unit*)nullptr, SPELL_PH3_SURGE_OF_POWER, false); + events.Repeat(7s); + break; } - void HandleIntroSpeech(const uint32 diff) - { - if (me->IsInCombat() || me->isDead()) - return; + DoMeleeAttackIfReady(); + } - // speech timer - if (timer1 <= diff) + void JustDied(Unit* /*killer*/) override + { + Talk(SAY_DEATH); + if (pInstance) + { + pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, NPC_MALYGOS, 1); + pInstance->SetData(DATA_ENCOUNTER_STATUS, DONE); + } + } + + void KilledUnit(Unit* victim) override + { + if (victim && victim->GetGUID() == me->GetGUID()) + return; + + if (events.IsInPhase(PHASE_ONE)) + Talk(SAY_SLAY_P1); + else if (events.IsInPhase(PHASE_TWO)) + Talk(SAY_SLAY_P2); + else + Talk(SAY_SLAY_P3); + } + + void JustSummoned(Creature* summon) override + { + if (!summon) + return; + summons.Summon(summon); + switch (summon->GetEntry()) + { + case NPC_ARCANE_OVERLOAD: + summon->CastSpell(summon, SPELL_ARCANE_OVERLOAD_DMG, true); + summon->DespawnOrUnsummon(45s); + break; + case NPC_STATIC_FIELD: + summon->DespawnOrUnsummon(20s); + break; + } + } + + void MoveInLineOfSight(Unit* /*who*/) override {} + + void EnterEvadeMode(EvadeReason why) override + { + me->SetDisableGravity(true); + me->GetMap()->SetZoneOverrideLight(AREA_EYE_OF_ETERNITY, LIGHT_GET_DEFAULT_FOR_MAP, 1s); + + me->RemoveUnitFlag(UNIT_FLAG_DISABLE_MOVE); + ScriptedAI::EnterEvadeMode(why); + } + + void HandleIntroSpeech(const uint32 diff) + { + if (me->IsInCombat() || me->isDead()) + return; + + // speech timer + if (timer1 <= diff) + { + Talk(SAY_INTRO); + timer1 = MalygosIntroIntervals[IntroCounter]; + if (++IntroCounter >= 5) + IntroCounter = 0; + } + else + timer1 -= diff; + + // movement timer + if (timer2) + { + if (timer2 <= diff) { - Talk(SAY_INTRO); - timer1 = MalygosIntroIntervals[IntroCounter]; - if (++IntroCounter >= 5) - IntroCounter = 0; + timer2 = 0; + uint32 tmp = urand(0, 3); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); + me->GetMotionMaster()->MovePoint(MI_POINT_INTRO_SIDE_0 + tmp, FourSidesPos[tmp]); } else - timer1 -= diff; - - // movement timer - if (timer2) - { - if (timer2 <= diff) - { - timer2 = 0; - uint32 tmp = urand(0, 3); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALKING); - me->GetMotionMaster()->MovePoint(MI_POINT_INTRO_SIDE_0 + tmp, FourSidesPos[tmp]); - } - else - timer2 -= diff; - } + timer2 -= diff; } - }; + } }; #define VORTEX_DEFAULT_DIFF 250 #define VORTEX_TRAVEL_TIME 3000 //#define VORTEX_RADIUS 25.0f -class npc_vortex_ride : public CreatureScript +struct npc_vortex_ride : public VehicleAI { -public: - npc_vortex_ride() : CreatureScript("npc_vortex_ride") { } - - CreatureAI* GetAI(Creature* pCreature) const override + npc_vortex_ride(Creature* pCreature) : VehicleAI(pCreature) { - return GetEyeOfEternityAI (pCreature); + VORTEX_RADIUS = 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_positionZ = CenterPos.GetPositionZ() + h; + pos.SetOrientation(pos.GetAngle(&CenterPos)); + me->SetPosition(pos); + timer = 0; + despawnTimer = 9500; + bUpdatedFlying = false; } - struct npc_vortex_rideAI : public VehicleAI + uint32 timer; + uint32 despawnTimer; + bool bUpdatedFlying; + float VORTEX_RADIUS; + + void PassengerBoarded(Unit* pass, int8 /*seat*/, bool apply) override { - npc_vortex_rideAI(Creature* pCreature) : VehicleAI(pCreature) + 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); + + 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; + me->UpdatePosition(CenterPos.GetPositionX(), CenterPos.GetPositionY(), CenterPos.GetPositionZ() + 18.0f, 0.0f, true); + me->StopMovingOnCurrentPos(); + if (Vehicle* vehicle = me->GetVehicleKit()) + vehicle->RemoveAllPassengers(); + me->DespawnOrUnsummon(); + return; + } + else + despawnTimer -= diff; + + if (timer <= diff) { - VORTEX_RADIUS = 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_positionZ = CenterPos.GetPositionZ() + h; - pos.SetOrientation(pos.GetAngle(&CenterPos)); - me->SetPosition(pos); - timer = 0; - despawnTimer = 9500; - bUpdatedFlying = false; - } - - uint32 timer; - uint32 despawnTimer; - bool bUpdatedFlying; - float VORTEX_RADIUS; - - void PassengerBoarded(Unit* pass, int8 /*seat*/, bool apply) override - { - if (pass && !apply && pass->IsPlayer()) + 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 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()) { - 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 (!bUpdatedFlying && timer) + { + bUpdatedFlying = true; + plr->SetDisableGravity(true); + } - sScriptMgr->AnticheatSetCanFlybyServer(plr, false); - sScriptMgr->AnticheatSetUnderACKmount(plr); + 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; } + else + timer -= diff; + } - 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; - me->UpdatePosition(CenterPos.GetPositionX(), CenterPos.GetPositionY(), CenterPos.GetPositionZ() + 18.0f, 0.0f, true); - me->StopMovingOnCurrentPos(); - if (Vehicle* vehicle = me->GetVehicleKit()) - vehicle->RemoveAllPassengers(); - me->DespawnOrUnsummon(); - return; - } - else - despawnTimer -= diff; - - if (timer <= diff) - { - float angle = CenterPos.GetAngle(me); - 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 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); - } - - 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; - } - else - timer -= diff; - } - - void AttackStart(Unit* /*who*/) override {} - void MoveInLineOfSight(Unit* /*who*/) override {} - void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override { damage = 0; } - }; + void AttackStart(Unit* /*who*/) override {} + void MoveInLineOfSight(Unit* /*who*/) override {} + void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override { damage = 0; } }; -class npc_power_spark : public CreatureScript +struct npc_power_spark : public NullCreatureAI { -public: - npc_power_spark() : CreatureScript("npc_power_spark") { } - - CreatureAI* GetAI(Creature* pCreature) const override + npc_power_spark(Creature* pCreature) : NullCreatureAI(pCreature) { - return GetEyeOfEternityAI(pCreature); + pInstance = me->GetInstanceScript(); + me->CastSpell(me, SPELL_POWER_SPARK_VISUAL, false); + CheckTimer = 1000; + MoveTimer = 0; } - struct npc_power_sparkAI : public NullCreatureAI + InstanceScript* pInstance; + uint16 CheckTimer; + uint16 MoveTimer; + + void DoAction(int32 param) override { - npc_power_sparkAI(Creature* pCreature) : NullCreatureAI(pCreature) + switch (param) { - pInstance = me->GetInstanceScript(); - me->CastSpell(me, SPELL_POWER_SPARK_VISUAL, false); - CheckTimer = 1000; + case 1: + MoveTimer = 1; + break; + case 2: MoveTimer = 0; + me->GetMotionMaster()->MoveIdle(); + me->DisableSpline(); + me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 0.05f, FORCED_MOVEMENT_NONE, 7.0f); + break; } + } - InstanceScript* pInstance; - uint16 CheckTimer; - uint16 MoveTimer; - - void DoAction(int32 param) override + void DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override + { + if (damage >= me->GetHealth()) { - switch (param) + damage = 0; + if (!me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) { - case 1: - MoveTimer = 1; - break; - case 2: - MoveTimer = 0; - me->GetMotionMaster()->MoveIdle(); - me->DisableSpline(); - me->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 0.05f, FORCED_MOVEMENT_NONE, 7.0f); - break; + 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 DamageTaken(Unit*, uint32& damage, DamageEffectType, SpellSchoolMask) override + void UpdateAI(uint32 diff) override + { + if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (CheckTimer <= diff) { - 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 (pInstance) + if (Creature* c = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_MALYGOS_GUID))) + if (me->IsWithinDist3d(c, 12.0f)) + { + me->CastSpell(c, SPELL_POWER_SPARK_MALYGOS_BUFF, true); + me->DespawnOrUnsummon(); + return; + } + CheckTimer = 1000; } + else + CheckTimer -= diff; - void UpdateAI(uint32 diff) override + if (MoveTimer) { - if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (CheckTimer <= diff) + if (MoveTimer <= diff) { if (pInstance) if (Creature* c = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_MALYGOS_GUID))) - if (me->IsWithinDist3d(c, 12.0f)) - { - me->CastSpell(c, SPELL_POWER_SPARK_MALYGOS_BUFF, true); - me->DespawnOrUnsummon(); - return; - } - CheckTimer = 1000; + me->GetMotionMaster()->MovePoint(0, *c); + MoveTimer = 2000; } else - CheckTimer -= diff; - - if (MoveTimer) - { - if (MoveTimer <= diff) - { - if (pInstance) - if (Creature* c = pInstance->instance->GetCreature(pInstance->GetGuidData(DATA_MALYGOS_GUID))) - me->GetMotionMaster()->MovePoint(0, *c); - MoveTimer = 2000; - } - else - MoveTimer -= diff; - } + MoveTimer -= diff; } - }; + } }; -class npc_nexus_lord : public CreatureScript +struct npc_nexus_lord : public ScriptedAI { -public: - npc_nexus_lord() : CreatureScript("npc_nexus_lord") { } - - CreatureAI* GetAI(Creature* pCreature) const override + npc_nexus_lord(Creature* pCreature) : ScriptedAI(pCreature) { - return GetEyeOfEternityAI(pCreature); + me->SetReactState(REACT_PASSIVE); + pInstance = me->GetInstanceScript(); + timer = 0; + events.Reset(); + events.RescheduleEvent(EVENT_TELEPORT_VISUAL, 0ms); } - struct npc_nexus_lordAI : public ScriptedAI + InstanceScript* pInstance; + EventMap events; + uint16 timer; + + void JustEngagedWith(Unit* /*who*/) override { - npc_nexus_lordAI(Creature* pCreature) : ScriptedAI(pCreature) - { - me->SetReactState(REACT_PASSIVE); - pInstance = me->GetInstanceScript(); - timer = 0; - events.Reset(); - events.RescheduleEvent(EVENT_TELEPORT_VISUAL, 0ms); - } + DoZoneInCombat(); + events.Reset(); + events.RescheduleEvent(EVENT_NEXUS_LORD_ARCANE_SHOCK, 3s, 10s); + events.RescheduleEvent(EVENT_NEXUS_LORD_HASTE, 8s, 14s); + } - InstanceScript* pInstance; - EventMap events; - uint16 timer; + void AttackStart(Unit* victim) override + { + if (victim && me->Attack(victim, true)) + me->GetMotionMaster()->MoveIdle(); + } - 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); - } - - void AttackStart(Unit* victim) override - { - if (victim && me->Attack(victim, true)) - me->GetMotionMaster()->MoveIdle(); - } - - void UpdateAI(uint32 diff) override - { - if (UpdateVictim()) - if (Unit* victim = me->GetVictim()) + void UpdateAI(uint32 diff) override + { + if (UpdateVictim()) + if (Unit* victim = me->GetVictim()) + { + if (timer <= diff) { - if (timer <= diff) + if (!victim->IsWithinMeleeRange(me)) { - if (!victim->IsWithinMeleeRange(me)) + float x, y, z; + victim->GetClosePoint(x, y, z, 0.0f, 1.5f, me->GetAngle(victim)); + if (Unit* v = me->GetVehicleBase()) + v->GetMotionMaster()->MovePoint(0, x, y, z); + } + timer = 1000; + } + else + timer -= diff; + } + + 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_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; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) override + { + if (Vehicle* v = me->GetVehicle()) + v->RemoveAllPassengers(); + } +}; + +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: + { + 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()) { - float x, y, z; - victim->GetClosePoint(x, y, z, 0.0f, 1.5f, me->GetAngle(victim)); - if (Unit* v = me->GetVehicleBase()) - v->GetMotionMaster()->MovePoint(0, x, y, z); + if (!pPlayer->GetVehicle()) + { + guids.push_back(pPlayer->GetGUID()); + } } - timer = 1000; } - else - timer -= diff; - } + if (!guids.empty()) + if (Player* plr = ObjectAccessor::GetPlayer(*me, guids.at(urand(0, guids.size() - 1)))) + me->CastSpell(plr, SPELL_SCION_ARCANE_BARRAGE); - 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_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; - } - - DoMeleeAttackIfReady(); + events.Repeat(5s, 8s); } - - void JustDied(Unit* /*killer*/) override - { - if (Vehicle* v = me->GetVehicle()) - v->RemoveAllPassengers(); + break; } - }; -}; - -class npc_scion_of_eternity : public CreatureScript -{ -public: - npc_scion_of_eternity() : CreatureScript("npc_scion_of_eternity") { } - - CreatureAI* GetAI(Creature* pCreature) const override - { - return GetEyeOfEternityAI(pCreature); } - struct npc_scion_of_eternityAI : public ScriptedAI + void JustDied(Unit* killer) override { - npc_scion_of_eternityAI(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); - } + if (Vehicle* v = me->GetVehicle()) + v->RemoveAllPassengers(); - 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: - { - 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()); - } - } - } - if (!guids.empty()) - if (Player* plr = ObjectAccessor::GetPlayer(*me, guids.at(urand(0, guids.size() - 1)))) - me->CastSpell(plr, SPELL_SCION_ARCANE_BARRAGE); - - events.Repeat(5s, 8s); - } - break; - } - } - - void JustDied(Unit* killer) override - { - if (Vehicle* v = me->GetVehicle()) - v->RemoveAllPassengers(); - - if (killer) - if (Player* player = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) - player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, me); - } - - void MoveInLineOfSight(Unit* /*who*/) override {} - void AttackStart(Unit* /*who*/) override {} - }; -}; - -class npc_hover_disk : public CreatureScript -{ -public: - npc_hover_disk() : CreatureScript("npc_hover_disk") { } - - CreatureAI* GetAI(Creature* pCreature) const override - { - return GetEyeOfEternityAI(pCreature); + if (killer) + if (Player* player = killer->GetCharmerOrOwnerPlayerOrPlayerItself()) + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, me); } - struct npc_hover_diskAI : public VehicleAI + void MoveInLineOfSight(Unit* /*who*/) override {} + void AttackStart(Unit* /*who*/) override {} +}; + +struct npc_hover_disk : public VehicleAI +{ + npc_hover_disk(Creature* pCreature) : VehicleAI(pCreature) { - npc_hover_diskAI(Creature* pCreature) : VehicleAI(pCreature) - { - pInstance = me->GetInstanceScript(); - events.Reset(); - } + pInstance = me->GetInstanceScript(); + events.Reset(); + } - InstanceScript* pInstance; - EventMap events; + InstanceScript* pInstance; + EventMap events; - void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override + void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override + { + events.Reset(); + if (!who) + return; + if (apply) { - events.Reset(); - if (!who) - return; - if (apply) + if (who->IsPlayer()) { - if (who->IsPlayer()) - { - who->ApplySpellImmune(0, IMMUNITY_ID, SPELL_ARCANE_OVERLOAD_DMG, true); - who->ApplySpellImmune(0, IMMUNITY_ID, SPELL_SURGE_OF_POWER_DMG, true); - me->SetSpeed(MOVE_RUN, 1.5f); - me->SetSpeed(MOVE_FLIGHT, 1.5f); - } - else if (who->GetEntry() == NPC_NEXUS_LORD) - { - me->SetSpeed(MOVE_RUN, 1.5f); - me->SetSpeed(MOVE_FLIGHT, 1.5f); - } - else - { - me->SetSpeed(MOVE_RUN, 0.6f); - me->SetSpeed(MOVE_FLIGHT, 0.6f); - } - - who->SetFacingTo(me->GetOrientation()); - me->SetCanFly(true); + who->ApplySpellImmune(0, IMMUNITY_ID, SPELL_ARCANE_OVERLOAD_DMG, true); + who->ApplySpellImmune(0, IMMUNITY_ID, SPELL_SURGE_OF_POWER_DMG, true); + me->SetSpeed(MOVE_RUN, 1.5f); + me->SetSpeed(MOVE_FLIGHT, 1.5f); + } + else if (who->GetEntry() == NPC_NEXUS_LORD) + { + me->SetSpeed(MOVE_RUN, 1.5f); + me->SetSpeed(MOVE_FLIGHT, 1.5f); } else { - me->GetMotionMaster()->MoveIdle(); - me->DisableSpline(); - me->SetCanFly(false); - me->GetMotionMaster()->MoveLand(0, me->GetPositionX(), me->GetPositionY(), 267.24f, 10.0f); - - if (who->IsPlayer()) - { - who->ApplySpellImmune(0, IMMUNITY_ID, SPELL_ARCANE_OVERLOAD_DMG, false); - who->ApplySpellImmune(0, IMMUNITY_ID, SPELL_SURGE_OF_POWER_DMG, false); - } + me->SetSpeed(MOVE_RUN, 0.6f); + me->SetSpeed(MOVE_FLIGHT, 0.6f); } - } - void MovementInform(uint32 type, uint32 id) override - { - if (type != POINT_MOTION_TYPE) - return; - - switch (id) - { - case MI_POINT_SCION: - events.RescheduleEvent(EVENT_DISK_MOVE_NEXT_POINT, 0ms); - break; - case MI_POINT_NEXUS_LORD: - if (me->GetPositionZ() > CenterPos.GetPositionZ() + 2.0f) - events.RescheduleEvent(EVENT_DISK_MOVE_NEXT_POINT, 0ms); - else if (Vehicle* v = me->GetVehicleKit()) - if (Unit* pass = v->GetPassenger(0)) - if (Creature* c = pass->ToCreature()) - { - c->SetReactState(REACT_AGGRESSIVE); - if (Player* plr = c->SelectNearestPlayer(100.0f)) - c->AI()->AttackStart(plr); - } - break; - } - } - - void DoAction(int32 param) override - { - switch (param) - { - case 1: // move to next point - if (Vehicle* v = me->GetVehicleKit()) - if (Unit* pass = v->GetPassenger(0)) - switch (pass->GetEntry()) - { - case NPC_NEXUS_LORD: - { - float angle = CenterPos.GetAngle(me); - float newangle = angle - 0.5f; - if (newangle < 0.0f) newangle += 2 * M_PI; - float newz = me->GetPositionZ() - 4.0f; - if (newz < CenterPos.GetPositionZ()) newz = CenterPos.GetPositionZ(); - me->GetMotionMaster()->MovePoint(MI_POINT_NEXUS_LORD, CenterPos.GetPositionX() + cos(newangle) * 22.0f, CenterPos.GetPositionY() + std::sin(newangle) * 22.0f, newz); - } - break; - case NPC_SCION_OF_ETERNITY: - { - float angle = CenterPos.GetAngle(me); - float newangle = angle - 0.3f; - if (newangle < 0.0f) newangle += 2 * M_PI; - float newz = me->GetPositionZ() - 2.0f; - if (newz < CenterPos.GetPositionZ() + 20.0f) newz = CenterPos.GetPositionZ() + 20.0f; - me->GetMotionMaster()->MovePoint(MI_POINT_SCION, CenterPos.GetPositionX() + cos(newangle) * 30.0f, CenterPos.GetPositionY() + std::sin(newangle) * 30.0f, newz); - } - break; - } - break; - } - } - - void UpdateAI(uint32 diff) override - { - events.Update(diff); - - switch (events.ExecuteEvent()) - { - case 0: - break; - case EVENT_DISK_MOVE_NEXT_POINT: - DoAction(1); - break; - } - } - - void MoveInLineOfSight(Unit* /*who*/) override {} - void AttackStart(Unit* /*who*/) override {} - }; -}; - -class npc_alexstrasza : public CreatureScript -{ -public: - npc_alexstrasza() : CreatureScript("npc_alexstrasza") { } - - CreatureAI* GetAI(Creature* pCreature) const override - { - return GetEyeOfEternityAI(pCreature); - } - - struct npc_alexstraszaAI : public ScriptedAI - { - npc_alexstraszaAI(Creature* pCreature) : ScriptedAI(pCreature) - { - events.Reset(); - events.ScheduleEvent(1, 9s); + who->SetFacingTo(me->GetOrientation()); me->SetCanFly(true); - me->SetDisableGravity(true); } - - EventMap events; - - void UpdateAI(uint32 diff) override + else { - events.Update(diff); - switch (events.ExecuteEvent()) + me->GetMotionMaster()->MoveIdle(); + me->DisableSpline(); + me->SetCanFly(false); + me->GetMotionMaster()->MoveLand(0, me->GetPositionX(), me->GetPositionY(), 267.24f, 10.0f); + + if (who->IsPlayer()) { - 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; + who->ApplySpellImmune(0, IMMUNITY_ID, SPELL_ARCANE_OVERLOAD_DMG, false); + who->ApplySpellImmune(0, IMMUNITY_ID, SPELL_SURGE_OF_POWER_DMG, false); } } - - void MoveInLineOfSight(Unit* /*who*/) override {} - void AttackStart(Unit* /*who*/) override {} - }; -}; - -class npc_eoe_wyrmrest_skytalon : public CreatureScript -{ -public: - npc_eoe_wyrmrest_skytalon() : CreatureScript("npc_eoe_wyrmrest_skytalon") { } - - CreatureAI* GetAI(Creature* pCreature) const override - { - return GetEyeOfEternityAI(pCreature); } - struct npc_eoe_wyrmrest_skytalonAI : public VehicleAI + void MovementInform(uint32 type, uint32 id) override { - npc_eoe_wyrmrest_skytalonAI(Creature* pCreature) : VehicleAI(pCreature) { } + if (type != POINT_MOTION_TYPE) + return; - void IsSummonedBy(WorldObject* summoner) override + switch (id) { - me->SetDisableGravity(true); - 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); - } + case MI_POINT_SCION: + events.RescheduleEvent(EVENT_DISK_MOVE_NEXT_POINT, 0ms); + break; + case MI_POINT_NEXUS_LORD: + if (me->GetPositionZ() > CenterPos.GetPositionZ() + 2.0f) + events.RescheduleEvent(EVENT_DISK_MOVE_NEXT_POINT, 0ms); + else if (Vehicle* v = me->GetVehicleKit()) + if (Unit* pass = v->GetPassenger(0)) + if (Creature* c = pass->ToCreature()) + { + c->SetReactState(REACT_AGGRESSIVE); + if (Player* plr = c->SelectNearestPlayer(100.0f)) + c->AI()->AttackStart(plr); + } + break; } + } - void PassengerBoarded(Unit* pass, int8 /*seat*/, bool apply) override + void DoAction(int32 param) override + { + switch (param) { - if (apply) - { - me->SetDisableGravity(false); - me->SendMovementFlagUpdate(); - } - else if (pass && pass->IsPlayer() && me->IsAlive()) - { - me->SetDisplayId(11686); // prevents nasty falling animation at despawn - me->DespawnOrUnsummon(1ms); - } + case 1: // move to next point + if (Vehicle* v = me->GetVehicleKit()) + if (Unit* pass = v->GetPassenger(0)) + switch (pass->GetEntry()) + { + case NPC_NEXUS_LORD: + { + float angle = CenterPos.GetAngle(me); + float newangle = angle - 0.5f; + if (newangle < 0.0f) newangle += 2 * M_PI; + float newz = me->GetPositionZ() - 4.0f; + if (newz < CenterPos.GetPositionZ()) newz = CenterPos.GetPositionZ(); + me->GetMotionMaster()->MovePoint(MI_POINT_NEXUS_LORD, CenterPos.GetPositionX() + cos(newangle) * 22.0f, CenterPos.GetPositionY() + std::sin(newangle) * 22.0f, newz); + } + break; + case NPC_SCION_OF_ETERNITY: + { + float angle = CenterPos.GetAngle(me); + float newangle = angle - 0.3f; + if (newangle < 0.0f) newangle += 2 * M_PI; + float newz = me->GetPositionZ() - 2.0f; + if (newz < CenterPos.GetPositionZ() + 20.0f) newz = CenterPos.GetPositionZ() + 20.0f; + me->GetMotionMaster()->MovePoint(MI_POINT_SCION, CenterPos.GetPositionX() + cos(newangle) * 30.0f, CenterPos.GetPositionY() + std::sin(newangle) * 30.0f, newz); + } + break; + } + break; } + } - void JustDied(Unit* /*killer*/) override + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + switch (events.ExecuteEvent()) + { + case 0: + break; + case EVENT_DISK_MOVE_NEXT_POINT: + DoAction(1); + break; + } + } + + void MoveInLineOfSight(Unit* /*who*/) override {} + void AttackStart(Unit* /*who*/) override {} +}; + +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; + + 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; + } + } + + void MoveInLineOfSight(Unit* /*who*/) override {} + void AttackStart(Unit* /*who*/) override {} +}; + +struct npc_eoe_wyrmrest_skytalon : public VehicleAI +{ + npc_eoe_wyrmrest_skytalon(Creature* creature) : VehicleAI(creature) { } + + 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); + } + } + + void PassengerBoarded(Unit* pass, int8 /*seat*/, bool apply) override + { + if (apply) + { + me->SetDisableGravity(false); + me->SendMovementFlagUpdate(); + } + else if (pass && pass->IsPlayer() && me->IsAlive()) { me->SetDisplayId(11686); // prevents nasty falling animation at despawn me->DespawnOrUnsummon(1ms); } - }; + } + + void JustDied(Unit* /*killer*/) override + { + me->SetDisplayId(11686); // prevents nasty falling animation at despawn + me->DespawnOrUnsummon(1ms); + } }; class go_the_focusing_iris : public GameObjectScript @@ -1567,15 +1478,15 @@ class spell_wyrmrest_skytalon_ride_red_dragon_buddy_trigger : public SpellScript void AddSC_boss_malygos() { - new boss_malygos(); - new npc_power_spark(); - new npc_vortex_ride(); - new npc_alexstrasza(); + RegisterEoECreatureAI(boss_malygos); + RegisterEoECreatureAI(npc_power_spark); + RegisterEoECreatureAI(npc_vortex_ride); + RegisterEoECreatureAI(npc_alexstrasza); new go_the_focusing_iris(); - new npc_nexus_lord(); - new npc_scion_of_eternity(); - new npc_hover_disk(); - new npc_eoe_wyrmrest_skytalon(); + RegisterEoECreatureAI(npc_nexus_lord); + RegisterEoECreatureAI(npc_scion_of_eternity); + RegisterEoECreatureAI(npc_hover_disk); + RegisterEoECreatureAI(npc_eoe_wyrmrest_skytalon); RegisterSpellScript(spell_wyrmrest_skytalon_summon_red_dragon_buddy); RegisterSpellScript(spell_wyrmrest_skytalon_ride_red_dragon_buddy_trigger); 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 cfdac7ee6..77a4f7c46 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h @@ -105,20 +105,11 @@ const Position Phase2NorthPos = {837.22f, 1301.676f, 296.10f, M_PI}; const uint32 MalygosIntroIntervals[] = {18000, 19000, 21000, 18000, 15000}; -class EoEDrakeEnterVehicleEvent : public BasicEvent -{ -public: - EoEDrakeEnterVehicleEvent(Creature& owner, ObjectGuid playerGUID) : _owner(owner), _playerGUID(playerGUID) { } - bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override; -private: - Creature& _owner; - ObjectGuid _playerGUID; -}; - template inline AI* GetEyeOfEternityAI(T* obj) { return GetInstanceAI(obj, EyeOfEternityScriptName); } +#define RegisterEoECreatureAI(ai_name) RegisterCreatureAIWithFactory(ai_name, GetEyeOfEternityAI) #endif