TrinityCore
Loading...
Searching...
No Matches
boss_thorim.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ScriptMgr.h"
19#include "AreaBoundary.h"
20#include "CellImpl.h"
21#include "Containers.h"
22#include "GridNotifiersImpl.h"
23#include "InstanceScript.h"
24#include "MotionMaster.h"
25#include "MoveSplineInit.h"
26#include "ObjectAccessor.h"
27#include "Player.h"
28#include "ScriptedCreature.h"
29#include "SpellAuraEffects.h"
30#include "SpellMgr.h"
31#include "SpellScript.h"
33#include "ulduar.h"
34#include <G3D/Vector3.h>
35
37{
38 // Thorim
50 SPELL_LIGHTNING_ORB_CHARGED = 62186, // wrong duration, triggered spell should handle lightning release
53 SPELL_LIGHTNING_PILLAR_2 = 62976, // caster high position, target low position
54 SPELL_LIGHTNING_PILLAR_1 = 63238, // caster high position, target low position
59
60 // Credits
63
64 // Lightning Field
67
68 // Sif
70 SPELL_BLINK = 62578,
75
76 // Runic Colossus
77 SPELL_SMASH = 62339,
83
84 // Ancient Rune Giant
87 SPELL_STOMP = 62411
88};
89
96
141
171
214
235
244
267
277
283
285{
286 { { 2149.68f, -263.477f, 419.679f, 3.120f }, NPC_JORMUNGAR_BEHEMOTH },
287 { { 2131.31f, -271.640f, 419.840f, 2.188f }, NPC_MERCENARY_CAPTAIN_A },
288 { { 2127.24f, -259.182f, 419.974f, 5.917f }, NPC_MERCENARY_SOLDIER_A },
289 { { 2123.32f, -254.770f, 419.840f, 6.170f }, NPC_MERCENARY_SOLDIER_A },
290 { { 2120.10f, -258.990f, 419.840f, 6.250f }, NPC_MERCENARY_SOLDIER_A },
291 { { 2129.09f, -277.142f, 419.756f, 1.222f }, NPC_DARK_RUNE_ACOLYTE_PRE }
292};
293
295{
296 { { 2218.38f, -297.50f, 412.18f, 1.030f }, NPC_IRON_RING_GUARD },
297 { { 2235.07f, -297.98f, 412.18f, 1.613f }, NPC_IRON_RING_GUARD },
298 { { 2235.26f, -338.34f, 412.18f, 1.589f }, NPC_IRON_RING_GUARD },
299 { { 2217.69f, -337.39f, 412.18f, 1.241f }, NPC_IRON_RING_GUARD },
300 { { 2227.58f, -308.30f, 412.18f, 1.591f }, NPC_DARK_RUNE_ACOLYTE },
301 { { 2227.47f, -345.37f, 412.18f, 1.566f }, NPC_DARK_RUNE_ACOLYTE }
302};
303
305{
306 { { 2198.05f, -428.77f, 419.95f, 6.056f }, NPC_IRON_HONOR_GUARD },
307 { { 2220.31f, -436.22f, 412.26f, 1.064f }, NPC_IRON_HONOR_GUARD },
308 { { 2158.88f, -441.73f, 438.25f, 0.127f }, NPC_IRON_HONOR_GUARD },
309 { { 2198.29f, -436.92f, 419.95f, 0.261f }, NPC_DARK_RUNE_ACOLYTE },
310 { { 2230.93f, -434.27f, 412.26f, 1.931f }, NPC_DARK_RUNE_ACOLYTE }
311};
312
313Position const SifSpawnPosition = { 2148.301f, -297.8453f, 438.3308f, 2.687807f };
314
322
327
329{
330 { 2134.889893f, -298.632996f, 438.247467f },
331 { 2134.570068f, -440.317993f, 438.247467f },
332 { 2167.820312f, -440.330261f, 438.247589f },
333 { 2213.394287f, -433.318298f, 412.665863f },
334 { 2227.766113f, -433.275818f, 412.177032f },
335 { 2227.551270f, -263.081085f, 412.176880f },
336 { 2202.208008f, -262.939270f, 412.168976f },
337 { 2182.310059f, -263.233093f, 414.739410f }
338};
339std::size_t const LightningOrbPathSize = std::extent<decltype(LightningOrbPath)>::value;
340
341// used for trash jump calculation
342Position const ArenaCenter = { 2134.77f, -262.307f };
343
344// used for lightning field calculation
345Position const LightningFieldCenter = { 2135.178f, -321.122f };
346
349
355
357{
358 public:
359 HeightPositionCheck(bool ret) : _ret(ret) { }
360
361 bool operator()(Position const* pos) const
362 {
363 return (pos->GetPositionZ() > THORIM_BALCONY_Z_CHECK) == _ret;
364 }
365
366 private:
367 bool _ret;
368
369 static float const THORIM_BALCONY_Z_CHECK;
370};
372
374{
375 public:
377
378 bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
379 {
381 return true;
382 }
383
384 private:
386};
387
389{
390 public:
391 TrashJumpEvent(Creature* owner) : _owner(owner), _stage(0) { }
392
393 bool Execute(uint64 eventTime, uint32 /*updateTime*/) override
394 {
395 switch (_stage)
396 {
397 case 0:
398 _owner->CastSpell(nullptr, SPELL_LEAP);
399 ++_stage;
400 _owner->m_Events.AddEvent(this, Milliseconds(eventTime) + 2s);
401 return false;
402 case 1:
406 return true;
407 default:
408 break;
409 }
410
411 return true;
412 }
413
414 private:
417};
418
420{
421 public:
423
424 bool Execute(uint64 eventTime, uint32 /*updateTime*/) override
425 {
426 if (InstanceScript* instance = _owner->GetInstanceScript())
427 {
428 if (instance->GetBossState(DATA_THORIM) == IN_PROGRESS)
429 {
431 _owner->m_Events.AddEvent(this, Milliseconds(eventTime) + 1s);
432 return false;
433 }
434 }
435
438 return true;
439 }
440
441 private:
443};
444
446{
447 public:
448 boss_thorim() : CreatureScript("boss_thorim") { }
449
450 struct boss_thorimAI : public BossAI
451 {
452 boss_thorimAI(Creature* creature) : BossAI(creature, DATA_THORIM)
453 {
454 _encounterFinished = false;
455 Initialize();
456 }
457
459 {
460 _killedCount = 0;
461 _waveType = 0;
462 _hardMode = true;
463 _orbSummoned = false;
465 }
466
467 void Reset() override
468 {
470 return;
471
472 SetBoundary(nullptr);
473 _Reset();
474 Initialize();
475
477 me->SetDisableGravity(true);
479 me->SetImmuneToPC(true);
480
482
483 // Respawn Mini Bosses
484 for (uint8 i = DATA_RUNIC_COLOSSUS; i <= DATA_RUNE_GIANT; ++i)
486 miniBoss->Respawn(true);
487
488 // Spawn Pre Phase Adds
489 for (SummonLocation const& s : PreAddLocations)
491
494
495 // Remove trigger auras
497 pillar->RemoveAllAuras();
498
500 controller->RemoveAllAuras();
501
503 }
504
505 void EnterEvadeMode(EvadeReason /*why*/) override
506 {
509 }
510
511 void SetGUID(ObjectGuid const& guid, int32 id) override
512 {
513 if (id == DATA_CHARGED_PILLAR)
514 {
515 _activePillarGUID = guid;
516
518 {
519 pillar->CastSpell(pillar, SPELL_LIGHTNING_ORB_CHARGED, true);
520 pillar->CastSpell(nullptr, SPELL_LIGHTNING_PILLAR_2);
522 }
523 }
524 }
525
526 uint32 GetData(uint32 type) const override
527 {
528 switch (type)
529 {
531 return _dontStandInTheLightning ? 1 : 0;
534 return _hardMode ? 1 : 0;
535 default:
536 break;
537 }
538
539 return 0;
540 }
541
542 void KilledUnit(Unit* who) override
543 {
544 if (who->GetTypeId() == TYPEID_PLAYER)
545 Talk(SAY_SLAY);
546 }
547
548 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
549 {
550 if (spellInfo->Id == SPELL_TOUCH_OF_DOMINION_TRIGGERED)
551 {
553 {
554 sif->AI()->Talk(SAY_SIF_DESPAWN);
555 sif->DespawnOrUnsummon(6s);
556 _hardMode = false;
557 }
558 }
559 }
560
561 void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
562 {
563 if (target->GetTypeId() == TYPEID_PLAYER && spellInfo->Id == SPELL_LIGHTNING_RELEASE)
565 }
566
568 {
570 return;
571
572 _encounterFinished = true;
573
574 DoCastAOE(SPELL_CREDIT_KILL, true); // before change faction
575
579 me->AttackStop();
582
584 controller->RemoveAllAuras();
586 pillar->RemoveAllAuras();
587
588 if (_hardMode)
589 {
591 {
592 summons.Despawn(sif);
593 sif->DespawnOrUnsummon(10s);
594 }
595 }
596
597 _JustDied();
598
603
605 }
606
607 void MovementInform(uint32 type, uint32 id) override
608 {
609 if (type != EFFECT_MOTION_TYPE || id != EVENT_JUMP)
610 return;
611
614 }
615
616 void JustEngagedWith(Unit* who) override
617 {
620
622
626
631
633
634 if (Creature* runicColossus = instance->GetCreature(DATA_RUNIC_COLOSSUS))
635 {
636 runicColossus->SetImmuneToPC(false);
637 runicColossus->AI()->DoAction(ACTION_ACTIVATE_ADDS);
638 }
639
641 lever->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
642
643 // Summon Sif
645 }
646
647 void JustSummoned(Creature* summon) override
648 {
649 switch (summon->GetEntry())
650 {
652 {
654 summon->CastSpell(summon, SPELL_LIGHTNING_DESTRUCTION, true);
655
656 std::function<void(Movement::MoveSplineInit&)> initializer = [](Movement::MoveSplineInit& init)
657 {
659 path.reserve(LightningOrbPathSize);
660 std::transform(std::begin(LightningOrbPath), std::end(LightningOrbPath), std::back_inserter(path), [](Position const& pos)
661 {
662 return G3D::Vector3(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ());
663 });
664
665 init.MovebyPath(path);
666 };
667 summon->GetMotionMaster()->LaunchMoveSpline(std::move(initializer), 0, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE);
668 break;
669 }
675 summon->m_Events.AddEvent(new TrashJumpEvent(summon), summon->m_Events.CalculateTime(3s));
676 break;
677 case NPC_SIF:
679 break;
680 default:
681 break;
682 }
683
684 BossAI::JustSummoned(summon);
685 }
686
687 void UpdateAI(uint32 diff) override
688 {
689 if (!UpdateVictim())
690 return;
691
692 events.Update(diff);
693
695 return;
696
697 while (uint32 eventId = events.ExecuteEvent())
698 {
699 switch (eventId)
700 {
703 break;
706 sif->AI()->Talk(SAY_SIF_START);
707 break;
710 sif->CastSpell(me, SPELL_TOUCH_OF_DOMINION);
711 break;
714 events.Repeat(15s, 20s);
715 break;
716 case EVENT_CHARGE_ORB:
718 events.Repeat(15s, 20s);
719 break;
721 SummonWave();
722 events.Repeat(_orbSummoned ? 3s : 10s);
723 break;
724 case EVENT_JUMPDOWN:
725 if (_hardMode)
727 sif->AI()->DoAction(ACTION_START_HARD_MODE);
730 me->SetDisableGravity(false);
732 me->GetMotionMaster()->MoveJump(2134.8f, -263.056f, 419.983f, me->GetOrientation(), 30.0f, 20.0f);
736 break;
739 events.Repeat(15s, 20s);
740 break;
742 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
744 events.Repeat(7s, 15s);
745 break;
748 controller->CastSpell(controller, SPELL_ACTIVATE_LIGHTNING_ORB_PERIODIC, true);
749 break;
753 break;
754 case EVENT_BERSERK:
756 {
757 Talk(SAY_WIPE);
760 }
761 else
762 {
765 }
766 break;
768 {
769 std::list<Creature*> triggers;
771 triggers.remove_if([](Creature* bunny)
772 {
773 if (HeightPositionCheck(false)(bunny))
774 return true;
775 return LightningFieldCenter.GetExactDist2dSq(bunny) > 1296.0f;
776 });
777
778 Milliseconds timer = 1s;
779 for (Creature* bunny : triggers)
780 bunny->m_Events.AddEvent(new LightningFieldEvent(bunny), bunny->m_Events.CalculateTime(timer += 100ms));
781
782 triggers.remove_if([](Creature* bunny)
783 {
784 return LightningFieldCenter.GetExactDist2dSq(bunny) < 576.0f;
785 });
786
787 triggers.sort([](Creature* a, Creature* b)
788 {
789 return a->GetPositionX() < b->GetPositionX();
790 });
791
792 for (auto itr = triggers.cbegin(); itr != triggers.cend();)
793 {
794 auto prev = itr++;
795 if (itr != triggers.cend())
796 (*prev)->CastSpell(*itr, SPELL_LIGHTNING_BEAM_CHANNEL);
797 }
798 break;
799 }
800 case EVENT_OUTRO_1:
802 if (_hardMode)
804 break;
805 case EVENT_OUTRO_2:
807 if (_hardMode)
809 sif->SetStandState(UNIT_STAND_STATE_DEAD);
810 break;
811 case EVENT_OUTRO_3:
813 break;
814 default:
815 break;
816 }
817
819 return;
820 }
821
823 }
824
825 void DoAction(int32 action) override
826 {
827 switch (action)
828 {
829 case ACTION_BERSERK:
831 return;
832
833 if (!_orbSummoned)
834 {
835 _orbSummoned = true;
837 }
838 return;
840 if (++_killedCount >= 6)
841 {
842 // Event starts
843 me->SetImmuneToPC(false);
845 }
846 break;
847 default:
848 break;
849 }
850 }
851
852 void GetTrashSpawnTriggers(std::list<Creature*>& triggerList, uint32 count = 1)
853 {
855 triggerList.remove_if([](Creature* bunny)
856 {
857 if (HeightPositionCheck(false)(bunny))
858 return true;
859 return ArenaCenter.GetExactDist2dSq(bunny) < 3025.0f;
860 });
861
862 if (triggerList.empty())
863 return;
864
865 if (count == 1)
866 {
868 triggerList.clear();
869 triggerList.push_back(bunny);
870 }
871 else
872 Trinity::Containers::RandomResize(triggerList, count);
873 }
874
876 {
877 switch (_waveType)
878 {
879 case 0:
880 {
881 // Dark Rune Commoner
882 std::list<Creature*> triggers;
883 GetTrashSpawnTriggers(triggers, urand(5, 6));
884
885 for (Creature* bunny : triggers)
887
888 ++_waveType;
889 break;
890 }
891 case 1:
892 if (urand(0, 1))
893 {
894 // Dark Rune Champion or Dark Rune Evoker
895 std::list<Creature*> triggers;
896 GetTrashSpawnTriggers(triggers, urand(2, 4));
897
898 for (Creature* bunny : triggers)
900 }
901 else
902 {
903 // Dark Rune Warbringer
904 std::list<Creature*> triggers;
905 GetTrashSpawnTriggers(triggers);
906
907 for (Creature* bunny : triggers)
909 }
910 --_waveType;
911 break;
912 }
913 }
914
915 bool CanStartPhase2(Unit* actor) const
916 {
917 if (!actor || actor->GetTypeId() != TYPEID_PLAYER || !me->IsWithinDistInMap(actor, 10.0f))
918 return false;
919
922 return runicColossus && !runicColossus->IsAlive() && runeGiant && !runeGiant->IsAlive();
923 }
924
925 void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
926 {
927 if (events.IsInPhase(PHASE_1) && CanStartPhase2(attacker))
928 {
934
936 sif->InterruptNonMeleeSpells(false);
937
938 // Hard Mode
939 if (_hardMode)
941 }
942 else if (me->HealthBelowPctDamaged(1, damage))
943 {
944 damage = 0;
946 }
947 }
948
949 private:
957 };
958
959 CreatureAI* GetAI(Creature* creature) const override
960 {
961 return GetUlduarAI<boss_thorimAI>(creature);
962 }
963};
964
966{
968 {
969 _instance = creature->GetInstanceScript();
970 for (uint8 i = 0; i < ThorimTrashCount; ++i)
973
974 ASSERT(_info);
975 }
976
977 struct AIHelper
978 {
980 static uint32 GetTotalHeal(SpellInfo const* spellInfo, Unit const* caster)
981 {
982 uint32 heal = 0;
983 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
984 {
985 if (spellEffectInfo.IsEffect(SPELL_EFFECT_HEAL))
986 heal += spellEffectInfo.CalcValue(caster);
987
988 if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA) && spellEffectInfo.IsAura(SPELL_AURA_PERIODIC_HEAL))
989 heal += spellInfo->GetMaxTicks() * spellEffectInfo.CalcValue(caster);
990 }
991 return heal;
992 }
993
996 {
997 uint32 heal = 0;
999 for (AuraEffect const* aurEff : auras)
1000 heal += aurEff->GetAmount() * aurEff->GetRemainingTicks();
1001
1002 return heal;
1003 }
1004
1006 {
1007 public:
1008 MostHPMissingInRange(Unit const* referer, float range, uint32 hp, uint32 exclAura = 0, bool exclSelf = false)
1009 : _referer(referer), _range(range), _hp(hp), _exclAura(exclAura), _exclSelf(exclSelf) { }
1010
1012 {
1013 if (_exclSelf && u == _referer)
1014 return false;
1015
1016 if (_exclAura && u->HasAura(sSpellMgr->GetSpellIdForDifficulty(_exclAura, _referer)))
1017 return false;
1018
1019 if ((u->GetHealth() + GetRemainingHealOn(u) + _hp) > u->GetMaxHealth())
1020 return false;
1021
1022 uint32 missingHP = u->GetMaxHealth() - u->GetHealth();
1023 if (u->IsAlive() && _referer->IsFriendlyTo(u) && _referer->IsWithinDistInMap(u, _range) && missingHP > _hp)
1024 {
1025 _hp = missingHP;
1026 return true;
1027 }
1028
1029 return false;
1030 }
1031
1032 private:
1034 float _range;
1038 };
1039
1040 static Unit* GetUnitWithMostMissingHp(SpellInfo const* spellInfo, Unit* caster)
1041 {
1042 // use positive range, it's a healing spell
1043 float const range = spellInfo->GetMaxRange(true);
1044 uint32 const heal = GetTotalHeal(spellInfo, caster);
1045
1046 Unit* target = nullptr;
1047 MostHPMissingInRange checker(caster, range, heal);
1048 Trinity::UnitLastSearcher<MostHPMissingInRange> searcher(caster, target, checker);
1049 Cell::VisitGridObjects(caster, searcher, range);
1050
1051 return target;
1052 }
1053
1054 static Unit* GetHealTarget(SpellInfo const* spellInfo, Unit* caster)
1055 {
1056 Unit* healTarget = nullptr;
1057 if (!spellInfo->HasAttribute(SPELL_ATTR1_CANT_TARGET_SELF) && !roll_chance_f(caster->GetHealthPct()) && ((caster->GetHealth() + GetRemainingHealOn(caster) + GetTotalHeal(spellInfo, caster)) <= caster->GetMaxHealth()))
1058 healTarget = caster;
1059 else
1060 healTarget = GetUnitWithMostMissingHp(spellInfo, caster);
1061
1062 return healTarget;
1063 }
1064 };
1065
1066 bool UseAbility(uint32 spellId)
1067 {
1068 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
1069 if (!spellInfo)
1070 return false;
1071
1072 Unit* target = nullptr;
1073 if (AIHelper::GetTotalHeal(spellInfo, me))
1074 target = AIHelper::GetHealTarget(spellInfo, me);
1075 else
1076 target = me->GetVictim();
1077
1078 if (!target)
1079 return false;
1080
1082 {
1083 bool allowMove = true;
1084 if (me->IsInRange(target, spellInfo->GetMinRange(), spellInfo->GetMaxRange()))
1085 allowMove = false;
1086
1087 if (IsCombatMovementAllowed() != allowMove)
1088 {
1089 SetCombatMovement(allowMove);
1090
1091 // need relaunch movement
1093
1094 // give some time to allow reposition, try again in a second
1095 if (allowMove)
1096 return false;
1097 }
1098 }
1099
1100 DoCast(target, spellId);
1101 return true;
1102 }
1103
1104 void UpdateAI(uint32 diff) final override
1105 {
1106 if (!UpdateVictim())
1107 return;
1108
1109 _events.Update(diff);
1110
1112 return;
1113
1114 while (uint32 eventId = _events.ExecuteEvent())
1115 {
1116 ExecuteEvent(eventId);
1117
1119 return;
1120 }
1121
1124 else
1126 }
1127
1128 virtual void ExecuteEvent(uint32 eventId) = 0;
1129
1130protected:
1133
1134 ThorimTrashInfo const* _info = nullptr;
1135};
1136
1138{
1139 public:
1140 npc_thorim_pre_phase() : CreatureScript("npc_thorim_pre_phase") { }
1141
1143 {
1145 {
1146 me->setActive(true); // prevent grid unload
1147 me->SetFarVisible(true);
1148 }
1149
1150 void Reset() override
1151 {
1152 _events.Reset();
1153 if (_info->PrimaryAbility)
1156 {
1159 else
1161 }
1162 if (_info->ThirdAbility)
1165 SetCombatMovement(false);
1166 }
1167
1168 void JustDied(Unit* /*killer*/) override
1169 {
1170 if (Creature* thorim = _instance->GetCreature(DATA_THORIM))
1171 thorim->AI()->DoAction(ACTION_INCREASE_PREADDS_COUNT);
1172 }
1173
1174 bool ShouldSparWith(Unit const* target) const override
1175 {
1176 return !target->GetAffectingPlayer();
1177 }
1178
1179 void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1180 {
1181 // nullify spell damage
1182 if (!attacker || !attacker->GetAffectingPlayer())
1183 damage = 0;
1184 }
1185
1186 void ExecuteEvent(uint32 eventId) override
1187 {
1188 switch (eventId)
1189 {
1192 _events.ScheduleEvent(eventId, 15s, 20s);
1193 else
1194 _events.ScheduleEvent(eventId, 1s);
1195 break;
1198 {
1200 _events.ScheduleEvent(eventId, 2s);
1201 else
1202 _events.ScheduleEvent(eventId, 4s, 8s);
1203 }
1204 else
1205 _events.ScheduleEvent(eventId, 1s);
1206 break;
1209 _events.ScheduleEvent(eventId, 6s, 8s);
1210 else
1211 _events.ScheduleEvent(eventId, 1s);
1212 break;
1213 default:
1214 break;
1215 }
1216 }
1217 };
1218
1219 CreatureAI* GetAI(Creature* creature) const override
1220 {
1221 return GetUlduarAI<npc_thorim_pre_phaseAI>(creature);
1222 }
1223};
1224
1226{
1227 public:
1228 npc_thorim_arena_phase() : CreatureScript("npc_thorim_arena_phase") { }
1229
1231 {
1233 {
1234 switch (_info->Type)
1235 {
1236 case DARK_RUNE_CHAMPION:
1238 case DARK_RUNE_COMMONER:
1239 case DARK_RUNE_EVOKER:
1240 _isInArena = true;
1241 break;
1242 case DARK_RUNE_ACOLYTE:
1243 {
1246 break;
1247 }
1248 default:
1249 _isInArena = false;
1250 break;
1251 }
1252 }
1253
1254 bool CanAIAttack(Unit const* who) const override
1255 {
1256 // don't try to attack players in balcony
1257 if (_isInArena && HeightPositionCheck(true)(who))
1258 return false;
1259
1260 return IsInBoundary(who);
1261 }
1262
1275
1276 void JustEngagedWith(Unit* /*who*/) override
1277 {
1280
1281 if (!_isInArena)
1283 colossus->AI()->DoAction(ACTION_ACTIVATE_RUNIC_SMASH);
1284 }
1285
1286 void EnterEvadeMode(EvadeReason why) override
1287 {
1289 return;
1290
1291 // this should only happen if theres no alive player in the arena -> summon orb
1292 if (Creature* thorim = _instance->GetCreature(DATA_THORIM))
1293 thorim->AI()->DoAction(ACTION_BERSERK);
1295 }
1296
1297 void ExecuteEvent(uint32 eventId) override
1298 {
1299 switch (eventId)
1300 {
1303 _events.Repeat(3s, 6s);
1304 else
1305 _events.Repeat(1s);
1306 break;
1309 _events.Repeat(12s, 16s);
1310 else
1311 _events.Repeat(1s);
1312 break;
1315 _events.Repeat(6s, 8s);
1316 else
1317 _events.Repeat(1s);
1318 break;
1320 {
1321 Unit* referer = me;
1322 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [referer](Unit* unit){ return unit->GetTypeId() == TYPEID_PLAYER && unit->IsInRange(referer, 8.0f, 25.0f); }))
1323 DoCast(target, SPELL_CHARGE);
1324 _events.ScheduleEvent(eventId, 12s);
1325 break;
1326 }
1327 default:
1328 break;
1329 }
1330 }
1331
1332 private:
1334 };
1335
1336 CreatureAI* GetAI(Creature* creature) const override
1337 {
1338 return GetUlduarAI<npc_thorim_arena_phaseAI>(creature);
1339 }
1340};
1341
1343{
1345 {
1346 _instance = creature->GetInstanceScript();
1347
1349 }
1350
1351 bool CanAIAttack(Unit const* who) const final override
1352 {
1353 return IsInBoundary(who);
1354 }
1355
1356 void JustSummoned(Creature* summon) final override
1357 {
1358 _summons.Summon(summon);
1359 }
1360
1361 void SummonedCreatureDespawn(Creature* summon) final override
1362 {
1363 _summons.Despawn(summon);
1364 }
1365
1366 void DoAction(int32 action) override
1367 {
1368 if (action == ACTION_ACTIVATE_ADDS)
1369 {
1370 for (ObjectGuid const& guid : _summons)
1371 if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
1372 summon->SetImmuneToPC(false);
1373 }
1374 }
1375
1376protected:
1380};
1381
1383{
1384 public:
1385 npc_runic_colossus() : CreatureScript("npc_runic_colossus") { }
1386
1388 {
1390 {
1391 Initialize();
1392 }
1393
1395 {
1396 _runicActive = false;
1397 }
1398
1399 void Reset() override
1400 {
1401 Initialize();
1402 _events.Reset();
1403
1404 // close the Runic Door
1406
1407 // Spawn trashes
1409 for (SummonLocation const& s : ColossusAddLocations)
1411 }
1412
1413 void MoveInLineOfSight(Unit* /*who*/) override
1414 {
1415 // don't enter combat
1416 }
1417
1418 void DoAction(int32 action) override
1419 {
1421
1422 if (_runicActive)
1423 return;
1424
1425 if (action == ACTION_ACTIVATE_RUNIC_SMASH)
1426 {
1427 _runicActive = true;
1429 }
1430 }
1431
1432 void JustDied(Unit* /*killer*/) override
1433 {
1434 // open the Runic Door
1436
1437 if (Creature* thorim = _instance->GetCreature(DATA_THORIM))
1438 thorim->AI()->Talk(SAY_SPECIAL);
1439
1441 {
1442 giant->SetImmuneToPC(false);
1443 giant->AI()->DoAction(ACTION_ACTIVATE_ADDS);
1444 }
1445 }
1446
1447 void JustEngagedWith(Unit* /*who*/) override
1448 {
1450 _events.Reset();
1454 }
1455
1456 void UpdateAI(uint32 diff) override
1457 {
1458 _events.Update(diff);
1459
1461 return;
1462
1463 while (uint32 eventId = _events.ExecuteEvent())
1464 {
1465 switch (eventId)
1466 {
1470 _events.Repeat(35s, 45s);
1471 break;
1472 case EVENT_SMASH:
1474 _events.Repeat(15s, 18s);
1475 break;
1476 case EVENT_RUNIC_CHARGE:
1477 {
1478 Unit* referer = me;
1479 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [referer](Unit* unit){ return unit->GetTypeId() == TYPEID_PLAYER && unit->IsInRange(referer, 8.0f, 40.0f); }))
1480 DoCast(target, SPELL_RUNIC_CHARGE);
1481 _events.Repeat(20s);
1482 break;
1483 }
1484 case EVENT_RUNIC_SMASH:
1486 _events.Repeat(6s);
1487 break;
1488 default:
1489 break;
1490 }
1491
1493 return;
1494 }
1495
1496 if (!UpdateVictim())
1497 return;
1498
1500 }
1501
1502 private:
1504 };
1505
1506 CreatureAI* GetAI(Creature* creature) const override
1507 {
1508 return GetUlduarAI<npc_runic_colossusAI>(creature);
1509 }
1510};
1511
1513{
1514 public:
1515 npc_ancient_rune_giant() : CreatureScript("npc_ancient_rune_giant") { }
1516
1518 {
1520
1521 void Reset() override
1522 {
1523 _events.Reset();
1524
1525 // close the Stone Door
1527
1528 // Spawn trashes
1530 for (SummonLocation const& s : GiantAddLocations)
1532 }
1533
1542
1543 void JustDied(Unit* /*killer*/) override
1544 {
1545 // opem the Stone Door
1547 }
1548
1549 void UpdateAI(uint32 diff) override
1550 {
1551 if (!UpdateVictim())
1552 return;
1553
1554 _events.Update(diff);
1555
1557 return;
1558
1559 while (uint32 eventId = _events.ExecuteEvent())
1560 {
1561 switch (eventId)
1562 {
1566 break;
1567 case EVENT_STOMP:
1569 _events.Repeat(10s, 12s);
1570 break;
1572 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
1574 _events.Repeat(10s, 12s);
1575 break;
1576 default:
1577 break;
1578 }
1579
1581 return;
1582 }
1583
1585 }
1586 };
1587
1588 CreatureAI* GetAI(Creature* creature) const override
1589 {
1590 return GetUlduarAI<npc_ancient_rune_giantAI>(creature);
1591 }
1592};
1593
1595{
1596 public:
1597 npc_sif() : CreatureScript("npc_sif") { }
1598
1599 struct npc_sifAI : public ScriptedAI
1600 {
1601 npc_sifAI(Creature* creature) : ScriptedAI(creature)
1602 {
1603 SetCombatMovement(false);
1604 _instance = creature->GetInstanceScript();
1605 }
1606
1607 void Reset() override
1608 {
1609 _events.Reset();
1610 }
1611
1612 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
1613 {
1614 if (spellInfo->Id == SPELL_STORMHAMMER_SIF)
1615 {
1618 me->AttackStop();
1619 }
1620 }
1621
1622 void DoAction(int32 action) override
1623 {
1624 if (action == ACTION_START_HARD_MODE)
1625 {
1629 _events.Reset();
1634 }
1635 }
1636
1637 void UpdateAI(uint32 diff) override
1638 {
1639 if (!UpdateVictim())
1640 return;
1641
1642 _events.Update(diff);
1643
1645 return;
1646
1647 while (uint32 eventId = _events.ExecuteEvent())
1648 {
1649 switch (eventId)
1650 {
1651 case EVENT_BLINK:
1652 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
1653 DoCast(target, SPELL_BLINK);
1655 _events.Repeat(20s, 25s);
1656 return;
1657 case EVENT_FROST_NOVA:
1659 return;
1660 case EVENT_FROSTBOLT:
1661 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
1662 DoCast(target, SPELL_FROSTBOLT);
1663 _events.Repeat(2s);
1664 return;
1667 _events.Repeat(15s, 20s);
1668 return;
1669 case EVENT_BLIZZARD:
1671 _events.Repeat(35s, 45s);
1672 return;
1673 default:
1674 break;
1675 }
1676
1678 return;
1679 }
1680
1681 // no melee attack
1682 }
1683
1684 private:
1687 };
1688
1689 CreatureAI* GetAI(Creature* creature) const override
1690 {
1691 return GetUlduarAI<npc_sifAI>(creature);
1692 }
1693};
1694
1695// 62576 - Blizzard
1696// 62602 - Blizzard
1698{
1699 public:
1700 spell_thorim_blizzard_effect() : SpellScriptLoader("spell_thorim_blizzard_effect") { }
1701
1703 {
1705
1706 bool CheckAreaTarget(Unit* target)
1707 {
1709 if (target != GetOwner())
1710 {
1711 // check if not stacking aura already on target
1712 // this one prevents overriding auras periodically by 2 near area aura owners
1713 Unit::AuraApplicationMap const& auraMap = target->GetAppliedAuras();
1714 for (Unit::AuraApplicationMap::const_iterator iter = auraMap.begin(); iter != auraMap.end(); ++iter)
1715 {
1716 Aura const* aura = iter->second->GetBase();
1717 if (GetId() == aura->GetId() && GetOwner() != aura->GetOwner() )
1718 return false;
1719 }
1720 }
1721
1722 return true;
1723 }
1724
1729 };
1730
1731 AuraScript* GetAuraScript() const override
1732 {
1734 }
1735};
1736
1737// 62580, 62604 - Frostbolt Volley
1739{
1740 public:
1741 spell_thorim_frostbolt_volley() : SpellScriptLoader("spell_thorim_frostbolt_volley") { }
1742
1744 {
1746
1747 void FilterTargets(std::list<WorldObject*>& targets)
1748 {
1749 targets.remove_if([](WorldObject* object) -> bool
1750 {
1751 if (object->GetTypeId() == TYPEID_PLAYER)
1752 return false;
1753
1754 if (Creature* creature = object->ToCreature())
1755 return !creature->IsPet();
1756
1757 return true;
1758 });
1759 }
1760
1765 };
1766
1767 SpellScript* GetSpellScript() const override
1768 {
1770 }
1771};
1772
1773// 62016 - Charge Orb
1775{
1776 public:
1777 spell_thorim_charge_orb() : SpellScriptLoader("spell_thorim_charge_orb") { }
1778
1780 {
1782
1783 bool Validate(SpellInfo const* /*spellInfo*/) override
1784 {
1786 }
1787
1788 void FilterTargets(std::list<WorldObject*>& targets)
1789 {
1790 targets.remove_if(HeightPositionCheck(false));
1791
1792 if (targets.empty())
1793 return;
1794
1796 targets.clear();
1797 targets.push_back(target);
1798 }
1799
1801 {
1802 if (Unit* target = GetHitUnit())
1803 target->CastSpell(nullptr, SPELL_LIGHTNING_PILLAR_1, true);
1804 }
1805
1811 };
1812
1813 SpellScript* GetSpellScript() const override
1814 {
1816 }
1817};
1818
1819// 62466 - Lightning Charge
1821{
1822 public:
1823 spell_thorim_lightning_charge() : SpellScriptLoader("spell_thorim_lightning_charge") { }
1824
1826 {
1828
1829 bool Validate(SpellInfo const* /*spellInfo*/) override
1830 {
1832 }
1833
1835 {
1837 if (Creature* creature = GetCaster()->ToCreature())
1838 creature->SetSpellFocus(GetSpell(), GetExplTargetWorldObject());
1839 }
1840
1845
1851 };
1852
1853 SpellScript* GetSpellScript() const override
1854 {
1856 }
1857};
1858
1859// 61934 - Leap
1861{
1862 public:
1863 spell_thorim_arena_leap() : SpellScriptLoader("spell_thorim_arena_leap") { }
1864
1866 {
1868
1869 bool Load() override
1870 {
1871 return GetCaster()->GetTypeId() == TYPEID_UNIT;
1872 }
1873
1874 void HandleScript(SpellEffIndex /*effIndex*/)
1875 {
1876 if (Position const* pos = GetHitDest())
1878 }
1879
1884 };
1885
1886 SpellScript* GetSpellScript() const override
1887 {
1889 }
1890};
1891
1893{
1894 bool operator()(Position const* who) const
1895 {
1897 }
1898};
1899
1900// 62042 - Stormhammer
1902{
1903 public:
1904 spell_thorim_stormhammer() : SpellScriptLoader("spell_thorim_stormhammer") { }
1905
1907 {
1909
1910 bool Validate(SpellInfo const* /*spellInfo*/) override
1911 {
1913 }
1914
1915 void FilterTargets(std::list<WorldObject*>& targets)
1916 {
1917 targets.remove_if([](WorldObject* target) -> bool { return HeightPositionCheck(true)(target) || OutOfArenaCheck()(target); });
1918
1919 if (targets.empty())
1920 {
1922 return;
1923 }
1924
1926 targets.clear();
1927 targets.push_back(target);
1928 }
1929
1930 void HandleScript(SpellEffIndex /*effIndex*/)
1931 {
1932 if (Unit* target = GetHitUnit())
1933 {
1934 target->CastSpell(target, SPELL_DEAFENING_THUNDER, true);
1935 target->CastSpell(GetCaster(), SPELL_STORMHAMMER_BOOMERANG, true);
1936 }
1937 }
1938
1940 {
1941 GetCaster()->SetVirtualItem(0, 0);
1942 }
1943
1950 };
1951
1952 SpellScript* GetSpellScript() const override
1953 {
1955 }
1956};
1957
1958// 64767 - Stormhammer
1960{
1961 public:
1962 spell_thorim_stormhammer_sif() : SpellScriptLoader("spell_thorim_stormhammer_sif") { }
1963
1965 {
1967
1968 bool Validate(SpellInfo const* /*spellInfo*/) override
1969 {
1971 }
1972
1973 void HandleScript(SpellEffIndex /*effIndex*/)
1974 {
1975 if (Unit* target = GetHitUnit())
1976 {
1977 target->CastSpell(GetCaster(), SPELL_STORMHAMMER_BOOMERANG, true);
1978 target->CastSpell(target, SPELL_SIF_TRANSFORM, true);
1979 }
1980 }
1981
1983 {
1984 GetCaster()->SetVirtualItem(0, 0);
1985 }
1986
1992 };
1993
1994 SpellScript* GetSpellScript() const override
1995 {
1997 }
1998};
1999
2000// 64909 - Stormhammer
2027
2028// 62057, 62058 - Runic Smash
2030{
2031 public:
2032 spell_thorim_runic_smash() : SpellScriptLoader("spell_thorim_runic_smash") { }
2033
2035 {
2037
2038 bool Validate(SpellInfo const* /*spellInfo*/) override
2039 {
2041 }
2042
2044 {
2045 PreventHitDefaultEffect(effIndex);
2046
2047 std::vector<Creature*> triggers;
2049 for (Creature* trigger : triggers)
2050 {
2051 Milliseconds time = Milliseconds(uint64(GetCaster()->GetExactDist(trigger) * 30.f));
2052 trigger->m_Events.AddEvent(new RunicSmashExplosionEvent(trigger), trigger->m_Events.CalculateTime(time));
2053 };
2054 }
2055
2060 };
2061
2062 SpellScript* GetSpellScript() const override
2063 {
2065 }
2066};
2067
2069{
2070 public:
2071 UpperOrbCheck() : _check(true) { }
2072
2073 bool operator() (Creature* target) const
2074 {
2075 return target->GetEntry() == NPC_THUNDER_ORB && _check(target);
2076 }
2077
2078 private:
2080};
2081
2082// 62184 - Activate Lightning Orb Periodic
2084{
2085 public:
2086 spell_thorim_activate_lightning_orb_periodic() : SpellScriptLoader("spell_thorim_activate_lightning_orb_periodic") { }
2087
2089 {
2091
2093
2094 void PeriodicTick(AuraEffect const* /*aurEff*/)
2095 {
2097
2098 Unit* caster = GetCaster();
2099 std::vector<Creature*> triggers;
2100
2101 UpperOrbCheck check;
2102 Trinity::CreatureListSearcher<UpperOrbCheck> searcher(caster, triggers, check);
2103 Cell::VisitGridObjects(caster, searcher, 100.f);
2104
2105 if (!triggers.empty())
2106 {
2108 if (Creature* thorim = instance->GetCreature(DATA_THORIM))
2109 thorim->AI()->SetGUID(target->GetGUID(), DATA_CHARGED_PILLAR);
2110 }
2111 }
2112
2113 bool Load() override
2114 {
2115 if (Unit* caster = GetCaster())
2116 instance = caster->GetInstanceScript();
2117
2118 return instance != nullptr;
2119 }
2120
2125 };
2126
2131};
2132
2133// 62320 - Aura of Celerity
2153
2155{
2156 public:
2157 achievement_dont_stand_in_the_lightning() : AchievementCriteriaScript("achievement_dont_stand_in_the_lightning") { }
2158
2159 bool OnCheck(Player* /*source*/, Unit* target) override
2160 {
2161 return target && target->GetAI()->GetData(ACHIEVEMENT_DONT_STAND_IN_THE_LIGHTNING);
2162 }
2163};
2164
2166{
2167 public:
2168 achievement_lose_your_illusion() : AchievementCriteriaScript("achievement_lose_your_illusion") { }
2169
2170 bool OnCheck(Player* /*source*/, Unit* target) override
2171 {
2172 return target && target->GetAI()->GetData(ACHIEVEMENT_LOSE_YOUR_ILLUSION);
2173 }
2174};
2175
2177{
2178 public:
2179 achievement_i_ll_take_you_all_on() : AchievementCriteriaScript("achievement_i_ll_take_you_all_on"), _check() { }
2180
2181 bool OnCheck(Player* source, Unit* /*target*/) override
2182 {
2183 return _check(source);
2184 }
2185
2186 private:
2188};
2189
2191{
2192 public:
2193 condition_thorim_arena_leap() : ConditionScript("condition_thorim_arena_leap"), _check(false) { }
2194
2195 bool OnConditionCheck(Condition const* condition, ConditionSourceInfo& sourceInfo) override
2196 {
2197 WorldObject* target = sourceInfo.mConditionTargets[condition->ConditionTarget];
2198 InstanceScript* instance = target->GetInstanceScript();
2199
2200 if (!instance)
2201 return false;
2202
2203 return _check(target);
2204 }
2205
2206 private:
2208};
2209
Actions
First const & RAND(First const &first, Second const &second, Rest const &... rest)
std::vector< AreaBoundary const * > CreatureBoundary
Definition CreatureAI.h:36
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint64_t uint64
Definition Define.h:132
uint32_t uint32
Definition Define.h:133
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
#define ASSERT
Definition Errors.h:68
@ IN_PROGRESS
@ MOTION_PRIORITY_NORMAL
@ POINT_MOTION_TYPE
@ EFFECT_MOTION_TYPE
@ TEMPSUMMON_CORPSE_TIMED_DESPAWN
@ TYPEID_UNIT
Definition ObjectGuid.h:38
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
Spells
Definition PlayerAI.cpp:32
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
bool roll_chance_f(float chance)
Definition Random.h:53
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
SpellEffIndex
@ EFFECT_0
@ EFFECT_2
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_HEAL
@ SPELL_EFFECT_TRIGGER_SPELL
@ SPELL_EFFECT_JUMP_DEST
@ SPELL_EFFECT_APPLY_AURA
@ TARGET_UNIT_SRC_AREA_ENTRY
@ TARGET_UNIT_SRC_AREA_ENEMY
@ EVENT_JUMP
@ SPELL_ATTR1_CANT_TARGET_SELF
@ GO_FLAG_NOT_SELECTABLE
@ FACTION_FRIENDLY
#define EFFECT_ALL
@ SPELL_FAILED_NO_VALID_TARGETS
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_MELEE_SLOW
@ SPELL_AURA_PERIODIC_HEAL
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
#define sSpellMgr
Definition SpellMgr.h:738
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
#define SpellCastFn(F)
#define SpellHitFn(F)
#define AuraCheckAreaTargetFn(F)
#define AuraEffectRemoveFn(F, I, N, M)
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STAND_STATE_DEAD
Definition UnitDefines.h:41
@ UNIT_FLAG_RENAME
@ CURRENT_GENERIC_SPELL
Definition Unit.h:607
@ UNIT_STATE_ROOT
Definition Unit.h:230
@ UNIT_STATE_CASTING
Definition Unit.h:235
DamageEffectType
Definition Unit.h:352
Data
SummonLocation const ColossusAddLocations[]
@ ACTION_PILLAR_CHARGED
@ ACTION_BERSERK
@ ACTION_INCREASE_PREADDS_COUNT
@ ACTION_START_HARD_MODE
@ ACTION_ACTIVATE_RUNIC_SMASH
@ ACTION_ACTIVATE_ADDS
CircleBoundary const ArenaFloorCircle(ArenaCenter, 45.4)
@ SAY_DEATH
@ SAY_AGGRO_2
@ EMOTE_RUNIC_MIGHT
@ SAY_SIF_EVENT
@ SAY_WIPE
@ EMOTE_RUNIC_BARRIER
@ SAY_END_HARD_3
@ SAY_SIF_START
@ SAY_SPECIAL
@ SAY_END_NORMAL_3
@ SAY_END_NORMAL_2
@ SAY_END_NORMAL_1
@ SAY_SLAY
@ SAY_END_HARD_1
@ SAY_AGGRO_1
@ SAY_SIF_DESPAWN
@ SAY_BERSERK
@ SAY_JUMPDOWN
@ SAY_END_HARD_2
uint8 const ThorimTrashCount
std::size_t const LightningOrbPathSize
@ SPELL_STOMP
@ SPELL_BLINK
@ SPELL_RUNE_DETONATION
@ SPELL_TOUCH_OF_DOMINION
@ SPELL_LIGHTNING_BEAM_CHANNEL
@ SPELL_SHEATH_OF_LIGHTNING
@ SPELL_LIGHTNING_PILLAR_2
@ SPELL_LIGHTNING_FIELD
@ SPELL_FROSTBOLT
@ SPELL_BERSERK_PHASE_2
@ SPELL_TOUCH_OF_DOMINION_TRIGGERED
@ SPELL_RUNIC_SMASH_LEFT
@ SPELL_UNBALANCING_STRIKE
@ SPELL_DEAFENING_THUNDER
@ SPELL_BERSERK_PHASE_1
@ SPELL_STORMHAMMER_SIF
@ SPELL_RUNIC_FORTIFICATION
@ SPELL_STORMHAMMER
@ SPELL_ACTIVATE_LIGHTNING_ORB_PERIODIC
@ SPELL_SUMMON_LIGHTNING_ORB
@ SPELL_CHARGE_ORB
@ SPELL_LIGHTNING_ORB_CHARGED
@ SPELL_BLIZZARD
@ SPELL_SMASH
@ SPELL_FROSTBOLT_VOLLEY
@ SPELL_LIGHTNING_PILLAR_1
@ SPELL_LIGHTNING_CHARGE
@ SPELL_SIF_TRANSFORM
@ SPELL_STORMHAMMER_BOOMERANG
@ SPELL_CHAIN_LIGHTNING
@ SPELL_FROSTNOVA
@ SPELL_LIGHTNING_DESTRUCTION
@ SPELL_LIGHTNING_RELEASE
@ SPELL_RUNIC_CHARGE
@ SPELL_RUNIC_SMASH_RIGHT
@ SPELL_CREDIT_KILL
@ SPELL_RUNIC_SMASH
@ SPELL_RUNIC_BARRIER
@ SPELL_CREDIT_SIFFED
@ PHASE_NULL
@ PHASE_2
@ PHASE_1
CreatureBoundary const ArenaBoundaries
Position const ArenaCenter
Position const LightningOrbPath[]
void AddSC_boss_thorim()
CircleBoundary const InvertedBalconyCircle(LightningFieldCenter, 32.0, true)
Position const LightningFieldCenter
ThorimTrashInfo const StaticThorimTrashInfo[ThorimTrashCount]
PreAddSpells
@ SPELL_CIRCLE_OF_HEALING
61965
@ SPELL_RUNIC_STRIKE
@ SPELL_HAMSTRING
@ SPELL_CLEAVE
@ SPELL_GREATER_HEAL
@ SPELL_SHOOT
@ SPELL_CHARGE
@ SPELL_RUNIC_MENDING
@ SPELL_AURA_OF_CELERITY_VISUAL
@ SPELL_SWEEP
@ SPELL_BARBED_SHOT
@ SPELL_PUMMEL
@ SPELL_HEROIC_SWIPE
@ SPELL_RUNIC_LIGHTNING
@ SPELL_HOLY_SMITE
@ SPELL_MORTAL_STRIKE
@ SPELL_SUNDER_ARMOR
@ SPELL_RUNIC_SHIELD
@ SPELL_RENEW
@ SPELL_LEAP
@ SPELL_LOW_BLOW
@ SPELL_AURA_OF_CELERITY
@ SPELL_SHIELD_SMASH
@ SPELL_WHIRLING_TRIP
@ SPELL_DEVASTATE
@ SPELL_WHIRLWIND
@ SPELL_IMPALE
@ SPELL_ACID_BREATH
TrashTypes
@ DARK_RUNE_EVOKER
@ MERCENARY_CAPTAIN
@ DARK_RUNE_ACOLYTE
@ IRON_RING_GUARD
@ DARK_RUNE_CHAMPION
@ BEHEMOTH
@ DARK_RUNE_COMMONER
@ MERCENARY_SOLDIER
@ IRON_HONOR_GUARD
@ DARK_RUNE_WARBRINGER
@ THORIM_WEAPON_DISPLAY_ID
SummonLocation const GiantAddLocations[]
Position const SifSpawnPosition
@ ACHIEVEMENT_LOSE_YOUR_ILLUSION
@ ACHIEVEMENT_DONT_STAND_IN_THE_LIGHTNING
@ ACHIEVEMENT_SIFFED
@ DATA_CHARGED_PILLAR
@ EVENT_CHAIN_LIGHTNING
@ EVENT_BLINK
@ EVENT_ACTIVATE_LIGHTNING_FIELD
@ EVENT_CHARGE_ORB
@ EVENT_RUNIC_BARRIER
@ EVENT_OUTRO_2
@ EVENT_OUTRO_3
@ EVENT_JUMPDOWN
@ EVENT_FROSTBOLT_VOLLEY
@ EVENT_SAY_SIF_START
@ EVENT_RUNIC_FORTIFICATION
@ EVENT_ABILITY_CHARGE
@ EVENT_SMASH
@ EVENT_RUNE_DETONATION
@ EVENT_SECONDARY_ABILITY
@ EVENT_BERSERK
@ EVENT_SUMMON_ADDS
@ EVENT_START_PERIODIC_CHARGE
@ EVENT_RUNIC_CHARGE
@ EVENT_STOMP
@ EVENT_FROST_NOVA
@ EVENT_BLIZZARD
@ EVENT_OUTRO_1
@ EVENT_START_SIF_CHANNEL
@ EVENT_STORMHAMMER
@ EVENT_RUNIC_SMASH
@ EVENT_LIGHTNING_CHARGE
@ EVENT_THIRD_ABILITY
@ EVENT_PRIMARY_ABILITY
@ EVENT_FROSTBOLT
@ EVENT_SAY_AGGRO_2
@ EVENT_UNBALANCING_STRIKE
SummonLocation const PreAddLocations[]
Yells
void PreventDefaultAction()
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectPeriodicHandler > OnEffectPeriodic
WorldObject * GetOwner() const
Unit * GetCaster() const
HookList< CheckAreaTargetHandler > DoCheckAreaTarget
Unit * GetTarget() const
uint32 GetId() const
WorldObject * GetOwner() const
Definition SpellAuras.h:121
uint32 GetId() const
Definition SpellAuras.h:116
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
void JustSummoned(Creature *summon) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
SummonList summons
EventMap events
static bool IsInBounds(CreatureBoundary const &boundary, Position const *who)
@ EVADE_REASON_BOUNDARY
Definition CreatureAI.h:95
@ EVADE_REASON_NO_HOSTILES
Definition CreatureAI.h:94
void DoZoneInCombat(Creature *creature=nullptr)
bool IsInBoundary(Position const *who=nullptr) const
bool UpdateVictim()
void SetBoundary(CreatureBoundary const *boundary, bool negativeBoundaries=false)
Creature *const me
Definition CreatureAI.h:82
virtual void EnterEvadeMode(EvadeReason why=EVADE_REASON_OTHER)
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:293
void SetImmuneToPC(bool apply) override
Definition Creature.h:129
void SetReactState(ReactStates st)
Definition Creature.h:119
CreatureAI * AI() const
Definition Creature.h:154
void Update(uint32 time)
Definition EventMap.h:67
void Repeat(Milliseconds time)
Definition EventMap.cpp:63
EventId ExecuteEvent()
Definition EventMap.cpp:73
bool IsInPhase(PhaseIndex phase) const
Definition EventMap.h:236
void RescheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:52
void SetPhase(PhaseIndex phase)
Definition EventMap.cpp:28
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
void Reset()
Definition EventMap.cpp:21
void AddEvent(BasicEvent *event, Milliseconds e_time, bool set_addtime=true)
Milliseconds CalculateTime(Milliseconds t_offset) const
HeightPositionCheck(bool ret)
bool operator()(Position const *pos) const
static float const THORIM_BALCONY_Z_CHECK
Creature * GetCreature(uint32 type)
void HandleGameObject(ObjectGuid guid, bool open, GameObject *go=nullptr)
virtual ObjectGuid GetGuidData(uint32 type) const override
GameObject * GetGameObject(uint32 type)
bool Execute(uint64 eventTime, uint32) override
LightningFieldEvent(Creature *owner)
void LaunchMoveSpline(std::function< void(Movement::MoveSplineInit &init)> &&initializer, uint32 id=0, MovementGeneratorPriority priority=MOTION_PRIORITY_NORMAL, MovementGeneratorType type=EFFECT_MOTION_TYPE)
void MoveJump(Position const &pos, float speedXY, float speedZ, uint32 id=EVENT_JUMP, bool hasOrientation=false)
void Clear()
Definition ObjectGuid.h:150
static Creature * ToCreature(Object *o)
Definition Object.h:186
TypeID GetTypeId() const
Definition Object.h:93
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:760
uint32 GetEntry() const
Definition Object.h:81
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
RunicSmashExplosionEvent(Creature *owner)
bool Execute(uint64, uint32) override
uint32 GetMaxTicks() const
float GetMaxRange(bool positive=false, WorldObject *caster=nullptr, Spell *spell=nullptr) const
uint32 Id
Definition SpellInfo.h:289
float GetMinRange(bool positive=false) const
bool HasAttribute(SpellAttr0 attribute) const
Definition SpellInfo.h:375
std::array< SpellEffectInfo, MAX_SPELL_EFFECTS > const & GetEffects() const
Definition SpellInfo.h:482
HookList< CastHandler > AfterCast
WorldLocation * GetHitDest() const
Unit * GetCaster() const
HookList< HitHandler > AfterHit
void PreventHitDefaultEffect(SpellEffIndex effIndex)
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
HookList< CastHandler > BeforeCast
Spell * GetSpell() const
WorldObject * GetExplTargetWorldObject() const
HookList< EffectHandler > OnEffectLaunch
SpellInfo const * GetSpellInfo() const
void FinishCast(SpellCastResult result, uint32 *param1=nullptr, uint32 *param2=nullptr)
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
void Despawn(Creature const *summon)
void Summon(Creature const *summon)
bool Execute(uint64 eventTime, uint32) override
TrashJumpEvent(Creature *owner)
Creature * _owner
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
virtual uint32 GetData(uint32) const
Definition UnitAI.h:155
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:96
bool DoSpellAttackIfReady(uint32 spell)
Definition UnitAI.cpp:78
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:243
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1384
float GetHealthPct() const
Definition Unit.h:921
void SetControlled(bool apply, UnitState state)
Definition Unit.cpp:11256
std::multimap< uint32, AuraApplication * > AuraApplicationMap
Definition Unit.h:780
void SetFaction(uint32 faction) override
Definition Unit.h:974
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3093
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
uint32 GetMaxHealth() const
Definition Unit.h:914
bool IsAlive() const
Definition Unit.h:1234
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4535
UnitAI * GetAI() const
Definition Unit.h:800
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition Unit.cpp:13286
void SetVirtualItem(uint32 slot, uint32 itemId)
Definition Unit.cpp:13868
void InterruptSpell(CurrentSpellTypes spellType, bool withDelayed=true, bool withInstant=true, SpellCastResult result=SPELL_FAILED_INTERRUPTED, Optional< SpellCastResult > resultOther={})
Definition Unit.cpp:3021
uint32 GetHealth() const
Definition Unit.h:913
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
Unit * GetVictim() const
Definition Unit.h:859
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
void RemoveAllAttackers()
Definition Unit.cpp:5736
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition Unit.h:918
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:954
AuraApplicationMap & GetAppliedAuras()
Definition Unit.h:1338
std::list< AuraEffect * > AuraEffectList
Definition Unit.h:787
bool AttackStop()
Definition Unit.cpp:5645
HeightPositionCheck const _check
bool operator()(Creature *target) const
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1087
void GetCreatureListWithEntryInGrid(Container &creatureContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition Object.cpp:3153
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1992
void setActive(bool isActiveObject)
Definition Object.cpp:991
void SetFarVisible(bool on)
Definition Object.cpp:1014
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:1192
bool IsInRange(WorldObject const *obj, float minRange, float maxRange, bool is3D=true) const
Definition Object.cpp:1283
EventProcessor m_Events
Definition Object.h:591
bool IsFriendlyTo(WorldObject const *target) const
Definition Object.cpp:2801
Player * GetAffectingPlayer() const
Definition Object.cpp:2212
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
bool OnCheck(Player *, Unit *target) override
bool OnCheck(Player *source, Unit *) override
bool OnCheck(Player *, Unit *target) override
CreatureAI * GetAI(Creature *creature) const override
HeightPositionCheck _check
bool OnConditionCheck(Condition const *condition, ConditionSourceInfo &sourceInfo) 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
MostHPMissingInRange(Unit const *referer, float range, uint32 hp, uint32 exclAura=0, bool exclSelf=false)
AuraScript * GetAuraScript() const override
PrepareSpellScript(spell_thorim_arena_leap_SpellScript)
SpellScript * GetSpellScript() const override
PrepareAuraScript(spell_thorim_aura_of_celerity)
bool Validate(SpellInfo const *) override
void AfterRemove(AuraEffect const *, AuraEffectHandleModes)
AuraScript * GetAuraScript() const override
void FilterTargets(std::list< WorldObject * > &targets)
PrepareSpellScript(spell_thorim_charge_orb_SpellScript)
SpellScript * GetSpellScript() const override
SpellScript * GetSpellScript() const override
SpellScript * GetSpellScript() const override
PrepareSpellScript(spell_thorim_runic_smash_SpellScript)
SpellScript * GetSpellScript() const override
void FilterTargets(std::list< WorldObject * > &targets)
PrepareSpellScript(spell_thorim_stormhammer_SpellScript)
SpellScript * GetSpellScript() const override
PrepareSpellScript(spell_thorim_stormhammer_sif_SpellScript)
SpellScript * GetSpellScript() const override
SpellScript * GetSpellScript() const override
std::vector< Vector3 > PointsArray
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition Containers.h:108
void RandomResize(C &container, std::size_t requestedSize)
Definition Containers.h:66
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:168
WorldObject * mConditionTargets[MAX_CONDITION_TARGETS]
uint8 ConditionTarget
bool operator()(Position const *who) const
float GetExactDist2dSq(const float x, const float y) const
Definition Position.h:100
float GetPositionZ() const
Definition Position.h:81
float GetOrientation() const
Definition Position.h:82
float GetPositionX() const
Definition Position.h:79
float GetPositionY() const
Definition Position.h:80
void AttackStart(Unit *) override
void SetCombatMovement(bool allowMovement)
bool IsCombatMovementAllowed() const
void ResetThreatList(Unit *who=nullptr)
void DamageTaken(Unit *attacker, uint32 &damage, DamageEffectType, SpellInfo const *) override
void UpdateAI(uint32 diff) override
boss_thorimAI(Creature *creature)
uint32 GetData(uint32 type) const override
void KilledUnit(Unit *who) override
void GetTrashSpawnTriggers(std::list< Creature * > &triggerList, uint32 count=1)
void EnterEvadeMode(EvadeReason) override
void SpellHitTarget(WorldObject *target, SpellInfo const *spellInfo) override
void MovementInform(uint32 type, uint32 id) override
void SetGUID(ObjectGuid const &guid, int32 id) override
bool CanStartPhase2(Unit *actor) const
void JustSummoned(Creature *summon) override
void JustEngagedWith(Unit *who) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void DoAction(int32 action) override
void DoAction(int32 action) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void DoAction(int32 action) override
void Reset() override
void UpdateAI(uint32 diff) override
npc_sifAI(Creature *creature)
InstanceScript * _instance
void EnterEvadeMode(EvadeReason why) override
bool CanAIAttack(Unit const *who) const override
void JustSummoned(Creature *summon) final override
npc_thorim_minibossAI(Creature *creature)
bool CanAIAttack(Unit const *who) const final override
void SummonedCreatureDespawn(Creature *summon) final override
void DoAction(int32 action) override
InstanceScript * _instance
void ExecuteEvent(uint32 eventId) override
void DamageTaken(Unit *attacker, uint32 &damage, DamageEffectType, SpellInfo const *) override
bool ShouldSparWith(Unit const *target) const override
static uint32 GetRemainingHealOn(Unit *target)
returns remaining heal amount on given target
static Unit * GetUnitWithMostMissingHp(SpellInfo const *spellInfo, Unit *caster)
static Unit * GetHealTarget(SpellInfo const *spellInfo, Unit *caster)
static uint32 GetTotalHeal(SpellInfo const *spellInfo, Unit const *caster)
returns heal amount of the given spell including hots
npc_thorim_trashAI(Creature *creature)
void UpdateAI(uint32 diff) final override
InstanceScript * _instance
ThorimTrashInfo const * _info
virtual void ExecuteEvent(uint32 eventId)=0
bool UseAbility(uint32 spellId)
@ DATA_THORIM
Definition ulduar.h:44
@ DATA_THORIM_LEVER
Definition ulduar.h:465
@ DATA_RUNIC_DOOR
Definition ulduar.h:468
@ DATA_RUNE_GIANT
Definition ulduar.h:467
@ DATA_STONE_DOOR
Definition ulduar.h:469
@ DATA_THORIM_HARDMODE
Definition ulduar.h:470
@ DATA_SIF
Definition ulduar.h:464
@ DATA_THORIM_CONTROLLER
Definition ulduar.h:471
@ DATA_RUNIC_COLOSSUS
Definition ulduar.h:466
@ NPC_THORIM_EVENT_BUNNY
Definition ulduar.h:188
@ NPC_GOLEM_LEFT_HAND_BUNNY
Definition ulduar.h:191
@ NPC_IRON_RING_GUARD
Definition ulduar.h:181
@ NPC_DARK_RUNE_WARBRINGER
Definition ulduar.h:184
@ NPC_DARK_RUNE_ACOLYTE_PRE
Definition ulduar.h:178
@ NPC_DARK_RUNE_CHAMPION
Definition ulduar.h:183
@ NPC_MERCENARY_CAPTAIN_A
Definition ulduar.h:174
@ NPC_MERCENARY_SOLDIER_H
Definition ulduar.h:177
@ NPC_JORMUNGAR_BEHEMOTH
Definition ulduar.h:173
@ NPC_DARK_RUNE_ACOLYTE
Definition ulduar.h:187
@ NPC_THUNDER_ORB
Definition ulduar.h:193
@ NPC_IRON_HONOR_GUARD
Definition ulduar.h:182
@ NPC_DARK_RUNE_EVOKER
Definition ulduar.h:185
@ NPC_MERCENARY_CAPTAIN_H
Definition ulduar.h:175
@ NPC_SIF
Definition ulduar.h:192
@ NPC_MERCENARY_SOLDIER_A
Definition ulduar.h:176
@ NPC_GOLEM_RIGHT_HAND_BUNNY
Definition ulduar.h:190
@ NPC_DARK_RUNE_COMMONER
Definition ulduar.h:186
@ NPC_LIGHTNING_ORB
Definition ulduar.h:189
DisplayIds
Definition zulaman.cpp:177