Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
boss_malygos.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6/* Script Data Start
7SDName: Boss Malygos
8Script Data End */
9
10#include "ScriptMgr.h"
11#include "ScriptedCreature.h"
12#include "SpellScript.h"
13#include "SpellAuraEffects.h"
14#include "eye_of_eternity.h"
15#include "Player.h"
16#include "Vehicle.h"
17#include "CombatAI.h"
18#include "GameObjectAI.h"
19#include "CreatureTextMgr.h"
20#include "MoveSplineInit.h"
21
23{
24 // =========== INTRO BEFORE WE START ENCOUNTER ===============
29
30 // =========== PHASE ONE ===============
35
36 // =========== PHASE TWO ===============
46
47 // =========== PHASE THREE =============
51
52 // ========== MISC MECHANICS ===========
54 EVENT_MOVE_TO_VORTEX_POINT = 22, // This should be fixed someday in core, we can't call new movement from MovementInform
55 EVENT_START_FIRST_RANDOM_PORTAL = 23, // There is something that is still loading when we first enter instance and it breaks
56 // first visual cast of intro portal beam mechanic, so we need short delay from the event.
57 EVENT_DELAY_MOVE_TO_DESTROY_P = 24, // If Malygos is too close to destroy platform point and transition from II to III is hit,
58 // this event will be sheduled to start after 5 seconds so there is enough time for "dimension change".
59
60 // ============ NEXUS LORDS ============
64
65 // ======== SCIONS OF ETERNITY =========
67
68 // ======== WYRMREST SKYTALON ==========
70};
71
79
81{
82 // Intro
84 SPELL_PORTAL_BEAM = 56046, // Malygos cast on portal to activate it during PHASE_NOT_STARTED
85
86 // Phase I
88 SPELL_MALYGOS_BERSERK = 47008, // it's the berserk spell that will hit only Malygos after 10 min of 60670
95 SPELL_VORTEX_1 = 56237, // seems that frezze object animation
96 SPELL_VORTEX_2 = 55873, // visual effect
97 SPELL_VORTEX_3 = 56105, // this spell must handle all the script - casted by the boss and to himself
98 SPELL_VORTEX_6 = 73040, // teleport - (casted to all raid), caster vortex bunnies, targets players.
99
100 // Phase II
101 SPELL_TELEPORT_VISUAL_ONLY = 41232, // Light blue animation cast by arcane NPCs when spawned on Hover Disks
108 SPELL_ARCANE_OVERLOAD_1 = 56432, // casted by npc Arcane Overload ID: 30282
109 // SPELL_ARCANE_OVERLOAD_2 = 56435, // Triggered by 56432 - resizing target
110 // SPELL_ARCANE_OVERLOAD_3 = 56438, // Triggered by 56432 - damage reduction
112 // SPELL_SURGE_OF_POWER_TRIGGERED = 56548,
113 SPELL_ARCANE_SHOCK = 57058, // used by Nexus Lords
114 SPELL_HASTE = 57060, // used by Nexus Lords
115 SPELL_ARCANE_BARRAGE = 56397, // used by Scions of Eternity
116 SPELL_ARCANE_BARRAGE_DAMAGE = 63934, // the actual damage - cast by affected player by script spell
117
118 // Transition /II-III/
121 SPELL_SUMMON_RED_DRAGON_BUDDY_F_CAST = 58846, // After implicitly hit player targets they will force cast 56070 on self
125
126 // Phase III
133 SPELL_SURGE_OF_POWER_WARNING_SELECTOR_25 = 60939, // used in 25 player mode for selecting targets for warnings and then sends to actual spell
135
136 // Phase I and III
138
139 // Outro
141};
142
156
158{
160};
161
163{
164 // Needed for melee hover disks /when Nexus Lords die/
166};
167
169{
170 // Malygos
177
178 // Caster hover disk despawn action
180
181 // Nexus Lord's action used to shedule casting spell that determine disk's target to chase
183};
184
186{
187 // Malygos
193 // SAY_START_P_TWO = 5, // Unused by Blizzard for some reason on any version
199 // SAY_START_P_THREE = 11, // Unused by Blizzard for some reason on any version
208
209 // Alexstrasza
214
215 // Power Sparks
217};
218
219#define MAX_SUMMONS_PHASE_TWO_10MAN 6
220#define MAX_SUMMONS_PHASE_TWO_25MAN 12
221
222#define MAX_RANGE_HOVER_DISK_SPAWNPOINTS 8
224{
225 { 782.9821f, 1296.652f, 282.1114f, 0.0f },
226 { 764.3126f, 1328.871f, 282.3091f, 0.0f },
227 { 725.8506f, 1306.749f, 282.2698f, 0.0f },
228 { 744.5175f, 1274.396f, 282.3402f, 0.0f },
229 { 764.3936f, 1274.371f, 282.6011f, 0.0f },
230 { 779.3761f, 1316.166f, 282.1653f, 0.0f },
231 { 744.4915f, 1328.901f, 282.2112f, 0.0f },
232 { 729.2364f, 1287.328f, 282.4173f, 0.0f }
233};
234
235#define MAX_MELEE_HOVER_DISK_SPAWNPOINTS 4
237{
238 { 754.4617f, 1283.859f, 285.0522f, 0.0f },
239 { 771.7864f, 1301.853f, 285.0522f, 0.0f },
240 { 753.9635f, 1319.003f, 285.0522f, 0.0f },
241 { 736.4914f, 1301.683f, 285.0522f, 0.0f }
242};
243
244#define MAX_MELEE_HOVER_DISK_WAYPOINTS 16
246{
247 // First melee hover disk wps
248 { 766.2931f, 1312.904f, 277.0551f, 0.0f },
249 { 754.3397f, 1319.759f, 274.0536f, 0.0f },
250 { 742.1018f, 1312.714f, 270.1367f, 0.0f },
251 { 735.6851f, 1301.422f, 266.7208f, 0.0f },
252 // Second melee hover disk wps
253 { 742.6257f, 1313.471f, 275.9713f, 0.0f },
254 { 736.8845f, 1301.921f, 274.0264f, 0.0f },
255 { 742.6632f, 1289.951f, 269.8603f, 0.0f },
256 { 754.3682f, 1283.942f, 266.6098f, 0.0f },
257 // Third melee hover disk wps
258 { 742.2078f, 1290.518f, 276.2484f, 0.0f },
259 { 754.5398f, 1284.311f, 273.5815f, 0.0f },
260 { 766.5588f, 1290.345f, 269.6655f, 0.0f },
261 { 773.4768f, 1301.474f, 266.5821f, 0.0f },
262 // Forth melee hover disk wps
263 { 766.1189f, 1290.197f, 276.9436f, 0.0f },
264 { 771.9507f, 1301.602f, 273.9712f, 0.0f },
265 { 766.1253f, 1313.451f, 270.4991f, 0.0f },
266 { 754.5378f, 1319.399f, 266.6653f, 0.0f }
267};
268
269#define MAX_MALYGOS_POS 10
271{
272 { 754.544f, 1301.71f, 320.01f, 0.0f }, // Point destroy platform
273 { 754.393f, 1301.27f, 292.91f, 0.0f }, // Point Vortex
274 { 754.362f, 1301.61f, 266.17f, 0.0f }, // Point land after Vortex
275 { 754.695f, 1301.66f, 316.65f, 0.0f }, // Point Surge of Power phase II
276 { 755.681f, 1298.41f, 220.06f, 0.0f } // Point idle phase III
277};
278
279Position const AlexstraszaSpawnPos = { 854.551f, 1225.31f, 300.901f, 0.0f }; // Alexstrasza's spawn position
280Position const HeartOfMagicSpawnPos = { 755.351f, 1298.31f, 223.909f, 0.0f }; // Heart of Magic spawn position
281
282#define TEN_MINUTES (10*MINUTE*IN_MILLISECONDS)
283
288
290{
292};
293
295{
296 // Lights
302
303 // Data (setters/getters)
304 DATA_SUMMON_DEATHS = 0, // phase 2
306
307 // Target guids
308 DATA_LAST_OVERLOAD_GUID = 13, // used to store last Arcane Overload guid
310 // DATA_SECOND_SURGE_TARGET_GUID = 15,
311 // DATA_THIRD_SURGE_TARGET_GUID = 16,
313
315};
316
317// Used to check if summons guids come from vehicles
319{
320 public:
321 bool operator()(uint64 guid) { return IS_VEHICLE_GUID(guid); }
322};
323
325{
326public:
327 boss_malygos() : CreatureScript("boss_malygos") { }
328
329 struct boss_malygosAI : public BossAI
330 {
332 {
333 _despawned = false; // We determine if Malygos will be realocated to spawning position on reset triggered by boss despawn on evade
334 _flySpeed = me->GetSpeed(MOVE_FLIGHT); // Get initial fly speed, otherwise on each wipe fly speed would add up if we get it
335 }
336
338 {
339 // EnterEvadeMode and Reset() links are cut for the sake of properly functioning despawner.
340 if (!_despawned)
341 _Reset();
342
343 _summonDeaths = 0;
347 memset(_surgeTargetGUID, 0, sizeof(_surgeTargetGUID));
348
349 _killSpamFilter = false;
350 _canAttack = false;
351 _executingVortex = false;
353 _flyingOutOfPlatform = false;
357
358 me->SetDisableGravity(true);
360 // TO DO: find what in core is making boss slower than in retail (when correct speed data) or find missing movement flag update or forced spline change
361 me->SetSpeed(MOVE_FLIGHT, _flySpeed * 0.25f);
362 if (_despawned)
364
366 me->SetReactState(REACT_PASSIVE);
367 if (instance)
369 }
370
372 {
373 switch (data)
374 {
376 return _summonDeaths;
377 case DATA_PHASE:
378 return _phase;
379 }
380
381 return 0;
382 }
383
384 void SetData(uint32 data, uint32 value) OVERRIDE
385 {
386 if (data == DATA_SUMMON_DEATHS && _phase == PHASE_TWO && !_despawned)
387 {
388 _summonDeaths = value;
389
391 {
393 {
396 }
397 }
399 {
401 {
404 }
405 }
406 }
407 }
408
418
419 void SetGUID(uint64 guid, int32 type) OVERRIDE
420 {
421 switch (type)
422 {
424 _arcaneOverloadGUID = guid;
425 break;
430 break;
433 }
434 }
435
437 {
438 switch (action)
439 {
441 events.CancelEventGroup(1);
442 if (Creature* alexstraszaBunny = me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID)))
443 {
444 Position pos;
445 pos.m_positionZ = alexstraszaBunny->GetPositionZ();
446 alexstraszaBunny->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 30.0f, alexstraszaBunny->GetAngle(me));
447 me->GetMotionMaster()->MoveLand(POINT_LAND_P_ONE, pos);
449 me->SetReactState(REACT_AGGRESSIVE);
450 me->SetInCombatWithZone();
452 }
453 break;
455 DoCast(me, SPELL_VORTEX_1, true);
456 DoCast(me, SPELL_VORTEX_2, true);
457 // the vortex execution continues in the dummy effect of this spell (see it's script)
458 DoCast(me, SPELL_VORTEX_3, true);
459 break;
461 Position _zToLift;
462 me->GetPosition(&_zToLift);
463 if (_phase == PHASE_ONE)
464 {
465 _zToLift.m_positionZ += 20.0f;
466 me->GetMotionMaster()->MoveTakeoff(POINT_LIFT_IN_AIR_P_ONE, _zToLift);
467 }
468 else if (_phase == PHASE_TWO)
469 {
470 _zToLift.m_positionZ = 300.1f;
471 me->GetMotionMaster()->MoveTakeoff(POINT_PHASE_ONE_TO_TWO_TRANSITION, _zToLift);
472 }
473 break;
475 events.CancelEventGroup(0);
476 events.CancelEventGroup(1);
477 events.CancelEventGroup(2);
478 // Vehicles shouldn't be despawned with 0 delay if the call comes from virtual function that overrides PassengerBoarded.
479 // Aside from that he doesn't despawn both vehicles and arcane overloads right away, but with some delay.
481 summons.DoAction(ACTION_DELAYED_DESPAWN, pred);
483 me->GetMotionMaster()->Clear(false);
484 me->StopMoving();
485 if (me->GetPositionZ() > 300.0f)
487 else
488 me->GetMotionMaster()->MovePoint(POINT_DESTROY_PLATFORM_P_TWO, MalygosPositions[0]);
489
491 break;
493 // Teleport to spawn position, we can't use normal relocate
494 float x, y, z, o;
495 me->GetRespawnPosition(x, y, z, &o);
496 me->NearTeleportTo(x, y, z, o);
497 // Respawn Iris
498 instance->SetData(DATA_RESPAWN_IRIS, 0);
499 _despawned = false;
500 break;
503 FillCirclePath(MalygosPositions[3], 120.0f, 283.2763f, init.Path(), true);
504 init.SetFly();
505 init.SetCyclic();
506 init.Launch();
507 break;
508 }
509 }
510
511 void SetPhase(uint8 phase, bool setEvents = false)
512 {
513 events.Reset();
514 events.SetPhase(phase);
515 _phase = phase;
516 if (setEvents)
518 }
519
521 {
522 switch (_phase)
523 {
525 events.ScheduleEvent(EVENT_SAY_INTRO, 1*IN_MILLISECONDS, 1, _phase);
527 break;
528 case PHASE_ONE:
529 events.ScheduleEvent(EVENT_ARCANE_BREATH, std::rand() % (10 * IN_MILLISECONDS) + (8 * IN_MILLISECONDS), 0, _phase);
530 events.ScheduleEvent(EVENT_ARCANE_STORM, std::rand() % (6 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS), 0, _phase);
531 events.ScheduleEvent(EVENT_VORTEX, std::rand() % (35 * IN_MILLISECONDS) + (30 * IN_MILLISECONDS), 0, _phase);
532 events.ScheduleEvent(EVENT_POWER_SPARKS, std::rand() % (30 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS), 0, _phase);
533 break;
534 case PHASE_TWO:
536 me->AI()->DoAction(ACTION_LIFT_IN_AIR);
537 break;
538 case PHASE_THREE:
539 events.ScheduleEvent(EVENT_ARCANE_PULSE, 7*IN_MILLISECONDS, 0, _phase);
540 events.ScheduleEvent(EVENT_ARCANE_STORM, 10*IN_MILLISECONDS, 0, _phase);
541 events.ScheduleEvent(EVENT_SURGE_OF_POWER_P_THREE, std::rand() % (6 * IN_MILLISECONDS) + (4 * IN_MILLISECONDS), 0, _phase);
542 events.ScheduleEvent(EVENT_STATIC_FIELD, std::rand() % (30 * IN_MILLISECONDS) + (20 * IN_MILLISECONDS), 0, _phase);
543 break;
544 }
545 }
546
547 // There are moments where boss will do nothing while being attacked
549 {
550 if (_canAttack)
551 BossAI::AttackStart(target);
552 }
553
554 void EnterCombat(Unit* /*who*/) OVERRIDE
555 {
556 // We can't call full function here since it includes DoZoneInCombat(),
557 // if someone does it will be returned with a warning.
558 me->setActive(true);
559 if (instance)
560 {
561 if (!instance->CheckRequiredBosses(DATA_MALYGOS_EVENT))
562 {
564 return;
565 }
566
568 }
569
571 DoCast(SPELL_BERSERK); // periodic aura, first tick in 10 minutes
572 if (instance)
574 }
575
577 {
578 if (instance)
579 instance->SetBossState(DATA_MALYGOS_EVENT, FAIL);
580
582
583 if (_phase == PHASE_THREE)
584 me->SetControlled(false, UNIT_STATE_ROOT);
585
586 uint32 corpseDelay = me->GetCorpseDelay();
587 uint32 respawnDelay = me->GetRespawnDelay();
588 me->SetCorpseDelay(1);
589 me->SetRespawnDelay(29);
590 me->DespawnOrUnsummon();
591 me->SetCorpseDelay(corpseDelay);
592 me->SetRespawnDelay(respawnDelay);
593
594 // Set speed to normal value
595 me->SetSpeed(MOVE_FLIGHT, _flySpeed);
598 me->RemoveAllAuras();
599 me->CombatStop(); // Sometimes threat can remain, so it's a safety measure
600
601 if (!_despawned)
602 _despawned = true;
603
604 me->ResetLootMode();
605 events.Reset();
606 if (!summons.empty())
607 {
608 if (_phase == PHASE_TWO)
609 {
611 summons.DoAction(ACTION_DELAYED_DESPAWN, pred);
612 summons.DespawnIf(pred);
613 summons.DespawnAll();
614 }
615 else if (_phase == PHASE_THREE)
616 summons.DespawnAll();
617 }
618
619 if (instance)
621 }
622
624 {
625 if (victim->GetTypeId() != TypeID::TYPEID_PLAYER)
626 return;
627
628 if (!_killSpamFilter)
629 {
630 switch (_phase)
631 {
632 case PHASE_ONE:
635 _killSpamFilter = true;
636 break;
637 case PHASE_TWO:
640 _killSpamFilter = true;
641 break;
642 case PHASE_THREE:
645 _killSpamFilter = true;
646 break;
647 }
648 }
649 }
650
651 void SpellHit(Unit* caster, SpellInfo const* spell) OVERRIDE
652 {
653 if (spell->Id == SPELL_POWER_SPARK_MALYGOS)
654 {
655 if (Creature* creature = caster->ToCreature())
656 creature->DespawnOrUnsummon();
657
659 }
660 else if (spell->Id == SPELL_MALYGOS_BERSERK)
662 }
663
665
666 {
667 if (!me->IsInCombat() || _phase != PHASE_ONE)
668 return;
669
670 if (who->GetEntry() == NPC_POWER_SPARK)
671 if (who->GetDistance(me) <= 2.5f)
672 who->CastSpell(me, SPELL_POWER_SPARK_MALYGOS, true);
673 }
674
676 {
677 if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE)
678 return;
679
680 switch (id)
681 {
683 if (Creature* portal = me->FindNearestCreature(NPC_PORTAL_TRIGGER, 31.0f, true))
684 {
687 DoCast(portal, SPELL_PORTAL_BEAM);
688 }
689 break;
690 case POINT_LAND_P_ONE:
691 me->SetDisableGravity(false);
692 break;
694 me->GetMotionMaster()->MoveIdle();
696 break;
698 me->SetDisableGravity(false);
699 _executingVortex = false;
700 _canAttack = true;
701 break;
703 me->SetDisableGravity(true);
704 events.ScheduleEvent(EVENT_MOVE_TO_VORTEX_POINT, 1, 0, PHASE_ONE);
705 break;
708 {
711 me->SetFacingToObject(me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID)));
713 }
714 _flyingOutOfPlatform = false;
717 break;
719 me->SetDisableGravity(true);
720 me->SetFacingToObject(me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID)));
723 break;
726 {
730 }
731 break;
736 break;
738 me->SetControlled(true, UNIT_STATE_ROOT);
740 break;
741 }
742 }
743
745 {
747 return;
748
749 events.Update(diff);
750
751 // we can't cast if we are casting already unless in PHASE_NOT_STARTED channeling PORTAL_BEAM
752 if (me->HasUnitState(UNIT_STATE_CASTING) && _phase != PHASE_NOT_STARTED)
753 return;
754
755 // at 50% hp Malygos switchs to phase 2 and removes hovering until reset or end of encounter
756 if (_phase == PHASE_ONE && me->GetHealthPct() <= 50.0f)
757 {
758 SetPhase(PHASE_TWO, true);
759 _canAttack = false;
760 me->AttackStop();
762 }
763
764 while (uint32 eventId = events.ExecuteEvent())
765 {
766 switch (eventId)
767 {
769 me->CastCustomSpell(SPELL_RANDOM_PORTAL, SPELLVALUE_MAX_TARGETS, 1);
770 break;
772 me->InterruptNonMeleeSpells(true);
773 break;
775 me->CastCustomSpell(SPELL_RANDOM_PORTAL, SPELLVALUE_MAX_TARGETS, 1);
776 break;
778 if (GameObject* iris = me->GetMap()->GetGameObject(instance->GetData64(DATA_FOCUSING_IRIS_GUID)))
779 {
780 me->SetFacingToObject(iris);
781 iris->Delete(); // this is not the best way.
782 }
783 _canAttack = true;
784 SetPhase(PHASE_ONE, true);
785 break;
786 case EVENT_SAY_INTRO:
788 events.ScheduleEvent(EVENT_SAY_INTRO, std::rand() % (95 * IN_MILLISECONDS) + (85 * IN_MILLISECONDS), 1, PHASE_NOT_STARTED);
789 break;
790 case EVENT_VORTEX:
791 _executingVortex = true;
793 events.ScheduleEvent(EVENT_VORTEX, std::rand() % (80 * IN_MILLISECONDS) + (60 * IN_MILLISECONDS), 0, PHASE_ONE);
794 break;
796 _canAttack = false;
797 me->AttackStop();
798 me->GetMotionMaster()->MovePoint(POINT_VORTEX_P_ONE, MalygosPositions[1]);
799 break;
802 events.ScheduleEvent(EVENT_POWER_SPARKS, std::rand() % (35 * IN_MILLISECONDS) + (30 * IN_MILLISECONDS), 0, PHASE_ONE);
803 break;
806 {
808 break;
809 }
810
811 me->CastSpell(me->GetVictim(), SPELL_ARCANE_BREATH);
813 break;
815 if (_phase == PHASE_ONE)
816 {
818 {
819 events.ScheduleEvent(EVENT_ARCANE_STORM, 10*IN_MILLISECONDS, 0, PHASE_ONE);
820 break;
821 }
822
824 events.ScheduleEvent(EVENT_ARCANE_STORM, 10*IN_MILLISECONDS, 0, PHASE_ONE);
825 }
826 else if (_phase == PHASE_THREE)
827 {
829 events.ScheduleEvent(EVENT_ARCANE_STORM, std::rand() % (12 * IN_MILLISECONDS) + (6 * IN_MILLISECONDS), 0, PHASE_THREE);
830 }
831 break;
834 {
835 if (Creature* alexstraszaBunny = me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID)))
836 {
837 Position randomPosOnRadius;
838 // Hardcodded retail value, reason is Z getters can fail... (TO DO: Change to getter when height calculation works on 100%!)
839 randomPosOnRadius.m_positionZ = 283.0521f;
840 alexstraszaBunny->GetNearPoint2D(randomPosOnRadius.m_positionX, randomPosOnRadius.m_positionY, 120.0f, alexstraszaBunny->GetAngle(me));
841 me->GetMotionMaster()->MovePoint(POINT_FLY_OUT_OF_PLATFORM_P_TWO, randomPosOnRadius);
843 }
844 }
845
847 {
848 for (uint8 rangeDisks = 0; rangeDisks < (GetDifficulty() == DIFFICULTY_10MAN_NORMAL ? 4 : 5); rangeDisks++)
849 {
850 Creature* casterDiskSummon = me->SummonCreature(NPC_HOVER_DISK_CASTER, RangeHoverDisksSpawnPositions[rangeDisks]);
851
852 if (casterDiskSummon->IsAIEnabled)
853 casterDiskSummon->AI()->DoAction(rangeDisks);
854 }
855
856 for (uint8 meleeDisks = 0; meleeDisks < 2; meleeDisks++)
857 {
858 Creature* meleeDiskSummon = me->SummonCreature(NPC_HOVER_DISK_MELEE, MeleeHoverDisksSpawnPositions[meleeDisks]);
860 }
861
862 _arcaneReinforcements = false;
863
866 }
867 break;
869 for (uint8 rangeDisks = 5; rangeDisks < 8; rangeDisks++)
870 {
871 Creature* casterDiskSummon = me->SummonCreature(NPC_HOVER_DISK_CASTER, RangeHoverDisksSpawnPositions[rangeDisks]);
872
873 if (casterDiskSummon->IsAIEnabled)
874 casterDiskSummon->AI()->DoAction(rangeDisks);
875 }
876
877 for (uint8 meleeDisks = 2; meleeDisks < 4; meleeDisks++)
878 {
879 Creature* meleeDiskSummon = me->SummonCreature(NPC_HOVER_DISK_MELEE, MeleeHoverDisksSpawnPositions[meleeDisks]);
881 }
882 break;
886 break;
889 {
892 me->GetMotionMaster()->MovePoint(POINT_SURGE_OF_POWER_P_TWO, MalygosPositions[3]);
894 }
895 break;
898 {
899 me->StopMoving();
901 }
902
904 {
906 if (Creature* lastArcaneOverloadBunny = me->GetMap()->GetCreature(_arcaneOverloadGUID))
907 DoCast(lastArcaneOverloadBunny, SPELL_ARCANE_BOMB_TRIGGER, true);
908 }
909 events.ScheduleEvent(EVENT_SUMMON_ARCANE_BOMB, std::rand() % (16 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS), 2, PHASE_TWO);
910 break;
913 {
917 }
918 else
919 {
922 }
923 break;
926 break;
928 me->GetMotionMaster()->MovePoint(POINT_DESTROY_PLATFORM_P_TWO, MalygosPositions[0]);
929 break;
932 me->GetMotionMaster()->MovePoint(POINT_IDLE_P_THREE, MalygosPositions[4]);
933 break;
938 _canAttack = true;
939 UpdateVictim();
941 SetPhase(PHASE_THREE, true);
942 break;
945 {
946 if (Unit* tempSurgeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, SPELL_RIDE_RED_DRAGON_BUDDY))
947 {
948 if (Vehicle* drakeVehicle = tempSurgeTarget->GetVehicleKit())
949 {
950 if (Unit* passenger = drakeVehicle->GetPassenger(0))
951 {
952 if (passenger->GetTypeId() == TypeID::TYPEID_PLAYER)
953 {
955 DoCast(tempSurgeTarget, SPELL_SURGE_OF_POWER_PHASE_3_10, true);
956 }
957 }
958 }
959 }
960 }
962 {
963 memset(_surgeTargetGUID, 0, sizeof(_surgeTargetGUID));
965 }
966
967 events.ScheduleEvent(EVENT_SURGE_OF_POWER_P_THREE, std::rand() % (18 * IN_MILLISECONDS) + (9 * IN_MILLISECONDS), 0, PHASE_THREE);
968 break;
970 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 60.0f, false, SPELL_RIDE_RED_DRAGON_BUDDY))
971 DoCast(target, SPELL_STATIC_FIELD_MISSLE, true);
972
973 events.ScheduleEvent(EVENT_STATIC_FIELD, std::rand() % (30 * IN_MILLISECONDS) + (15 * IN_MILLISECONDS), 0, PHASE_THREE);
974 break;
976 _killSpamFilter = false;
977 break;
978 default:
979 break;
980 }
981 }
982
983 if (_phase != PHASE_THREE)
985 }
986
987 void JustDied(Unit* /*killer*/) OVERRIDE
988 {
989 _JustDied();
991 if (Creature* alexstraszaGiftBoxBunny = me->GetMap()->GetCreature(instance->GetData64(DATA_GIFT_BOX_BUNNY_GUID)))
992 {
994 alexstraszaGiftBoxBunny->SummonGameObject(GO_HEART_OF_MAGIC_10, HeartOfMagicSpawnPos.GetPositionX(), HeartOfMagicSpawnPos.GetPositionY(),
995 HeartOfMagicSpawnPos.GetPositionZ(), HeartOfMagicSpawnPos.GetOrientation(), 0.0f, 0.0f, 0.0f, 1.0f, 0);
997 alexstraszaGiftBoxBunny->SummonGameObject(GO_HEART_OF_MAGIC_25, HeartOfMagicSpawnPos.GetPositionX(), HeartOfMagicSpawnPos.GetPositionY(),
998 HeartOfMagicSpawnPos.GetPositionZ(), HeartOfMagicSpawnPos.GetOrientation(), 0.0f, 0.0f, 0.0f, 1.0f, 0);
999 }
1000
1002 me->DespawnOrUnsummon(5*IN_MILLISECONDS);
1003 }
1004
1005 private:
1006 // Used to generate perfect cyclic movements (Enter Circle).
1007 void FillCirclePath(Position const& centerPos, float radius, float z, Movement::PointsArray& path, bool clockwise)
1008 {
1009 float step = clockwise ? -M_PI / 8.0f : M_PI / 8.0f;
1010 float angle = centerPos.GetAngle(me->GetPositionX(), me->GetPositionY());
1011
1012 for (uint8 i = 0; i < 16; angle += step, ++i)
1013 {
1014 G3D::Vector3 point;
1015 point.x = centerPos.GetPositionX() + radius * cosf(angle);
1016 point.y = centerPos.GetPositionY() + radius * sinf(angle);
1017 point.z = z; // Don't use any height getters unless all bugs are fixed.
1018 path.push_back(point);
1019 }
1020 }
1021
1022 // Function that will change lights of map for all players on map.
1023 void SendLightOverride(uint32 overrideId, uint32 fadeInTime) const
1024 {
1026 data << uint32(1773); // Light.dbc entry (map default)
1027 data << uint32(overrideId); // Light.dbc entry (override)
1028 data << uint32(fadeInTime);
1029 SendPacketToPlayers(&data);
1030 }
1031
1032 // Send packet to all players in Eye of Eternity
1033 void SendPacketToPlayers(WorldPacket const* data) const
1034 {
1035 Map::PlayerList const& players = me->GetMap()->GetPlayers();
1036 if (!players.isEmpty())
1037 for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
1038 if (Player* player = itr->GetSource())
1039 if (player->GetAreaId() == AREA_EYE_OF_ETERNITY)
1040 player->GetSession()->SendPacket(data);
1041 }
1042
1043 uint8 _phase; // Counter for phases used with a getter.
1044 uint8 _summonDeaths; // Keeps count of arcane trash.
1045 uint8 _preparingPulsesChecker; // In retail they use 2 preparing pulses with 7 sec CD, after they pass 2 seconds.
1046 uint64 _arcaneOverloadGUID; // Last Arcane Overload summoned to know to which should visual be cast to (the purple ball, not bubble).
1047 uint64 _lastHitByArcaneBarrageGUID; // Last hit player by Arcane Barrage, will be removed if targets > 1.
1048 uint64 _surgeTargetGUID[3]; // All these three are used to keep current tagets to which warning should be sent.
1049
1050 bool _killSpamFilter; // Prevent text spamming on killed player by helping implement a CD.
1051 bool _canAttack; // Used to control attacking (Move Chase not being applied after Stop Attack, only few times should act like this).
1052 bool _despawned; // Checks if boss pass through evade on reset.
1053 bool _executingVortex; // Prevents some events being sheduled during Vortex takeoff/land.
1054 bool _arcaneReinforcements; // Checks if 10 or 25 man arcane trash will be spawned.
1055 bool _flyingOutOfPlatform; // Used to prevent Malygos casting Arcane Overload shields while leaving platform.
1056 bool _firstCyclicMovementStarted; // At first movement start he throws one shield asap, so this check is needed for it only.
1057 bool _performingSurgeOfPower; // Used to prevent starting Cyclic Movement called in Arcane Bomb event.
1058 bool _performingDestroyPlatform; // Used to prevent starting some movements right when Destroy Platfrom event starts.
1059
1060 float _flySpeed; // Used to store base fly speed to prevent stacking on each evade.
1061 };
1062
1064 {
1065 return new boss_malygosAI(creature);
1066 }
1067};
1068
1070{
1071public:
1072 npc_portal_eoe() : CreatureScript("npc_portal_eoe") { }
1073
1075 {
1076 npc_portal_eoeAI(Creature* creature) : ScriptedAI(creature)
1077 {
1078 _instance = creature->GetInstanceScript();
1079 }
1080
1081 void SpellHit(Unit* /*caster*/, SpellInfo const* spell) OVERRIDE
1082 {
1083 if (spell->Id == SPELL_PORTAL_OPENED)
1084 {
1085 if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS)))
1086 {
1087 if (malygos->AI()->GetData(DATA_PHASE) == PHASE_ONE)
1089 }
1090 }
1091 }
1092
1093 void UpdateAI(uint32 /*diff*/) OVERRIDE
1094 {
1095 // When duration of opened riff visual ends, closed one should be cast
1096 if (!me->HasAura(SPELL_PORTAL_VISUAL_CLOSED) && !me->HasAura(SPELL_PORTAL_OPENED))
1098
1099 if (_instance)
1100 {
1101 if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS)))
1102 {
1103 if (malygos->AI()->GetData(DATA_PHASE) != PHASE_ONE && me->HasAura(SPELL_PORTAL_OPENED))
1104 {
1105 me->RemoveAura(SPELL_PORTAL_OPENED);
1107 }
1108 }
1109 }
1110 }
1111
1112 private:
1114 };
1115
1117 {
1118 return new npc_portal_eoeAI(creature);
1119 }
1120};
1121
1123{
1124public:
1125 npc_power_spark() : CreatureScript("npc_power_spark") { }
1126
1128 {
1130 {
1131 _instance = creature->GetInstanceScript();
1132 // Talk range was not enough for this encounter
1134 MoveToMalygos();
1135 }
1136
1138 {
1139 me->GetMotionMaster()->MoveIdle();
1140
1141 if (_instance)
1142 if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS)))
1143 me->GetMotionMaster()->MoveFollow(malygos, 0.0f, 0.0f);
1144 }
1145
1146 void UpdateAI(uint32 /*diff*/) OVERRIDE
1147 {
1148 if (!_instance)
1149 return;
1150
1151 if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS)))
1152 {
1153 if (malygos->AI()->GetData(DATA_PHASE) != PHASE_ONE || _instance->GetBossState(DATA_MALYGOS_EVENT) == FAIL)
1154 {
1155 me->DespawnOrUnsummon();
1156 return;
1157 }
1158
1159 if (malygos->HasAura(SPELL_VORTEX_1))
1160 {
1161 me->GetMotionMaster()->MoveIdle();
1162 return;
1163 }
1164
1165 if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
1166 me->GetMotionMaster()->MoveFollow(malygos, 0.0f, 0.0f);
1167 }
1168 }
1169
1170 void JustDied(Unit* /*killer*/) OVERRIDE
1171 {
1172 me->CastSpell(me, SPELL_POWER_SPARK_DEATH, true); // not supposed to hide the fact it's there by not selectable
1173 }
1174
1175 private:
1177 };
1178
1180 {
1181 return new npc_power_sparkAI(creature);
1182 }
1183};
1184
1186{
1187public:
1188 npc_melee_hover_disk() : CreatureScript("npc_melee_hover_disk") { }
1189
1191 {
1193 {
1194 _instance = creature->GetInstanceScript();
1195 me->SetReactState(REACT_PASSIVE);
1196 // TO DO: These were a bit faster than what they should be. Not sure what is the reason.
1197 me->SetSpeed(MOVE_FLIGHT, 1.25f);
1198 }
1199
1201 {
1203
1204 _wpCount = 0;
1205 }
1206
1207 void PassengerBoarded(Unit* unit, int8 /*seat*/, bool apply) OVERRIDE
1208 {
1209 if (apply)
1210 {
1211 if (unit->GetTypeId() == TypeID::TYPEID_UNIT)
1212 {
1213 unit->CastSpell(unit, SPELL_TELEPORT_VISUAL_ONLY);
1214 unit->ToCreature()->SetInCombatWithZone();
1215 }
1216 else if (unit->GetTypeId() == TypeID::TYPEID_PLAYER)
1217 me->SetDisableGravity(true);
1218 }
1219 else if (!apply)
1220 {
1221 if (unit->GetTypeId() != TypeID::TYPEID_PLAYER)
1222 {
1223 me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation());
1225 me->SetDisableGravity(false);
1226 me->SetCanFly(false);
1227 }
1228 else if (unit->GetTypeId() == TypeID::TYPEID_PLAYER)
1229 {
1230 me->SetDisableGravity(false);
1231 me->SetCanFly(false);
1232 }
1233
1234 me->setFaction(FACTION_FRIENDLY);
1235 me->RemoveAllAuras();
1236 }
1237 }
1238
1240 {
1241 _events.Update(diff);
1242
1243 while (uint32 eventId = _events.ExecuteEvent())
1244 me->GetMotionMaster()->MovePoint(eventId, MeleeHoverDisksWaypoints[eventId]);
1245 }
1246
1247 void DoAction(int32 /*action*/) OVERRIDE
1248 {
1249 if (Vehicle* vehicleTemp = me->GetVehicleKit())
1250 {
1251 if (vehicleTemp->GetPassenger(0) && vehicleTemp->GetPassenger(0)->GetTypeId() == TypeID::TYPEID_PLAYER)
1252 {
1253 vehicleTemp->RemoveAllPassengers();
1255 }
1256 }
1257 me->DespawnOrUnsummon(3*IN_MILLISECONDS);
1258 }
1259
1261 {
1262 if (type != POINT_MOTION_TYPE)
1263 return;
1264
1265 if (_wpCount < 3)
1266 {
1267 _events.ScheduleEvent(id + 1, 1);
1268 ++_wpCount;
1269 }
1270 else if (Vehicle* hoverDisk = me->GetVehicleKit())
1271 if (Unit* lordPassenger = hoverDisk->GetPassenger(0))
1272 if (Creature* lordCreature = lordPassenger->ToCreature())
1273 if (lordCreature->AI())
1274 lordCreature->AI()->DoAction(ACTION_SET_DISK_VICTIM_CHASE);
1275 }
1276
1277 private:
1278 uint8 _wpCount; // how many points are triggered
1281 };
1282
1284 {
1285 return new npc_melee_hover_diskAI(creature);
1286 }
1287};
1288
1290{
1291public:
1292 npc_caster_hover_disk() : CreatureScript("npc_caster_hover_disk") { }
1293
1295 {
1297 {
1298 _instance = creature->GetInstanceScript();
1299 me->SetReactState(REACT_PASSIVE);
1300 // TO DO: Something is wrong with calculations for flying creatures that are on WP/Cyclic path.
1301 // They should get the same difference as to when at ground from run creature switch to walk.
1302 me->SetSpeed(MOVE_FLIGHT, 0.45f);
1303 }
1304
1306 {
1308 }
1309
1311 {
1312 }
1313
1314 void PassengerBoarded(Unit* unit, int8 /*seat*/, bool apply) OVERRIDE
1315 {
1316 if (apply)
1317 {
1318 if (unit->GetTypeId() == TypeID::TYPEID_UNIT)
1319 unit->CastSpell(unit, SPELL_TELEPORT_VISUAL_ONLY);
1320 }
1321 else if (!apply)
1322 {
1323 me->StopMoving();
1324 me->SetDisableGravity(false);
1325 me->SetCanFly(false);
1326 me->RemoveAllAuras();
1327 }
1328 }
1329
1331 {
1332 if (action < ACTION_DELAYED_DESPAWN)
1333 {
1335 FillCirclePath(MalygosPositions[3], 35.0f, 282.3402f, init.Path(), true);
1336 init.SetFly();
1337 init.SetCyclic();
1338 init.Launch();
1339 }
1340 else
1341 {
1342 me->DespawnOrUnsummon(3*IN_MILLISECONDS);
1343 }
1344 }
1345
1346 private:
1347 void FillCirclePath(Position const& centerPos, float radius, float z, Movement::PointsArray& path, bool clockwise)
1348 {
1349 float step = clockwise ? -M_PI / 9.0f : M_PI / 9.0f;
1350 float angle = centerPos.GetAngle(me->GetPositionX(), me->GetPositionY());
1351
1352 for (uint8 i = 0; i < 18; angle += step, ++i)
1353 {
1354 G3D::Vector3 point;
1355 point.x = centerPos.GetPositionX() + radius * cosf(angle);
1356 point.y = centerPos.GetPositionY() + radius * sinf(angle);
1357 point.z = z; // Don't use any height getters unless all bugs are fixed.
1358 path.push_back(point);
1359 }
1360 }
1361
1363 };
1364
1366 {
1367 return new npc_caster_hover_diskAI(creature);
1368 }
1369};
1370
1372{
1373 public:
1374 npc_nexus_lord() : CreatureScript("npc_nexus_lord") { }
1375
1377 {
1378 npc_nexus_lordAI(Creature* creature) : ScriptedAI(creature)
1379 {
1380 _instance = creature->GetInstanceScript();
1381 }
1382
1384 {
1385 _events.Reset();
1386 }
1387
1389 {
1390 }
1391
1392 void DoAction(int32 /*action*/) OVERRIDE
1393 {
1394 _events.ScheduleEvent(EVENT_NUKE_DUMMY, 1);
1395 _events.ScheduleEvent(EVENT_ARCANE_SHOCK, 2*IN_MILLISECONDS);
1396 _events.ScheduleEvent(EVENT_HASTE_BUFF, 12*IN_MILLISECONDS);
1397 }
1398
1400 {
1401 if (!UpdateVictim())
1402 return;
1403
1404 _events.Update(diff);
1405
1406 while (uint32 eventId = _events.ExecuteEvent())
1407 {
1408 switch (eventId)
1409 {
1410 case EVENT_ARCANE_SHOCK:
1411 if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 5.0f, true))
1412 DoCast(victim, SPELL_ARCANE_SHOCK);
1413 _events.ScheduleEvent(EVENT_ARCANE_SHOCK, std::rand() % (15 * IN_MILLISECONDS) + (7 * IN_MILLISECONDS));
1414 break;
1415 case EVENT_HASTE_BUFF:
1417 _events.ScheduleEvent(EVENT_HASTE_BUFF, 15*IN_MILLISECONDS);
1418 break;
1419 case EVENT_NUKE_DUMMY:
1422 _events.ScheduleEvent(EVENT_NUKE_DUMMY, 1*IN_MILLISECONDS);
1423 break;
1424 }
1425 }
1426
1428 }
1429
1430 void JustDied(Unit* /*killer*/) OVERRIDE
1431 {
1432 if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS)))
1433 malygos->AI()->SetData(DATA_SUMMON_DEATHS, malygos->AI()->GetData(DATA_SUMMON_DEATHS) + 1);
1434 }
1435
1436 private:
1439 };
1440
1442 {
1443 return new npc_nexus_lordAI(creature);
1444 }
1445};
1446
1448{
1449 public:
1450 npc_scion_of_eternity() : CreatureScript("npc_scion_of_eternity") { }
1451
1453 {
1455 {
1456 _instance = creature->GetInstanceScript();
1457 }
1458
1460 {
1461 _events.Reset();
1462 }
1463
1464 void IsSummonedBy(Unit* /*summoner*/) OVERRIDE
1465 {
1466 _events.ScheduleEvent(EVENT_ARCANE_BARRAGE, std::rand() % (29 * IN_MILLISECONDS) + (14 * IN_MILLISECONDS));
1467 }
1468
1470 {
1471 }
1472
1473 void AttackStart(Unit* /*target*/) OVERRIDE
1474 {
1475 }
1476
1478 {
1479 }
1480
1482 {
1483 _events.Update(diff);
1484
1485 while (uint32 eventId = _events.ExecuteEvent())
1486 {
1487 switch (eventId)
1488 {
1491 _events.ScheduleEvent(EVENT_ARCANE_BARRAGE, std::rand() % (15 * IN_MILLISECONDS) + (3 * IN_MILLISECONDS));
1492 break;
1493 }
1494 }
1495 }
1496
1497 void JustDied(Unit* /*killer*/) OVERRIDE
1498 {
1499 if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS)))
1500 malygos->AI()->SetData(DATA_SUMMON_DEATHS, malygos->AI()->GetData(DATA_SUMMON_DEATHS) + 1);
1501 }
1502
1503 private:
1506 };
1507
1509 {
1510 return new npc_scion_of_eternityAI(creature);
1511 }
1512};
1513
1515{
1516public:
1517 npc_arcane_overload() : CreatureScript("npc_arcane_overload") { }
1518
1520 {
1522 {
1523 _instance = creature->GetInstanceScript();
1524 me->SetReactState(REACT_PASSIVE);
1525 }
1526
1528 {
1529 if (Creature* creature = summoner->ToCreature())
1530 {
1531 _malygos = creature;
1532 _malygos->AI()->SetGUID(me->GetGUID(), DATA_LAST_OVERLOAD_GUID);
1533 }
1534 }
1535
1536 void UpdateAI(uint32 /*diff*/) OVERRIDE
1537 {
1538 }
1539
1540 void DoAction(int32 /*action*/) OVERRIDE
1541 {
1542 if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS)))
1543 {
1544 if (malygos->AI()->GetData(DATA_PHASE) == PHASE_TWO)
1545 me->DespawnOrUnsummon(6*IN_MILLISECONDS);
1546 // If evade is hit during phase II shields should disappear with no delay
1547 else if (malygos->AI()->GetData(DATA_PHASE) == 0)
1548 me->DespawnOrUnsummon();
1549 }
1550 }
1551
1552 void SpellHit(Unit* /*caster*/, SpellInfo const* spell) OVERRIDE
1553 {
1554 if (spell->Id == SPELL_ARCANE_BOMB_TRIGGER)
1555 {
1558 }
1559 }
1560
1561 private:
1564 };
1565
1567 {
1568 return new npc_arcane_overloadAI(creature);
1569 }
1570};
1571
1572// SmartAI does not work correctly for vehicles
1574{
1575public:
1576 npc_wyrmrest_skytalon() : CreatureScript("npc_wyrmrest_skytalon") { }
1577
1579 {
1581 {
1582 }
1583
1585 {
1586 _summoner = NULL;
1587 if (Player* player = summoner->ToPlayer())
1588 {
1589 _summoner = player;
1591 }
1592 }
1593
1595 {
1596 VehicleAI::UpdateAI(diff);
1597 _events.Update(diff);
1598
1599 while (uint32 eventId = _events.ExecuteEvent())
1600 {
1601 switch (eventId)
1602 {
1604 me->CastSpell(_summoner, SPELL_RIDE_RED_DRAGON_TRIGGERED, true);
1605 break;
1606 }
1607 }
1608 }
1609
1610 void PassengerBoarded(Unit* /*unit*/, int8 /*seat*/, bool apply) OVERRIDE
1611 {
1612 if (!apply)
1613 {
1614 me->DespawnOrUnsummon(2050);
1615 me->SetOrientation(2.5f);
1616 me->SetSpeed(MOVE_FLIGHT, 1.0f, true);
1617 Position pos;
1618 me->GetPosition(&pos);
1619 pos.m_positionX += 10.0f;
1620 pos.m_positionY += 10.0f;
1621 pos.m_positionZ += 12.0f;
1622 me->GetMotionMaster()->MovePoint(1, pos);
1623 }
1624 }
1625
1626 private:
1629 };
1630
1632 {
1633 return new npc_wyrmrest_skytalonAI(creature);
1634 }
1635};
1636
1637// We shouldn't use SAI for stuff that aren't within boss main mechanic
1638// and SAI type of despawn can cause problems here.
1640{
1641 public:
1642 npc_static_field() : CreatureScript("npc_static_field") { }
1643
1645 {
1647 {
1648 }
1649
1650 void IsSummonedBy(Unit* /*summoner*/) OVERRIDE
1651 {
1652 // For some great reason the spell doesn't time it...
1653 me->DespawnOrUnsummon(30*IN_MILLISECONDS);
1654 }
1655 };
1656
1658 {
1659 return new npc_static_fieldAI(creature);
1660 }
1661};
1662
1664{
1665 public:
1666 spell_malygos_portal_beam() : SpellScriptLoader("spell_malygos_portal_beam") { }
1667
1669 {
1671
1673 {
1675 }
1676
1677 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
1678 {
1679 if (!sSpellMgr->GetSpellInfo(SPELL_PORTAL_OPENED))
1680 return false;
1681
1682 return true;
1683 }
1684
1685 void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1686 {
1687 if (Creature* target = GetTarget()->ToCreature())
1688 target->CastSpell(target, SPELL_PORTAL_OPENED);
1689 }
1690
1691 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1692 {
1693 if (Creature* target = GetTarget()->ToCreature())
1694 target->RemoveAura(SPELL_PORTAL_OPENED);
1695 }
1696
1702 };
1703
1708};
1709
1711{
1712 public:
1713 spell_malygos_random_portal() : SpellScriptLoader("spell_malygos_random_portal") { }
1714
1716 {
1718
1720 {
1722 }
1723
1724 void HandleDummy(SpellEffIndex /*effIndex*/)
1725 {
1726 Creature* malygos = GetCaster()->ToCreature();
1727 if (Creature* target = GetHitCreature())
1728 {
1729 Position pos;
1730 pos.m_positionZ = target->GetPositionZ();
1731 target->GetNearPoint2D(pos.m_positionX, pos.m_positionY, frand(29.1f, 30.0f), target->GetAngle(malygos));
1733 }
1734 }
1735
1740 };
1741
1746};
1747
1749{
1750 public:
1751 IsCreatureVehicleCheck(bool isVehicle) : _isVehicle(isVehicle) { }
1752
1754 {
1755 if (Unit* unit = obj->ToUnit())
1756 if (unit->GetTypeId() == TypeID::TYPEID_UNIT && unit->GetVehicleKit())
1757 return _isVehicle;
1758
1759 return !_isVehicle;
1760 }
1761
1762 private:
1764};
1765
1767{
1768 public:
1769 spell_malygos_arcane_storm() : SpellScriptLoader("spell_malygos_arcane_storm") { }
1770
1772 {
1774
1776 {
1778 }
1779
1780 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
1781 {
1782 if (!sSpellMgr->GetSpellInfo(SPELL_ARCANE_STORM_EXTRA_VISUAL))
1783 return false;
1784
1785 return true;
1786 }
1787
1788 void FilterTargets(std::list<WorldObject*>& targets)
1789 {
1790 if (targets.empty())
1791 return;
1792
1793 Creature* malygos = GetCaster()->ToCreature();
1795 {
1796 // Resize list only to objects that are vehicles.
1797 IsCreatureVehicleCheck check(true);
1798 Skyfire::Containers::RandomResizeList(targets, check, (malygos->GetMap()->GetDifficulty() == DIFFICULTY_10MAN_NORMAL ? 4 : 10));
1799 }
1800 else
1802 }
1803
1804 void HandleVisual(SpellEffIndex /*effIndex*/)
1805 {
1806 // Both missiles should start approx at same time (with SPELL_ARCANE_STORM_EXTRA_VISUAL having advantage - it should lead)
1807 if (!GetHitUnit())
1808 return;
1809
1811 }
1812
1818 };
1819
1824};
1825
1827{
1828public:
1829 spell_malygos_vortex_dummy() : SpellScriptLoader("spell_malygos_vortex_dummy") { }
1830
1832 {
1839
1840 void HandleScript(SpellEffIndex /*effIndex*/)
1841 {
1842 Creature* caster = GetCaster()->ToCreature();
1843 // Each player will enter to the trigger vehicle (entry 30090) which is already spawned (each one can hold up to 5 players, it has 5 seats,
1844 // the players enter the vehicles casting SPELL_VORTEX_4 or SPELL_VORTEX_5.
1845 if (InstanceScript* instance = caster->GetInstanceScript())
1846 instance->SetData(DATA_VORTEX_HANDLING, 0);
1847
1848 // the rest of the vortex execution continues when SPELL_VORTEX_2 is removed.
1849 }
1850
1855 };
1856
1861};
1862
1864{
1865 public:
1866 spell_malygos_vortex_visual() : SpellScriptLoader("spell_malygos_vortex_visual") { }
1867
1869 {
1871
1873 {
1875 }
1876
1877 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
1878 {
1879 if (!sSpellMgr->GetSpellInfo(SPELL_VORTEX_1) || !sSpellMgr->GetSpellInfo(SPELL_VORTEX_6))
1880 return false;
1881
1882 return true;
1883 }
1884
1885 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
1886 {
1887 if (Creature* caster = GetCaster()->ToCreature())
1888 {
1889 ThreatContainer::StorageType const& m_threatlist = caster->getThreatManager().getThreatList();
1890 for (ThreatContainer::StorageType::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr)
1891 {
1892 if (Unit* target = (*itr)->getTarget())
1893 {
1894 Player* targetPlayer = target->ToPlayer();
1895 if (!targetPlayer || targetPlayer->IsGameMaster())
1896 continue;
1897
1898 if (InstanceScript* instance = caster->GetInstanceScript())
1899 {
1900 // Teleport spell - I'm not sure but might be it must be casted by each vehicle when it's passenger leaves it.
1901 if (Creature* trigger = caster->GetMap()->GetCreature(instance->GetData64(DATA_TRIGGER)))
1902 trigger->CastSpell(targetPlayer, SPELL_VORTEX_6, true);
1903 }
1904 }
1905 }
1906
1907 if (Creature* malygos = caster->ToCreature())
1908 {
1909 malygos->GetMotionMaster()->MoveLand(POINT_LAND_AFTER_VORTEX_P_ONE, MalygosPositions[2]);
1910 malygos->RemoveAura(SPELL_VORTEX_1);
1911 }
1912 }
1913 }
1914
1919 };
1920
1925};
1926
1928{
1929 public:
1930 ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) { }
1931
1933 {
1934 return _source->GetExactDist2d(unit) > _dist;
1935 }
1936
1937 private:
1938 Unit* _source;
1939 float _dist;
1940};
1941
1943{
1944 public:
1945 spell_arcane_overload() : SpellScriptLoader("spell_arcane_overload") { }
1946
1948 {
1950
1952 {
1954 }
1955
1956 void ResizeEffectRadiusTargetChecker(std::list<WorldObject*>& targets)
1957 {
1958 Creature* arcaneOverload = GetCaster()->ToCreature();
1959 targets.remove_if(ExactDistanceCheck(arcaneOverload,
1960 GetSpellInfo()->Effects[EFFECT_0].CalcRadius(arcaneOverload) * arcaneOverload->GetObjectScale()));
1961 }
1962
1967 };
1968
1973};
1974
2007
2009{
2010 public:
2011 IsPlayerOnHoverDisk(bool isOnHoverDisk) : _isOnHoverDisk(isOnHoverDisk) { }
2012
2014 {
2015 if (Unit* passenger = obj->ToUnit())
2016 if (passenger->GetVehicleBase() && passenger->GetVehicleBase()->GetEntry() == NPC_HOVER_DISK_MELEE)
2017 return _isOnHoverDisk;
2018
2019 return !_isOnHoverDisk;
2020 }
2021
2022 private:
2024};
2025
2027{
2028 public:
2029 spell_scion_of_eternity_arcane_barrage() : SpellScriptLoader("spell_scion_of_eternity_arcane_barrage") { }
2030
2032 {
2034
2036 {
2037 return GetCaster()->GetTypeId() == TypeID::TYPEID_UNIT && GetCaster()->GetInstanceScript() != NULL;
2038 }
2039
2040 void FilterMeleeHoverDiskPassangers(std::list<WorldObject*>& targets)
2041 {
2042 if (targets.empty())
2043 return;
2044
2045 Creature* caster = GetCaster()->ToCreature();
2046 InstanceScript* instance = caster->GetInstanceScript();
2047 Creature* malygos = caster->GetMap()->GetCreature(instance->GetData64(DATA_MALYGOS));
2048
2049 // If max possible targets are more than 1 then Scions wouldn't select previosly selected target,
2050 // in longer terms this means if spell picks target X then 2nd cast of this spell will pick smth else
2051 // and if 3rd picks X again 4th will pick smth else (by not limiting the cast to certain caster).
2052 if (targets.size() > 1)
2053 if (malygos && malygos->AI()->GetGUID(DATA_LAST_TARGET_BARRAGE_GUID))
2054 targets.remove_if(Skyfire::ObjectGUIDCheck(malygos->AI()->GetGUID(DATA_LAST_TARGET_BARRAGE_GUID)));
2055
2056 // Remove players not on Hover Disk from second list
2057 std::list<WorldObject*> playersWithoutDisk;
2058 IsPlayerOnHoverDisk check(false);
2059 for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
2060 if (check(*itr))
2061 playersWithoutDisk.push_back(*itr);
2062
2063 // if it's empty than we can have player on Hover disk as target.
2064 if (!playersWithoutDisk.empty())
2065 targets = playersWithoutDisk;
2066
2067 // Finally here we remove all targets that have been damaged by Arcane Barrage
2068 // and have 2 seconds long aura still lasting. Used to give healers some time.
2069 if (!targets.empty())
2070 targets.remove_if(Skyfire::UnitAuraCheck(true, SPELL_ARCANE_BARRAGE_DAMAGE));
2071
2072 // Now we resize the list to max output targets which can be only 1
2073 // to take it's guid and send/store it to DATA_LAST_TARGET_BARRAGE_GUID.
2074 // Same target is never picked until next pick pass. This doesn't mean
2075 // that it can't be hit more than once. In fact all is chance and raid speed.
2076 if (!targets.empty())
2077 {
2078 if (targets.size() > 1)
2080
2081 if (WorldObject* filteredTarget = targets.front())
2082 if (malygos)
2083 malygos->AI()->SetGUID(filteredTarget->GetGUID(), DATA_LAST_TARGET_BARRAGE_GUID);
2084 }
2085 }
2086
2088 {
2089 if (Player* hitTarget = GetHitPlayer())
2090 {
2091 // There is some proc in this spell I have absolutely no idea of use, but just in case...
2093 hitTarget->CastSpell(hitTarget, SPELL_ARCANE_BARRAGE_DAMAGE, triggerFlags, NULL, NULL, GetCaster()->GetGUID());
2094 }
2095 }
2096
2102 };
2103
2108};
2109
2111{
2112 public:
2113 spell_malygos_destroy_platform_channel() : SpellScriptLoader("spell_malygos_destroy_platform_channel") { }
2114
2116 {
2118
2120 {
2122 }
2123
2124 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
2125 {
2127 return false;
2128
2129 return true;
2130 }
2131
2132 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2133 {
2134 if (Creature* target = GetTarget()->ToCreature())
2135 if (InstanceScript* instance = target->GetInstanceScript())
2136 if (Creature* platformTrigger = target->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID)))
2137 platformTrigger->CastSpell(platformTrigger, SPELL_DESTROY_PLATFORM_BOOM_VISUAL);
2138 }
2139
2144 };
2145
2150};
2151
2191
2193{
2194 public:
2195 spell_alexstrasza_bunny_destroy_platform_event() : SpellScriptLoader("spell_alexstrasza_bunny_destroy_platform_event") { }
2196
2225
2230};
2231
2233{
2234 public:
2235 spell_wyrmrest_skytalon_summon_red_dragon_buddy() : SpellScriptLoader("spell_wyrmrest_skytalon_summon_red_dragon_buddy") { }
2236
2238 {
2240
2242 {
2244 }
2245
2247 {
2248 // Adjust effect summon position to lower Z
2249 WorldLocation summonPos = *GetExplTargetDest();
2250 Position offset = { 0.0f, 0.0f, -80.0f, 0.0f };
2251 summonPos.RelocateOffset(offset);
2252 SetExplTargetDest(summonPos);
2253 GetHitDest()->RelocateOffset(offset);
2254 }
2255
2260 };
2261
2266};
2267
2299
2301{
2302 public:
2303 spell_malygos_surge_of_power_warning_selector_25() : SpellScriptLoader("spell_malygos_surge_of_power_warning_selector_25") { }
2304
2306 {
2313
2314 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
2315 {
2316 if (!sSpellMgr->GetSpellInfo(SPELL_SURGE_OF_POWER_PHASE_3_25))
2317 return false;
2318
2319 return true;
2320 }
2321
2322 void SendThreeTargets(std::list<WorldObject*>& targets)
2323 {
2324 // This spell hits only vehicles (SMSG_SPELL_GO target)
2325 Creature* caster = GetCaster()->ToCreature();
2326 // Remove all objects that aren't* vehicles.
2327 targets.remove_if(IsCreatureVehicleCheck(false));
2328 if (targets.empty())
2329 return;
2330
2331 // But in fact it selects 3 targets (SMSG_SPELL_GO target are not filtered)
2332 std::list<WorldObject*> selectedTargets = targets;
2333
2334 uint8 guidDataSlot = DATA_FIRST_SURGE_TARGET_GUID; // SetGuid in Malygos AI is reserved for 14th, 15th and 16th Id for the three targets
2335 Skyfire::Containers::RandomResizeList(selectedTargets, 3);
2336 for (std::list<WorldObject*>::const_iterator itr = selectedTargets.begin(); itr != selectedTargets.end(); ++itr)
2337 {
2338 Creature* target = (*itr)->ToCreature();
2339 caster->AI()->SetGUID(target->GetGUID(), guidDataSlot++);
2340
2341 if (Vehicle* vehicle = target->GetVehicleKit())
2342 if (Unit* passenger = vehicle->GetPassenger(0))
2343 if (passenger->GetTypeId() == TypeID::TYPEID_PLAYER)
2344 caster->AI()->Talk(EMOTE_SURGE_OF_POWER_WARNING_P3, passenger);
2345 }
2346 }
2347
2352
2358 };
2359
2364};
2365
2367{
2368 public:
2369 spell_malygos_surge_of_power_25() : SpellScriptLoader("spell_malygos_surge_of_power_25") { }
2370
2372 {
2379
2380 void FilterTargets(std::list<WorldObject*>& targets)
2381 {
2382 Creature* caster = GetCaster()->ToCreature();
2383
2384 for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end();)
2385 {
2386 bool found = false;
2387 WorldObject* target = *itr;
2388
2390 {
2391 if (target->GetGUID() == caster->AI()->GetGUID(guidSlot))
2392 {
2393 found = true;
2394 break;
2395 }
2396 }
2397
2398 if (!found)
2399 targets.erase(itr++);
2400 else
2401 ++itr;
2402 }
2403 }
2404
2409 };
2410
2415};
2416
2418{
2419 public:
2420 spell_alexstrasza_gift_beam() : SpellScriptLoader("spell_alexstrasza_gift_beam") { }
2421
2423 {
2425
2427 {
2429 }
2430
2431 bool Validate(SpellInfo const* /*spell*/) OVERRIDE
2432 {
2434 return false;
2435
2436 return true;
2437 }
2438
2439 void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2440 {
2441 if (Creature* target = GetTarget()->ToCreature())
2442 target->CastSpell(target, SPELL_ALEXSTRASZAS_GIFT_BEAM_VISUAL);
2443 }
2444
2445 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2446 {
2447 if (Creature* target = GetTarget()->ToCreature())
2448 target->RemoveAura(SPELL_ALEXSTRASZAS_GIFT_BEAM_VISUAL);
2449 }
2450
2456 };
2457
2462};
2463
2465{
2466 public:
2467 spell_alexstrasza_gift_beam_visual() : SpellScriptLoader("spell_alexstrasza_gift_beam_visual") { }
2468
2470 {
2472
2474 {
2476 }
2477
2478 void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2479 {
2480 if (Creature* target = GetTarget()->ToCreature())
2481 {
2482 if (target->GetMap()->GetDifficulty() == DIFFICULTY_10MAN_NORMAL)
2483 _alexstraszaGift = target->SummonGameObject(GO_ALEXSTRASZA_S_GIFT_10, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0);
2484 else if (target->GetMap()->GetDifficulty() == DIFFICULTY_25MAN_NORMAL)
2485 _alexstraszaGift = target->SummonGameObject(GO_ALEXSTRASZA_S_GIFT_25, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0);
2486 }
2487 }
2488
2489 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
2490 {
2491 if (Creature* target = GetTarget()->ToCreature())
2492 if (InstanceScript* instance = GetCaster()->GetInstanceScript())
2493 {
2495 if (GameObject* heartMagic = target->GetMap()->GetGameObject(instance->GetData64(DATA_HEART_OF_MAGIC_GUID)))
2496 {
2497 heartMagic->RemoveFlag(GAMEOBJECT_FIELD_FLAGS, GO_FLAG_NOT_SELECTABLE);
2498 // TO DO: This is hack, core doesn't have support for these flags,
2499 // remove line below if it ever gets supported otherwise object won't be accessible.
2500 heartMagic->RemoveFlag(GAMEOBJECT_FIELD_FLAGS, GO_FLAG_INTERACT_COND);
2501 }
2502 }
2503 }
2504
2510
2512 };
2513
2518};
2519
2521{
2522 public:
2523 achievement_denyin_the_scion() : AchievementCriteriaScript("achievement_denyin_the_scion") { }
2524
2525 bool OnCheck(Player* source, Unit* /*target*/) OVERRIDE
2526 {
2527 // Only melee disks can be used
2528 if (Unit* disk = source->GetVehicleBase())
2529 if (disk->GetEntry() == NPC_HOVER_DISK_MELEE)
2530 return true;
2531
2532 return false;
2533 }
2534};
2535
Actions
@ IN_MILLISECONDS
Definition Common.h:125
#define M_PI
Definition Common.h:192
#define sCreatureTextMgr
@ TEXT_RANGE_MAP
@ ACHIEVEMENT_TIMED_TYPE_EVENT
Definition DBCEnums.h:158
@ DIFFICULTY_25MAN_NORMAL
Definition DBCEnums.h:335
@ DIFFICULTY_10MAN_NORMAL
Definition DBCEnums.h:334
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::int8_t int8
Definition Define.h:75
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
@ IN_PROGRESS
@ FAIL
@ NOT_STARTED
@ CHASE_MOTION_TYPE
@ POINT_MOTION_TYPE
@ EFFECT_MOTION_TYPE
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
@ TEMPSUMMON_MANUAL_DESPAWN
Definition Object.h:75
bool IS_VEHICLE_GUID(uint64 guid)
SpellEffIndex
@ EFFECT_0
@ EFFECT_2
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_SEND_EVENT
@ SPELL_EFFECT_SUMMON
@ SPELL_EFFECT_SCHOOL_DAMAGE
@ TARGET_UNIT_SRC_AREA_ENEMY
@ GO_FLAG_INTERACT_COND
@ GO_FLAG_NOT_SELECTABLE
@ GO_FLAG_DESTROYED
@ SPELL_AURA_DUMMY
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
#define sSpellMgr
Definition SpellMgr.h:744
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectApplyFn(F, I, N, M)
#define SpellHitFn(F)
#define AuraEffectRemoveFn(F, I, N, M)
@ SPELLVALUE_MAX_TARGETS
Definition Unit.h:118
@ UNIT_BYTE1_FLAG_HOVER
Definition Unit.h:189
@ UNIT_BYTE1_FLAG_ALWAYS_STAND
Definition Unit.h:188
TriggerCastFlags
Definition Unit.h:415
@ TRIGGERED_FULL_MASK
Will ignore most target checks (mostly DBC target checks).
Definition Unit.h:435
@ TRIGGERED_DISALLOW_PROC_EVENTS
Will ignore caster aura restrictions or requirements.
Definition Unit.h:431
@ UNIT_STATE_ROOT
Definition Unit.h:522
@ UNIT_STATE_CASTING
Definition Unit.h:527
@ MOVE_FLIGHT
Definition Unit.h:561
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
@ UNIT_FLAG_IMMUNE_TO_NPC
Definition Unit.h:634
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ UNIT_FLAG_IMMUNE_TO_PC
Definition Unit.h:633
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_ANIM_TIER
@ UNIT_FIELD_FLAGS
@ GAMEOBJECT_FIELD_FLAGS
float frand(float min, float max)
Definition Util.cpp:39
@ SPELL_CLEAR_ALL_DEBUFFS
Position const centerPos
#define SAY_DEATH
@ PHASE_NOT_STARTED
@ DATA_SUMMON_DEATHS
@ SPELL_ARCANE_BARRAGE
#define SPELL_BERSERK
@ PHASE_ONE
@ PHASE_THREE
@ PHASE_TWO
Position const AlexstraszaSpawnPos
#define MAX_RANGE_HOVER_DISK_SPAWNPOINTS
@ LIGHT_CHANGE_DIMENSIONS
@ LIGHT_OBSCURE_ARCANE_RUNES
@ LIGHT_OBSCURE_SPACE
@ LIGHT_GET_DEFAULT_FOR_MAP
@ DATA_LAST_TARGET_BARRAGE_GUID
@ DATA_FIRST_SURGE_TARGET_GUID
@ NUM_MAX_SURGE_TARGETS
@ DATA_SUMMON_DEATHS
@ DATA_PHASE
@ DATA_LAST_OVERLOAD_GUID
@ LIGHT_ARCANE_RUNES
@ ACTION_HANDLE_P_THREE_INTRO
@ ACTION_LAND_ENCOUNTER_START
@ ACTION_SET_DISK_VICTIM_CHASE
@ ACTION_CYCLIC_MOVEMENT
@ ACTION_DELAYED_DESPAWN
@ ACTION_EXECUTE_VORTEX
@ ACTION_HANDLE_RESPAWN
@ ACTION_LIFT_IN_AIR
void AddSC_boss_malygos()
@ SEAT_0
@ SPELL_PORTAL_BEAM
@ SPELL_CLEAR_ALL_DEBUFFS
@ SPELL_ARCANE_STORM_EXTRA_VISUAL
@ SPELL_VORTEX_1
@ SPELL_RIDE_HOVER_DISK
@ SPELL_ARCANE_PULSE
@ SPELL_POWER_SPARK_MALYGOS
@ SPELL_POWER_SPARK_DEATH
@ SPELL_PORTAL_VISUAL_CLOSED
@ SPELL_SUMMON_ARCANE_BOMB
@ SPELL_ARCANE_BARRAGE
@ SPELL_ARCANE_STORM_P_I
@ SPELL_SUMMON_RED_DRAGON_BUDDY_F_CAST
@ SPELL_HASTE
@ SPELL_RIDE_RED_DRAGON_BUDDY
@ SPELL_ARCANE_BOMB_TRIGGER
@ SPELL_DESTROY_PLATFORM_BOOM_VISUAL
@ SPELL_ARCANE_BARRAGE_DAMAGE
@ SPELL_ARCANE_BREATH
@ SPELL_ARCANE_SHOCK
@ SPELL_SUMMOM_RED_DRAGON_BUDYY
@ SPELL_VORTEX_2
@ SPELL_DUMMY_NUKE
@ SPELL_DESTROY_PLATFORM_CHANNEL
@ SPELL_RANDOM_PORTAL
@ SPELL_VORTEX_3
@ SPELL_SURGE_OF_POWER_PHASE_3_10
@ SPELL_ARCANE_OVERLOAD_1
@ SPELL_ARCANE_BOMB_KNOCKBACK_DAMAGE
@ SPELL_MALYGOS_BERSERK
@ SPELL_ALEXSTRASZAS_GIFT_BEAM_VISUAL
@ SPELL_SURGE_OF_POWER_PHASE_3_25
@ SPELL_IMMUNE_CURSES
@ SPELL_ALIGN_DISK_AGGRO
@ SPELL_DESTROY_PLATFORM_EVENT
@ SPELL_STATIC_FIELD_MISSLE
@ SPELL_BERSERK
@ SPELL_SURGE_OF_POWER_WARNING_SELECTOR_25
@ SPELL_SUMMON_POWER_PARK
@ SPELL_TELEPORT_VISUAL_ONLY
@ SPELL_SURGE_OF_POWER_P_II
@ SPELL_VORTEX_6
@ SPELL_ARCANE_STORM_P_III
@ PHASE_ONE
@ PHASE_NOT_STARTED
@ PHASE_THREE
@ PHASE_TWO
Position const RangeHoverDisksSpawnPositions[MAX_RANGE_HOVER_DISK_SPAWNPOINTS]
#define MAX_SUMMONS_PHASE_TWO_25MAN
@ SAY_DEATH
@ SAY_START_P_THREE
@ SAY_END_P_ONE
@ SAY_ANTI_MAGIC_SHELL
@ SAY_ONE
@ SAY_TWO
@ EMOTE_POWER_SPARK_SUMMONED
@ SAY_DEEP_BREATH
@ SAY_KILLED_PLAYER_P_THREE
@ SAY_KILLED_PLAYER_P_TWO
@ EMOTE_SURGE_OF_POWER_WARNING_P3
@ SAY_SURGE_OF_POWER
@ SAY_END_P_TWO
@ SAY_MAGIC_BLAST
@ SAY_INTRO_EVENT
@ SAY_FOUR
@ SAY_SPELL_CASTING_P_THREE
@ SAY_THREE
@ EMOTE_SURGE_OF_POWER_WARNING_P2
@ SAY_START_P_ONE
@ SAY_KILLED_PLAYER_P_ONE
@ EMOTE_HIT_BERSERKER_TIMER
@ SAY_BUFF_SPARK
Position const MalygosPositions[MAX_MALYGOS_POS]
Position const HeartOfMagicSpawnPos
Position const MeleeHoverDisksSpawnPositions[MAX_RANGE_HOVER_DISK_SPAWNPOINTS]
Position const MeleeHoverDisksWaypoints[MAX_MELEE_HOVER_DISK_WAYPOINTS]
#define MAX_MELEE_HOVER_DISK_SPAWNPOINTS
@ FACTION_FRIENDLY
#define MAX_MALYGOS_POS
Movements
@ POINT_DESTROY_PLATFORM_P_TWO
@ POINT_NEAR_RANDOM_PORTAL_P_NONE
@ POINT_LIFT_IN_AIR_P_ONE
@ POINT_LAND_AFTER_VORTEX_P_ONE
@ POINT_PHASE_ONE_TO_TWO_TRANSITION
@ POINT_LAND_P_ONE
@ POINT_SURGE_OF_POWER_P_TWO
@ POINT_FLY_OUT_OF_PLATFORM_P_TWO
@ POINT_VORTEX_P_ONE
@ POINT_IDLE_P_THREE
#define MAX_SUMMONS_PHASE_TWO_10MAN
@ ACHIEV_TIMED_START_EVENT
#define MAX_MELEE_HOVER_DISK_WAYPOINTS
@ AREA_EYE_OF_ETERNITY
@ EVENT_LAND_START_ENCOUNTER
@ EVENT_STOP_PORTAL_BEAM
@ EVENT_ARCANE_SHOCK
@ EVENT_START_P_THREE
@ EVENT_VORTEX
@ EVENT_SUMMON_ARCANE_BOMB
@ EVENT_MOVE_TO_POINT_SURGE_P_TWO
@ EVENT_ARCANE_STORM
@ EVENT_DELAYED_REINFORCEMENTS
@ EVENT_HASTE_BUFF
@ EVENT_STATIC_FIELD
@ EVENT_SURGE_OF_POWER_P_THREE
@ EVENT_POWER_SPARKS
@ EVENT_MOVE_TO_P_THREE_POINT
@ EVENT_LIGHT_DIMENSION_CHANGE
@ EVENT_SAY_INTRO
@ EVENT_SURGE_OF_POWER_P_TWO
@ EVENT_CAST_RIDE_SPELL
@ EVENT_ARCANE_BARRAGE
@ EVENT_PATHING_AROUND_PLATFORM
@ EVENT_ARCANE_PULSE
@ EVENT_PREVENT_SAY_SPAM_ON_KILL
@ EVENT_FLY_OUT_OF_PLATFORM
@ EVENT_NUKE_DUMMY
@ EVENT_DELAY_MOVE_TO_DESTROY_P
@ EVENT_START_FIRST_RANDOM_PORTAL
@ EVENT_RANDOM_PORTAL
@ EVENT_MOVE_TO_VORTEX_POINT
@ EVENT_ARCANE_BREATH
@ SPELL_HASTE
@ SPELL_ARCANE_SHOCK
virtual bool Load()
AchievementCriteriaScript(const char *name)
HookList< EffectApplyHandler > AfterEffectRemove
Unit * GetCaster() const
Unit * GetTarget() const
HookList< EffectApplyHandler > OnEffectApply
InstanceScript *const instance
SummonList summons
EventMap events
BossAI(Creature *creature, uint32 bossId)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:56
CreatureAI * AI() const
Definition Creature.h:483
CreatureScript(const char *name)
ExactDistanceCheck(Unit *source, float dist)
bool operator()(WorldObject *unit)
IsCreatureVehicleCheck(bool isVehicle)
bool operator()(WorldObject *obj)
IsPlayerOnHoverDisk(bool isOnHoverDisk)
bool operator()(WorldObject *obj)
bool isEmpty() const
Definition LinkedList.h:86
DifficultyID GetDifficulty() const
Definition Map.h:363
MapRefManager PlayerList
Definition Map.h:406
GameObject * GetGameObject(uint64 guid)
Definition Map.cpp:3184
Creature * GetCreature(uint64 guid)
Definition Map.cpp:3179
iterator end()
iterator begin()
LinkedListHead::Iterator< MapReference const > const_iterator
void MoveChase(Unit *target, float dist=0.0f, float angle=0.0f)
void MovePoint(uint32 id, Position const &pos, bool generatePath=true)
float GetObjectScale() const
Definition Object.h:128
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
TypeID GetTypeId() const
Definition Object.h:131
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:1261
Creature * ToCreature()
Definition Object.h:207
Unit * ToUnit()
Definition Object.h:210
bool IsGameMaster() const
Definition Player.h:1369
Creature * GetHitCreature()
WorldLocation const * GetExplTargetDest()
Player * GetHitPlayer()
void SetExplTargetDest(WorldLocation &loc)
HookList< HitHandler > AfterHit
SpellInfo const * GetSpellInfo()
HookList< HitHandler > OnHit
HookList< EffectHandler > OnEffectHit
HookList< EffectHandler > OnEffectHitTarget
Unit * GetHitUnit()
WorldLocation * GetHitDest()
int32 GetEffectValue()
HookList< EffectHandler > OnEffectLaunchTarget
Unit * GetCaster()
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
SpellScriptLoader(const char *name)
std::list< HostileReference * > StorageType
virtual uint64 GetGUID(int32=0) const
Definition UnitAI.h:130
virtual void DoAction(int32)
Definition UnitAI.h:126
virtual void SetGUID(uint64, int32=0)
Definition UnitAI.h:129
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
Unit * SelectTarget(SelectAggroTarget targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:66
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
void DoCastAOE(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:176
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:16
Definition Unit.h:1367
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
Unit * GetVehicleBase() const
Definition Unit.cpp:7203
MotionMaster * GetMotionMaster()
Definition Unit.h:2605
Unit * GetVictim() const
Definition Unit.h:1468
bool IsAIEnabled
Definition Unit.h:2735
Vehicle * GetVehicleKit() const
Definition Unit.h:2739
bool operator()(uint64 guid)
Map * GetMap() const
Definition Object.h:740
InstanceScript * GetInstanceScript()
Definition Object.cpp:1612
virtual uint64 GetData64(uint32) const
Definition ZoneScript.h:32
bool OnCheck(Player *source, Unit *) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
void OnApply(AuraEffect const *, AuraEffectHandleModes)
AuraScript * GetAuraScript() const OVERRIDE
AuraScript * GetAuraScript() const OVERRIDE
PrepareSpellScript(spell_arcane_overload_SpellScript)
void ResizeEffectRadiusTargetChecker(std::list< WorldObject * > &targets)
SpellScript * GetSpellScript() const OVERRIDE
PrepareSpellScript(spell_malygos_arcane_storm_SpellScript)
SpellScript * GetSpellScript() const OVERRIDE
AuraScript * GetAuraScript() const OVERRIDE
PrepareAuraScript(spell_malygos_portal_beam_AuraScript)
void OnApply(AuraEffect const *, AuraEffectHandleModes)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
AuraScript * GetAuraScript() const OVERRIDE
PrepareSpellScript(spell_malygos_random_portal_SpellScript)
SpellScript * GetSpellScript() const OVERRIDE
PrepareSpellScript(spell_malygos_surge_of_power_25_SpellScript) bool Load() OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
PrepareSpellScript(spell_malygos_surge_of_power_warning_selector_25_SpellScript) bool Load() OVERRIDE
PrepareSpellScript(spell_malygos_vortex_dummy_SpellScript) bool Load() OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
AuraScript * GetAuraScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
@ DATA_VORTEX_HANDLING
@ DATA_RESPAWN_IRIS
@ DATA_POWER_SPARKS_HANDLING
@ DATA_MALYGOS_EVENT
@ DATA_HEART_OF_MAGIC_GUID
@ DATA_TRIGGER
@ DATA_MALYGOS
@ DATA_ALEXSTRASZA_BUNNY_GUID
@ DATA_FOCUSING_IRIS_GUID
@ DATA_PLATFORM
@ DATA_GIFT_BOX_BUNNY_GUID
@ GO_HEART_OF_MAGIC_10
@ GO_HEART_OF_MAGIC_25
@ GO_ALEXSTRASZA_S_GIFT_10
@ GO_ALEXSTRASZA_S_GIFT_25
@ NPC_PORTAL_TRIGGER
@ NPC_POWER_SPARK
@ NPC_HOVER_DISK_CASTER
@ NPC_ALEXSTRASZA
@ NPC_HOVER_DISK_MELEE
@ SPELL_RIDE_RED_DRAGON_TRIGGERED
@ SPELL_PORTAL_OPENED
@ SMSG_OVERRIDE_LIGHT
Definition Opcodes.h:840
std::vector< Vector3 > PointsArray
void RandomResizeList(std::list< T > &list, uint32 size)
Definition Containers.h:19
@ ACHIEV_TIMED_START_EVENT
float m_positionZ
Definition Object.h:289
float m_positionX
Definition Object.h:287
float m_positionY
Definition Object.h:288
void RelocateOffset(Position const &offset)
Definition Object.cpp:1841
DifficultyID GetDifficulty() const
Creature * me
ScriptedAI(Creature *creature)
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
Definition CombatAI.cpp:270
VehicleAI(Creature *c)
Definition CombatAI.cpp:262
void Reset() OVERRIDE
Definition CombatAI.cpp:287
void AttackStart(Unit *target) OVERRIDE
void JustDied(Unit *) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void SendLightOverride(uint32 overrideId, uint32 fadeInTime) const
void SetData(uint32 data, uint32 value) OVERRIDE
uint32 GetData(uint32 data) const OVERRIDE
void MoveInLineOfSight(Unit *who) OVERRIDE
uint64 GetGUID(int32 type) const OVERRIDE
boss_malygosAI(Creature *creature)
void SetPhase(uint8 phase, bool setEvents=false)
void SendPacketToPlayers(WorldPacket const *data) const
void KilledUnit(Unit *victim) OVERRIDE
void SpellHit(Unit *caster, SpellInfo const *spell) OVERRIDE
void EnterCombat(Unit *) OVERRIDE
void FillCirclePath(Position const &centerPos, float radius, float z, Movement::PointsArray &path, bool clockwise)
void DoAction(int32 action) OVERRIDE
void SetGUID(uint64 guid, int32 type) OVERRIDE
void MovementInform(uint32 type, uint32 id) OVERRIDE
void SpellHit(Unit *, SpellInfo const *spell) OVERRIDE
void UpdateAI(uint32) OVERRIDE
== Triggered Actions Requested ==================
void IsSummonedBy(Unit *summoner) OVERRIDE
void PassengerBoarded(Unit *unit, int8, bool apply) OVERRIDE
== Fields =======================================
void FillCirclePath(Position const &centerPos, float radius, float z, Movement::PointsArray &path, bool clockwise)
void MovementInform(uint32 type, uint32 id) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void PassengerBoarded(Unit *unit, int8, bool apply) OVERRIDE
== Fields =======================================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32) OVERRIDE
== Triggered Actions Requested ==================
void SpellHit(Unit *, SpellInfo const *spell) OVERRIDE
void UpdateAI(uint32) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void PassengerBoarded(Unit *, int8, bool apply) OVERRIDE
== Fields =======================================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
@ FACTION_FRIENDLY