TrinityCore
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"
32#include "ulduar.h"
33#include <G3D/Vector3.h>
34
36{
37 // Thorim
49 SPELL_LIGHTNING_ORB_CHARGED = 62186, // wrong duration, triggered spell should handle lightning release
52 SPELL_LIGHTNING_PILLAR_2 = 62976, // caster high position, target low position
53 SPELL_LIGHTNING_PILLAR_1 = 63238, // caster high position, target low position
58
59 // Credits
62
63 // Lightning Field
66
67 // Sif
69 SPELL_BLINK = 62578,
74
75 // Runic Colossus
76 SPELL_SMASH = 62339,
82
83 // Ancient Rune Giant
86};
87
88#define SPELL_STOMP RAID_MODE<uint32>(62411,62413)
89
91{
95};
96
98{
99 // Thorim
116
117 // Runic Colossus
122
123 // Ancient Rune Giant
127
128 // Arena NPC
133
134 // Sif
141
143{
144 // Thorim
159
160 // Runic Colossus
162
163 // Ancient Rune Giant
165
166 // Sif
169 SAY_SIF_EVENT = 2
171
173{
175 SPELL_SWEEP = 62316,
176
180
182 SPELL_SHOOT = 16496,
183
184 SPELL_RENEW = 62333,
187
189
190 SPELL_LEAP = 61934,
191
195
198
202
205
208
212};
213
215{
216 // Pre Phase Trash
220
221 // Arena Phase Trash
226
227 // Hall Way Trash
230
231 // Shared
234
236{
242};
243
246{
247 // Pre Phase
254
255 // Arena Phase
260
261 // Hall Way
265};
266
268{
276
278{
281};
282
284{
285 { { 2149.68f, -263.477f, 419.679f, 3.120f }, NPC_JORMUNGAR_BEHEMOTH },
286 { { 2131.31f, -271.640f, 419.840f, 2.188f }, NPC_MERCENARY_CAPTAIN_A },
287 { { 2127.24f, -259.182f, 419.974f, 5.917f }, NPC_MERCENARY_SOLDIER_A },
288 { { 2123.32f, -254.770f, 419.840f, 6.170f }, NPC_MERCENARY_SOLDIER_A },
289 { { 2120.10f, -258.990f, 419.840f, 6.250f }, NPC_MERCENARY_SOLDIER_A },
290 { { 2129.09f, -277.142f, 419.756f, 1.222f }, NPC_DARK_RUNE_ACOLYTE_PRE }
291};
292
294{
295 { { 2218.38f, -297.50f, 412.18f, 1.030f }, NPC_IRON_RING_GUARD },
296 { { 2235.07f, -297.98f, 412.18f, 1.613f }, NPC_IRON_RING_GUARD },
297 { { 2235.26f, -338.34f, 412.18f, 1.589f }, NPC_IRON_RING_GUARD },
298 { { 2217.69f, -337.39f, 412.18f, 1.241f }, NPC_IRON_RING_GUARD },
299 { { 2227.58f, -308.30f, 412.18f, 1.591f }, NPC_DARK_RUNE_ACOLYTE },
300 { { 2227.47f, -345.37f, 412.18f, 1.566f }, NPC_DARK_RUNE_ACOLYTE }
301};
302
304{
305 { { 2198.05f, -428.77f, 419.95f, 6.056f }, NPC_IRON_HONOR_GUARD },
306 { { 2220.31f, -436.22f, 412.26f, 1.064f }, NPC_IRON_HONOR_GUARD },
307 { { 2158.88f, -441.73f, 438.25f, 0.127f }, NPC_IRON_HONOR_GUARD },
308 { { 2198.29f, -436.92f, 419.95f, 0.261f }, NPC_DARK_RUNE_ACOLYTE },
309 { { 2230.93f, -434.27f, 412.26f, 1.931f }, NPC_DARK_RUNE_ACOLYTE }
310};
311
312Position const SifSpawnPosition = { 2148.301f, -297.8453f, 438.3308f, 2.687807f };
313
315{
318
320{
323
325{
326 { 2134.889893f, -298.632996f, 438.247467f },
327 { 2134.570068f, -440.317993f, 438.247467f },
328 { 2167.820312f, -440.330261f, 438.247589f },
329 { 2213.394287f, -433.318298f, 412.665863f },
330 { 2227.766113f, -433.275818f, 412.177032f },
331 { 2227.551270f, -263.081085f, 412.176880f },
332 { 2202.208008f, -262.939270f, 412.168976f },
333 { 2182.310059f, -263.233093f, 414.739410f }
334};
335std::size_t const LightningOrbPathSize = std::extent<decltype(LightningOrbPath)>::value;
336
337// used for trash jump calculation
338Position const ArenaCenter = { 2134.77f, -262.307f };
339
340// used for lightning field calculation
341Position const LightningFieldCenter = { 2135.178f, -321.122f };
342
345
347{
350};
351
353{
354 public:
355 HeightPositionCheck(bool ret) : _ret(ret) { }
356
357 bool operator()(Position const* pos) const
358 {
359 return (pos->GetPositionZ() > THORIM_BALCONY_Z_CHECK) == _ret;
360 }
361
362 private:
363 bool _ret;
364
365 static float const THORIM_BALCONY_Z_CHECK;
366};
368
370{
371 public:
373
374 bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override
375 {
377 return true;
378 }
379
380 private:
382};
383
385{
386 public:
387 TrashJumpEvent(Creature* owner) : _owner(owner), _stage(0) { }
388
389 bool Execute(uint64 eventTime, uint32 /*updateTime*/) override
390 {
391 switch (_stage)
392 {
393 case 0:
394 _owner->CastSpell(nullptr, SPELL_LEAP);
395 ++_stage;
396 _owner->m_Events.AddEvent(this, Milliseconds(eventTime) + 2s);
397 return false;
398 case 1:
402 return true;
403 default:
404 break;
405 }
406
407 return true;
408 }
409
410 private:
413};
414
416{
417 public:
419
420 bool Execute(uint64 eventTime, uint32 /*updateTime*/) override
421 {
422 if (InstanceScript* instance = _owner->GetInstanceScript())
423 {
424 if (instance->GetBossState(DATA_THORIM) == IN_PROGRESS)
425 {
427 _owner->m_Events.AddEvent(this, Milliseconds(eventTime) + 1s);
428 return false;
429 }
430 }
431
434 return true;
435 }
436
437 private:
439};
440
442{
443 public:
444 boss_thorim() : CreatureScript("boss_thorim") { }
445
446 struct boss_thorimAI : public BossAI
447 {
448 boss_thorimAI(Creature* creature) : BossAI(creature, DATA_THORIM)
449 {
450 _encounterFinished = false;
451 Initialize();
452 }
453
455 {
456 _killedCount = 0;
457 _waveType = 0;
458 _hardMode = true;
459 _orbSummoned = false;
461 }
462
463 void Reset() override
464 {
466 return;
467
468 SetBoundary(nullptr);
469 _Reset();
470 Initialize();
471
473 me->SetDisableGravity(true);
475 me->SetImmuneToPC(true);
476
478
479 // Respawn Mini Bosses
480 for (uint8 i = DATA_RUNIC_COLOSSUS; i <= DATA_RUNE_GIANT; ++i)
482 miniBoss->Respawn(true);
483
484 // Spawn Pre Phase Adds
485 for (SummonLocation const& s : PreAddLocations)
487
489 lever->SetFlag(GO_FLAG_NOT_SELECTABLE);
490
491 // Remove trigger auras
493 pillar->RemoveAllAuras();
494
496 controller->RemoveAllAuras();
497
499 }
500
501 void EnterEvadeMode(EvadeReason /*why*/) override
502 {
505 }
506
507 void SetGUID(ObjectGuid const& guid, int32 id) override
508 {
509 if (id == DATA_CHARGED_PILLAR)
510 {
511 _activePillarGUID = guid;
512
514 {
515 pillar->CastSpell(pillar, SPELL_LIGHTNING_ORB_CHARGED, true);
516 pillar->CastSpell(nullptr, SPELL_LIGHTNING_PILLAR_2);
518 }
519 }
520 }
521
522 void KilledUnit(Unit* who) override
523 {
524 if (who->GetTypeId() == TYPEID_PLAYER)
525 Talk(SAY_SLAY);
526 }
527
528 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
529 {
530 if (spellInfo->Id == SPELL_TOUCH_OF_DOMINION_TRIGGERED)
531 {
533 {
534 sif->AI()->Talk(SAY_SIF_DESPAWN);
535 sif->DespawnOrUnsummon(6s);
536 _hardMode = false;
537 }
538 }
539 }
540
541 void SpellHitTarget(WorldObject* target, SpellInfo const* spellInfo) override
542 {
543 if (target->GetTypeId() == TYPEID_PLAYER && spellInfo->Id == SPELL_LIGHTNING_RELEASE)
545 }
546
548 {
550 return;
551
552 _encounterFinished = true;
553
554 DoCastAOE(SPELL_CREDIT_KILL, true); // before change faction
555
559 me->AttackStop();
562
564 controller->RemoveAllAuras();
566 pillar->RemoveAllAuras();
567
568 if (_hardMode)
569 {
571 {
572 summons.Despawn(sif);
573 sif->DespawnOrUnsummon(10s);
574 }
575 }
576
577 _JustDied();
578
583
585 }
586
587 void MovementInform(uint32 type, uint32 id) override
588 {
589 if (type != EFFECT_MOTION_TYPE || id != EVENT_JUMP)
590 return;
591
594 }
595
596 void JustEngagedWith(Unit* who) override
597 {
600
602
606
611
613
614 if (Creature* runicColossus = instance->GetCreature(DATA_RUNIC_COLOSSUS))
615 {
616 runicColossus->SetImmuneToPC(false);
617 runicColossus->AI()->DoAction(ACTION_ACTIVATE_ADDS);
618 }
619
621 lever->RemoveFlag(GO_FLAG_NOT_SELECTABLE);
622
623 // Summon Sif
625 }
626
627 void JustSummoned(Creature* summon) override
628 {
629 switch (summon->GetEntry())
630 {
632 {
634 summon->CastSpell(summon, SPELL_LIGHTNING_DESTRUCTION, true);
635
636 std::function<void(Movement::MoveSplineInit&)> initializer = [](Movement::MoveSplineInit& init)
637 {
639 path.reserve(LightningOrbPathSize);
640 std::transform(std::begin(LightningOrbPath), std::end(LightningOrbPath), std::back_inserter(path), [](Position const& pos)
641 {
642 return G3D::Vector3(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ());
643 });
644
645 init.MovebyPath(path);
646 };
647 summon->GetMotionMaster()->LaunchMoveSpline(std::move(initializer), 0, MOTION_PRIORITY_NORMAL, POINT_MOTION_TYPE);
648 break;
649 }
655 summon->m_Events.AddEvent(new TrashJumpEvent(summon), summon->m_Events.CalculateTime(3s));
656 break;
657 case NPC_SIF:
659 break;
660 default:
661 break;
662 }
663
664 BossAI::JustSummoned(summon);
665 }
666
667 void UpdateAI(uint32 diff) override
668 {
669 if (!UpdateVictim())
670 return;
671
672 events.Update(diff);
673
675 return;
676
677 while (uint32 eventId = events.ExecuteEvent())
678 {
679 switch (eventId)
680 {
683 break;
686 sif->AI()->Talk(SAY_SIF_START);
687 break;
690 sif->CastSpell(me, SPELL_TOUCH_OF_DOMINION);
691 break;
694 events.Repeat(15s, 20s);
695 break;
696 case EVENT_CHARGE_ORB:
698 events.Repeat(15s, 20s);
699 break;
701 SummonWave();
702 events.Repeat(_orbSummoned ? 3s : 10s);
703 break;
704 case EVENT_JUMPDOWN:
705 if (_hardMode)
707 sif->AI()->DoAction(ACTION_START_HARD_MODE);
710 me->SetDisableGravity(false);
712 me->GetMotionMaster()->MoveJump(2134.8f, -263.056f, 419.983f, me->GetOrientation(), 30.0f, 20.0f);
716 break;
719 events.Repeat(15s, 20s);
720 break;
722 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
724 events.Repeat(7s, 15s);
725 break;
728 controller->CastSpell(controller, SPELL_ACTIVATE_LIGHTNING_ORB_PERIODIC, true);
729 break;
733 break;
734 case EVENT_BERSERK:
736 {
737 Talk(SAY_WIPE);
740 }
741 else
742 {
745 }
746 break;
748 {
749 std::list<Creature*> triggers;
751 triggers.remove_if([](Creature* bunny)
752 {
753 if (HeightPositionCheck(false)(bunny))
754 return true;
755 return LightningFieldCenter.GetExactDist2dSq(bunny) > 1296.0f;
756 });
757
758 Milliseconds timer = 1s;
759 for (Creature* bunny : triggers)
760 bunny->m_Events.AddEvent(new LightningFieldEvent(bunny), bunny->m_Events.CalculateTime(timer += 100ms));
761
762 triggers.remove_if([](Creature* bunny)
763 {
764 return LightningFieldCenter.GetExactDist2dSq(bunny) < 576.0f;
765 });
766
767 triggers.sort([](Creature* a, Creature* b)
768 {
769 return a->GetPositionX() < b->GetPositionX();
770 });
771
772 for (auto itr = triggers.cbegin(); itr != triggers.cend();)
773 {
774 auto prev = itr++;
775 if (itr != triggers.cend())
776 (*prev)->CastSpell(*itr, SPELL_LIGHTNING_BEAM_CHANNEL);
777 }
778 break;
779 }
780 case EVENT_OUTRO_1:
782 if (_hardMode)
784 break;
785 case EVENT_OUTRO_2:
787 if (_hardMode)
789 sif->SetStandState(UNIT_STAND_STATE_DEAD);
790 break;
791 case EVENT_OUTRO_3:
793 break;
794 default:
795 break;
796 }
797
799 return;
800 }
801 }
802
803 void DoAction(int32 action) override
804 {
805 switch (action)
806 {
807 case ACTION_BERSERK:
809 return;
810
811 if (!_orbSummoned)
812 {
813 _orbSummoned = true;
815 }
816 return;
818 if (++_killedCount >= 6)
819 {
820 // Event starts
821 me->SetImmuneToPC(false);
823 }
824 break;
825 default:
826 break;
827 }
828 }
829
830 void GetTrashSpawnTriggers(std::list<Creature*>& triggerList, uint32 count = 1)
831 {
833 triggerList.remove_if([](Creature* bunny)
834 {
835 if (HeightPositionCheck(false)(bunny))
836 return true;
837 return ArenaCenter.GetExactDist2dSq(bunny) < 3025.0f;
838 });
839
840 if (triggerList.empty())
841 return;
842
843 if (count == 1)
844 {
846 triggerList.clear();
847 triggerList.push_back(bunny);
848 }
849 else
850 Trinity::Containers::RandomResize(triggerList, count);
851 }
852
854 {
855 switch (_waveType)
856 {
857 case 0:
858 {
859 // Dark Rune Commoner
860 std::list<Creature*> triggers;
861 GetTrashSpawnTriggers(triggers, urand(5, 6));
862
863 for (Creature* bunny : triggers)
865
866 ++_waveType;
867 break;
868 }
869 case 1:
870 if (urand(0, 1))
871 {
872 // Dark Rune Champion or Dark Rune Evoker
873 std::list<Creature*> triggers;
874 GetTrashSpawnTriggers(triggers, urand(2, 4));
875
876 for (Creature* bunny : triggers)
878 }
879 else
880 {
881 // Dark Rune Warbringer
882 std::list<Creature*> triggers;
883 GetTrashSpawnTriggers(triggers);
884
885 for (Creature* bunny : triggers)
887 }
888 --_waveType;
889 break;
890 }
891 }
892
893 bool CanStartPhase2(Unit* actor) const
894 {
895 if (!actor || actor->GetTypeId() != TYPEID_PLAYER || !me->IsWithinDistInMap(actor, 10.0f))
896 return false;
897
900 return runicColossus && !runicColossus->IsAlive() && runeGiant && !runeGiant->IsAlive();
901 }
902
903 void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
904 {
905 if (events.IsInPhase(PHASE_1) && CanStartPhase2(attacker))
906 {
912
914 sif->InterruptNonMeleeSpells(false);
915
916 // Hard Mode
917 if (_hardMode)
919 }
920 else if (me->HealthBelowPctDamaged(1, damage))
921 {
922 damage = 0;
924 }
925 }
926
927 private:
935 };
936
937 CreatureAI* GetAI(Creature* creature) const override
938 {
939 return GetUlduarAI<boss_thorimAI>(creature);
940 }
941};
942
944{
946 {
947 _instance = creature->GetInstanceScript();
948 for (uint8 i = 0; i < ThorimTrashCount; ++i)
951
952 ASSERT(_info);
954 me->SetCanMelee(false); // DoSpellAttackIfReady
955 }
956
957 struct AIHelper
958 {
960 static uint32 GetTotalHeal(SpellInfo const* spellInfo, Unit const* caster)
961 {
962 uint32 heal = 0;
963 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
964 {
965 if (spellEffectInfo.IsEffect(SPELL_EFFECT_HEAL))
966 heal += spellEffectInfo.CalcValue(caster);
967
968 if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA) && spellEffectInfo.IsAura(SPELL_AURA_PERIODIC_HEAL))
969 heal += spellInfo->GetMaxTicks() * spellEffectInfo.CalcValue(caster);
970 }
971 return heal;
972 }
973
976 {
977 uint32 heal = 0;
979 for (AuraEffect const* aurEff : auras)
980 heal += aurEff->GetAmount() * aurEff->GetRemainingTicks();
981
982 return heal;
983 }
984
986 {
987 public:
988 MostHPMissingInRange(Unit const* referer, float range, uint32 hp, uint32 exclAura = 0, bool exclSelf = false)
989 : _referer(referer), _range(range), _hp(hp), _exclAura(exclAura), _exclSelf(exclSelf) { }
990
992 {
993 if (_exclSelf && u == _referer)
994 return false;
995
996 if (_exclAura && u->HasAura(_exclAura))
997 return false;
998
999 if ((u->GetHealth() + GetRemainingHealOn(u) + _hp) > u->GetMaxHealth())
1000 return false;
1001
1002 uint32 missingHP = u->GetMaxHealth() - u->GetHealth();
1003 if (u->IsAlive() && _referer->IsFriendlyTo(u) && _referer->IsWithinDistInMap(u, _range) && missingHP > _hp)
1004 {
1005 _hp = missingHP;
1006 return true;
1007 }
1008
1009 return false;
1010 }
1011
1012 private:
1014 float _range;
1018 };
1019
1020 static Unit* GetUnitWithMostMissingHp(SpellInfo const* spellInfo, Unit* caster)
1021 {
1022 // use positive range, it's a healing spell
1023 float const range = spellInfo->GetMaxRange(true);
1024 uint32 const heal = GetTotalHeal(spellInfo, caster);
1025
1026 Unit* target = nullptr;
1027 Trinity::MostHPMissingInRange checker(caster, range, heal);
1028 Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange> searcher(caster, target, checker);
1029 Cell::VisitGridObjects(caster, searcher, 60.0f);
1030
1031 return target;
1032 }
1033
1034 static Unit* GetHealTarget(SpellInfo const* spellInfo, Unit* caster)
1035 {
1036 Unit* healTarget = nullptr;
1037 if (!spellInfo->HasAttribute(SPELL_ATTR1_EXCLUDE_CASTER) && !roll_chance_f(caster->GetHealthPct()) && ((caster->GetHealth() + GetRemainingHealOn(caster) + GetTotalHeal(spellInfo, caster)) <= caster->GetMaxHealth()))
1038 healTarget = caster;
1039 else
1040 healTarget = GetUnitWithMostMissingHp(spellInfo, caster);
1041
1042 return healTarget;
1043 }
1044 };
1045
1046 bool UseAbility(uint32 spellId)
1047 {
1048 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, GetDifficulty());
1049 if (!spellInfo)
1050 return false;
1051
1052 Unit* target = nullptr;
1053 if (AIHelper::GetTotalHeal(spellInfo, me))
1054 target = AIHelper::GetHealTarget(spellInfo, me);
1055 else
1056 target = me->GetVictim();
1057
1058 if (!target)
1059 return false;
1060
1062 {
1063 bool allowMove = true;
1064 if (me->IsInRange(target, spellInfo->GetMinRange(), spellInfo->GetMaxRange()))
1065 allowMove = false;
1066
1067 if (IsCombatMovementAllowed() != allowMove)
1068 {
1069 SetCombatMovement(allowMove);
1070
1071 // need relaunch movement
1073
1074 // give some time to allow reposition, try again in a second
1075 if (allowMove)
1076 return false;
1077 }
1078 }
1079
1080 DoCast(target, spellId);
1081 return true;
1082 }
1083
1084 void UpdateAI(uint32 diff) final override
1085 {
1086 if (!UpdateVictim())
1087 return;
1088
1089 _events.Update(diff);
1090
1092 return;
1093
1094 while (uint32 eventId = _events.ExecuteEvent())
1095 {
1096 ExecuteEvent(eventId);
1097
1099 return;
1100 }
1101
1104 }
1105
1106 virtual void ExecuteEvent(uint32 eventId) = 0;
1107
1108protected:
1111
1112 ThorimTrashInfo const* _info = nullptr;
1113};
1114
1116{
1117 public:
1118 npc_thorim_pre_phase() : CreatureScript("npc_thorim_pre_phase") { }
1119
1121 {
1123 {
1124 me->setActive(true); // prevent grid unload
1125 me->SetFarVisible(true);
1126 }
1127
1128 void Reset() override
1129 {
1130 _events.Reset();
1131 if (_info->PrimaryAbility)
1134 {
1137 else
1139 }
1140 if (_info->ThirdAbility)
1143 SetCombatMovement(false);
1144 }
1145
1146 void JustDied(Unit* /*killer*/) override
1147 {
1148 if (Creature* thorim = _instance->GetCreature(DATA_THORIM))
1149 thorim->AI()->DoAction(ACTION_INCREASE_PREADDS_COUNT);
1150 }
1151
1152 void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1153 {
1154 // nullify spell damage
1155 if (!attacker || !attacker->GetAffectingPlayer())
1156 damage = 0;
1157 }
1158
1159 void ExecuteEvent(uint32 eventId) override
1160 {
1161 switch (eventId)
1162 {
1165 _events.ScheduleEvent(eventId, 15s, 20s);
1166 else
1167 _events.ScheduleEvent(eventId, 1s);
1168 break;
1171 {
1173 _events.ScheduleEvent(eventId, 2s);
1174 else
1175 _events.ScheduleEvent(eventId, 4s, 8s);
1176 }
1177 else
1178 _events.ScheduleEvent(eventId, 1s);
1179 break;
1182 _events.ScheduleEvent(eventId, 6s, 8s);
1183 else
1184 _events.ScheduleEvent(eventId, 1s);
1185 break;
1186 default:
1187 break;
1188 }
1189 }
1190 };
1191
1192 CreatureAI* GetAI(Creature* creature) const override
1193 {
1194 return GetUlduarAI<npc_thorim_pre_phaseAI>(creature);
1195 }
1196};
1197
1199{
1200 public:
1201 npc_thorim_arena_phase() : CreatureScript("npc_thorim_arena_phase") { }
1202
1204 {
1206 {
1207 switch (_info->Type)
1208 {
1209 case DARK_RUNE_CHAMPION:
1211 case DARK_RUNE_COMMONER:
1212 case DARK_RUNE_EVOKER:
1213 _isInArena = true;
1214 break;
1215 case DARK_RUNE_ACOLYTE:
1216 {
1219 break;
1220 }
1221 default:
1222 _isInArena = false;
1223 break;
1224 }
1225 }
1226
1227 bool CanAIAttack(Unit const* who) const override
1228 {
1229 // don't try to attack players in balcony
1230 if (_isInArena && HeightPositionCheck(true)(who))
1231 return false;
1232
1233 return IsInBoundary(who);
1234 }
1235
1236 void Reset() override
1237 {
1238 _events.Reset();
1239 if (_info->PrimaryAbility)
1243 if (_info->ThirdAbility)
1247 }
1248
1249 void JustEngagedWith(Unit* /*who*/) override
1250 {
1253
1254 if (!_isInArena)
1256 colossus->AI()->DoAction(ACTION_ACTIVATE_RUNIC_SMASH);
1257 }
1258
1259 void EnterEvadeMode(EvadeReason why) override
1260 {
1262 return;
1263
1264 // this should only happen if theres no alive player in the arena -> summon orb
1265 if (Creature* thorim = _instance->GetCreature(DATA_THORIM))
1266 thorim->AI()->DoAction(ACTION_BERSERK);
1268 }
1269
1270 void ExecuteEvent(uint32 eventId) override
1271 {
1272 switch (eventId)
1273 {
1276 _events.Repeat(3s, 6s);
1277 else
1278 _events.Repeat(1s);
1279 break;
1282 _events.Repeat(12s, 16s);
1283 else
1284 _events.Repeat(1s);
1285 break;
1288 _events.Repeat(6s, 8s);
1289 else
1290 _events.Repeat(1s);
1291 break;
1293 {
1294 Unit* referer = me;
1295 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [referer](Unit* unit){ return unit->GetTypeId() == TYPEID_PLAYER && unit->IsInRange(referer, 8.0f, 25.0f); }))
1296 DoCast(target, SPELL_CHARGE);
1297 _events.ScheduleEvent(eventId, 12s);
1298 break;
1299 }
1300 default:
1301 break;
1302 }
1303 }
1304
1305 private:
1307 };
1308
1309 CreatureAI* GetAI(Creature* creature) const override
1310 {
1311 return GetUlduarAI<npc_thorim_arena_phaseAI>(creature);
1312 }
1313};
1314
1316{
1318 {
1319 _instance = creature->GetInstanceScript();
1320
1322 }
1323
1324 bool CanAIAttack(Unit const* who) const final override
1325 {
1326 return IsInBoundary(who);
1327 }
1328
1329 void JustSummoned(Creature* summon) final override
1330 {
1331 _summons.Summon(summon);
1332 }
1333
1334 void SummonedCreatureDespawn(Creature* summon) final override
1335 {
1336 _summons.Despawn(summon);
1337 }
1338
1339 void DoAction(int32 action) override
1340 {
1341 if (action == ACTION_ACTIVATE_ADDS)
1342 {
1343 for (ObjectGuid const& guid : _summons)
1344 if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
1345 summon->SetImmuneToPC(false);
1346 }
1347 }
1348
1349protected:
1353};
1354
1356{
1357 public:
1358 npc_runic_colossus() : CreatureScript("npc_runic_colossus") { }
1359
1361 {
1363 {
1364 Initialize();
1365 }
1366
1368 {
1369 _runicActive = false;
1370 }
1371
1372 void Reset() override
1373 {
1374 Initialize();
1375 _events.Reset();
1376
1377 // close the Runic Door
1379
1380 // Spawn trashes
1382 for (SummonLocation const& s : ColossusAddLocations)
1384 }
1385
1386 void MoveInLineOfSight(Unit* /*who*/) override
1387 {
1388 // don't enter combat
1389 }
1390
1391 void DoAction(int32 action) override
1392 {
1394
1395 if (_runicActive)
1396 return;
1397
1398 if (action == ACTION_ACTIVATE_RUNIC_SMASH)
1399 {
1400 _runicActive = true;
1402 }
1403 }
1404
1405 void JustDied(Unit* /*killer*/) override
1406 {
1407 // open the Runic Door
1409
1410 if (Creature* thorim = _instance->GetCreature(DATA_THORIM))
1411 thorim->AI()->Talk(SAY_SPECIAL);
1412
1414 {
1415 giant->SetImmuneToPC(false);
1416 giant->AI()->DoAction(ACTION_ACTIVATE_ADDS);
1417 }
1418 }
1419
1420 void JustEngagedWith(Unit* /*who*/) override
1421 {
1423 _events.Reset();
1427 }
1428
1429 void UpdateAI(uint32 diff) override
1430 {
1431 _events.Update(diff);
1432
1434 return;
1435
1436 while (uint32 eventId = _events.ExecuteEvent())
1437 {
1438 switch (eventId)
1439 {
1443 _events.Repeat(35s, 45s);
1444 break;
1445 case EVENT_SMASH:
1447 _events.Repeat(15s, 18s);
1448 break;
1449 case EVENT_RUNIC_CHARGE:
1450 {
1451 Unit* referer = me;
1452 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, [referer](Unit* unit){ return unit->GetTypeId() == TYPEID_PLAYER && unit->IsInRange(referer, 8.0f, 40.0f); }))
1453 DoCast(target, SPELL_RUNIC_CHARGE);
1454 _events.Repeat(20s);
1455 break;
1456 }
1457 case EVENT_RUNIC_SMASH:
1459 _events.Repeat(6s);
1460 break;
1461 default:
1462 break;
1463 }
1464
1466 return;
1467 }
1468
1469 if (!UpdateVictim())
1470 return;
1471 }
1472
1473 private:
1475 };
1476
1477 CreatureAI* GetAI(Creature* creature) const override
1478 {
1479 return GetUlduarAI<npc_runic_colossusAI>(creature);
1480 }
1481};
1482
1484{
1485 public:
1486 npc_ancient_rune_giant() : CreatureScript("npc_ancient_rune_giant") { }
1487
1489 {
1491
1492 void Reset() override
1493 {
1494 _events.Reset();
1495
1496 // close the Stone Door
1498
1499 // Spawn trashes
1501 for (SummonLocation const& s : GiantAddLocations)
1503 }
1504
1505 void JustEngagedWith(Unit* /*who*/) override
1506 {
1508 _events.Reset();
1512 }
1513
1514 void JustDied(Unit* /*killer*/) override
1515 {
1516 // opem the Stone Door
1518 }
1519
1520 void UpdateAI(uint32 diff) override
1521 {
1522 if (!UpdateVictim())
1523 return;
1524
1525 _events.Update(diff);
1526
1528 return;
1529
1530 while (uint32 eventId = _events.ExecuteEvent())
1531 {
1532 switch (eventId)
1533 {
1537 break;
1538 case EVENT_STOMP:
1540 _events.Repeat(10s, 12s);
1541 break;
1543 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 60.0f, true))
1545 _events.Repeat(10s, 12s);
1546 break;
1547 default:
1548 break;
1549 }
1550
1552 return;
1553 }
1554 }
1555 };
1556
1557 CreatureAI* GetAI(Creature* creature) const override
1558 {
1559 return GetUlduarAI<npc_ancient_rune_giantAI>(creature);
1560 }
1561};
1562
1564{
1565 public:
1566 npc_sif() : CreatureScript("npc_sif") { }
1567
1568 struct npc_sifAI : public ScriptedAI
1569 {
1570 npc_sifAI(Creature* creature) : ScriptedAI(creature)
1571 {
1572 SetCombatMovement(false);
1573 _instance = creature->GetInstanceScript();
1574 }
1575
1576 void Reset() override
1577 {
1578 _events.Reset();
1579 }
1580
1581 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
1582 {
1583 if (spellInfo->Id == SPELL_STORMHAMMER_SIF)
1584 {
1587 me->AttackStop();
1588 }
1589 }
1590
1591 void DoAction(int32 action) override
1592 {
1593 if (action == ACTION_START_HARD_MODE)
1594 {
1598 _events.Reset();
1603 }
1604 }
1605
1606 void UpdateAI(uint32 diff) override
1607 {
1608 if (!UpdateVictim())
1609 return;
1610
1611 _events.Update(diff);
1612
1614 return;
1615
1616 while (uint32 eventId = _events.ExecuteEvent())
1617 {
1618 switch (eventId)
1619 {
1620 case EVENT_BLINK:
1621 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
1622 DoCast(target, SPELL_BLINK);
1624 _events.Repeat(20s, 25s);
1625 return;
1626 case EVENT_FROST_NOVA:
1628 return;
1629 case EVENT_FROSTBOLT:
1630 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, true))
1631 DoCast(target, SPELL_FROSTBOLT);
1632 _events.Repeat(2s);
1633 return;
1636 _events.Repeat(15s, 20s);
1637 return;
1638 case EVENT_BLIZZARD:
1640 _events.Repeat(35s, 45s);
1641 return;
1642 default:
1643 break;
1644 }
1645
1647 return;
1648 }
1649
1650 // no melee attack
1651 }
1652
1653 private:
1656 };
1657
1658 CreatureAI* GetAI(Creature* creature) const override
1659 {
1660 return GetUlduarAI<npc_sifAI>(creature);
1661 }
1662};
1663
1664// 62576 - Blizzard
1665// 62602 - Blizzard
1667{
1668 public:
1669 spell_thorim_blizzard_effect() : SpellScriptLoader("spell_thorim_blizzard_effect") { }
1670
1672 {
1673 bool CheckAreaTarget(Unit* target)
1674 {
1676 if (target != GetOwner())
1677 {
1678 // check if not stacking aura already on target
1679 // this one prevents overriding auras periodically by 2 near area aura owners
1680 Unit::AuraApplicationMap const& auraMap = target->GetAppliedAuras();
1681 for (Unit::AuraApplicationMap::const_iterator iter = auraMap.begin(); iter != auraMap.end(); ++iter)
1682 {
1683 Aura const* aura = iter->second->GetBase();
1684 if (GetId() == aura->GetId() && GetOwner() != aura->GetOwner() )
1685 return false;
1686 }
1687 }
1688
1689 return true;
1690 }
1691
1692 void Register() override
1693 {
1695 }
1696 };
1697
1698 AuraScript* GetAuraScript() const override
1699 {
1701 }
1702};
1703
1704// 62580, 62604 - Frostbolt Volley
1706{
1707 public:
1708 spell_thorim_frostbolt_volley() : SpellScriptLoader("spell_thorim_frostbolt_volley") { }
1709
1711 {
1712 void FilterTargets(std::list<WorldObject*>& targets)
1713 {
1714 targets.remove_if([](WorldObject* object) -> bool
1715 {
1716 if (object->GetTypeId() == TYPEID_PLAYER)
1717 return false;
1718
1719 if (Creature* creature = object->ToCreature())
1720 return !creature->IsPet();
1721
1722 return true;
1723 });
1724 }
1725
1726 void Register() override
1727 {
1729 }
1730 };
1731
1732 SpellScript* GetSpellScript() const override
1733 {
1735 }
1736};
1737
1738// 62016 - Charge Orb
1740{
1741 public:
1742 spell_thorim_charge_orb() : SpellScriptLoader("spell_thorim_charge_orb") { }
1743
1745 {
1746 bool Validate(SpellInfo const* /*spellInfo*/) override
1747 {
1749 }
1750
1751 void FilterTargets(std::list<WorldObject*>& targets)
1752 {
1753 targets.remove_if(HeightPositionCheck(false));
1754
1755 if (targets.empty())
1756 return;
1757
1759 targets.clear();
1760 targets.push_back(target);
1761 }
1762
1764 {
1765 if (Unit* target = GetHitUnit())
1766 target->CastSpell(nullptr, SPELL_LIGHTNING_PILLAR_1, true);
1767 }
1768
1769 void Register() override
1770 {
1773 }
1774 };
1775
1776 SpellScript* GetSpellScript() const override
1777 {
1779 }
1780};
1781
1782// 62466 - Lightning Charge
1784{
1785 public:
1786 spell_thorim_lightning_charge() : SpellScriptLoader("spell_thorim_lightning_charge") { }
1787
1789 {
1790 bool Validate(SpellInfo const* /*spellInfo*/) override
1791 {
1793 }
1794
1796 {
1798 if (Creature* creature = GetCaster()->ToCreature())
1799 creature->SetSpellFocus(GetSpell(), GetExplTargetWorldObject());
1800 }
1801
1803 {
1805 }
1806
1807 void Register() override
1808 {
1811 }
1812 };
1813
1814 SpellScript* GetSpellScript() const override
1815 {
1817 }
1818};
1819
1820// 61934 - Leap
1822{
1823 public:
1824 spell_thorim_arena_leap() : SpellScriptLoader("spell_thorim_arena_leap") { }
1825
1827 {
1828 bool Load() override
1829 {
1830 return GetCaster()->GetTypeId() == TYPEID_UNIT;
1831 }
1832
1833 void HandleScript(SpellEffIndex /*effIndex*/)
1834 {
1835 if (Position const* pos = GetHitDest())
1837 }
1838
1839 void Register() override
1840 {
1842 }
1843 };
1844
1845 SpellScript* GetSpellScript() const override
1846 {
1848 }
1849};
1850
1852{
1853 bool operator()(Position const* who) const
1854 {
1856 }
1857};
1858
1859// 62042 - Stormhammer
1861{
1862 public:
1863 spell_thorim_stormhammer() : SpellScriptLoader("spell_thorim_stormhammer") { }
1864
1866 {
1867 bool Validate(SpellInfo const* /*spellInfo*/) override
1868 {
1870 }
1871
1872 void FilterTargets(std::list<WorldObject*>& targets)
1873 {
1874 targets.remove_if([](WorldObject* target) -> bool { return HeightPositionCheck(true)(target) || OutOfArenaCheck()(target); });
1875
1876 if (targets.empty())
1877 {
1879 return;
1880 }
1881
1883 targets.clear();
1884 targets.push_back(target);
1885 }
1886
1887 void HandleScript(SpellEffIndex /*effIndex*/)
1888 {
1889 if (Unit* target = GetHitUnit())
1890 {
1891 target->CastSpell(target, SPELL_DEAFENING_THUNDER, true);
1892 target->CastSpell(GetCaster(), SPELL_STORMHAMMER_BOOMERANG, true);
1893 }
1894 }
1895
1897 {
1898 GetCaster()->SetVirtualItem(0, 0);
1899 }
1900
1901 void Register() override
1902 {
1906 }
1907 };
1908
1909 SpellScript* GetSpellScript() const override
1910 {
1912 }
1913};
1914
1915// 64767 - Stormhammer
1917{
1918 public:
1919 spell_thorim_stormhammer_sif() : SpellScriptLoader("spell_thorim_stormhammer_sif") { }
1920
1922 {
1923 bool Validate(SpellInfo const* /*spellInfo*/) override
1924 {
1926 }
1927
1928 void HandleScript(SpellEffIndex /*effIndex*/)
1929 {
1930 if (Unit* target = GetHitUnit())
1931 {
1932 target->CastSpell(GetCaster(), SPELL_STORMHAMMER_BOOMERANG, true);
1933 target->CastSpell(target, SPELL_SIF_TRANSFORM, true);
1934 }
1935 }
1936
1938 {
1939 GetCaster()->SetVirtualItem(0, 0);
1940 }
1941
1942 void Register() override
1943 {
1946 }
1947 };
1948
1949 SpellScript* GetSpellScript() const override
1950 {
1952 }
1953};
1954
1955// 64909 - Stormhammer
1957{
1958 public:
1959 spell_thorim_stormhammer_boomerang() : SpellScriptLoader("spell_thorim_stormhammer_boomerang") { }
1960
1962 {
1963 void RecoverHammer(SpellEffIndex /*effIndex*/)
1964 {
1965 if (Unit* target = GetHitUnit())
1966 target->SetVirtualItem(0, THORIM_WEAPON_DISPLAY_ID);
1967 }
1968
1969 void Register() override
1970 {
1972 }
1973 };
1974
1975 SpellScript* GetSpellScript() const override
1976 {
1978 }
1979};
1980
1981// 62057, 62058 - Runic Smash
1983{
1984 public:
1985 spell_thorim_runic_smash() : SpellScriptLoader("spell_thorim_runic_smash") { }
1986
1988 {
1989 bool Validate(SpellInfo const* /*spellInfo*/) override
1990 {
1992 }
1993
1995 {
1996 PreventHitDefaultEffect(effIndex);
1997
1998 std::vector<Creature*> triggers;
2000 for (Creature* trigger : triggers)
2001 {
2002 Milliseconds time = Milliseconds(uint64(GetCaster()->GetExactDist(trigger) * 30.f));
2003 trigger->m_Events.AddEvent(new RunicSmashExplosionEvent(trigger), trigger->m_Events.CalculateTime(time));
2004 };
2005 }
2006
2007 void Register() override
2008 {
2010 }
2011 };
2012
2013 SpellScript* GetSpellScript() const override
2014 {
2016 }
2017};
2018
2020{
2021 public:
2022 UpperOrbCheck() : _check(true) { }
2023
2024 bool operator() (Creature* target) const
2025 {
2026 return target->GetEntry() == NPC_THUNDER_ORB && _check(target);
2027 }
2028
2029 private:
2031};
2032
2033// 62184 - Activate Lightning Orb Periodic
2035{
2036 public:
2037 spell_thorim_activate_lightning_orb_periodic() : SpellScriptLoader("spell_thorim_activate_lightning_orb_periodic") { }
2038
2040 {
2042
2043 void PeriodicTick(AuraEffect const* /*aurEff*/)
2044 {
2046
2047 Unit* caster = GetCaster();
2048 std::vector<Creature*> triggers;
2049
2050 UpperOrbCheck check;
2051 Trinity::CreatureListSearcher<UpperOrbCheck> searcher(caster, triggers, check);
2052 Cell::VisitGridObjects(caster, searcher, 100.f);
2053
2054 if (!triggers.empty())
2055 {
2057 if (Creature* thorim = instance->GetCreature(DATA_THORIM))
2058 thorim->AI()->SetGUID(target->GetGUID(), DATA_CHARGED_PILLAR);
2059 }
2060 }
2061
2062 bool Load() override
2063 {
2064 if (Unit* caster = GetCaster())
2065 instance = caster->GetInstanceScript();
2066
2067 return instance != nullptr;
2068 }
2069
2070 void Register() override
2071 {
2073 }
2074 };
2075
2076 AuraScript* GetAuraScript() const override
2077 {
2079 }
2080};
2081
2083{
2084 public:
2085 condition_thorim_arena_leap() : ConditionScript("condition_thorim_arena_leap"), _check(false) { }
2086
2087 bool OnConditionCheck(Condition const* condition, ConditionSourceInfo& sourceInfo) override
2088 {
2089 WorldObject const* target = sourceInfo.mConditionTargets[condition->ConditionTarget];
2090 InstanceScript* instance = target->GetInstanceScript();
2091
2092 if (!instance)
2093 return false;
2094
2095 return _check(target);
2096 }
2097
2098 private:
2100};
2101
2103{
2104 new boss_thorim();
2107 new npc_runic_colossus();
2109 new npc_sif();
2121}
Actions
First const & RAND(First const &first, Second const &second, Rest const &... rest)
std::vector< AreaBoundary const * > CreatureBoundary
Definition: CreatureAI.h:37
uint8_t uint8
Definition: Define.h:144
int32_t int32
Definition: Define.h:138
uint64_t uint64
Definition: Define.h:141
uint32_t uint32
Definition: Define.h:142
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:29
#define ASSERT
Definition: Errors.h:68
@ IN_PROGRESS
@ MOTION_PRIORITY_NORMAL
@ POINT_MOTION_TYPE
@ EFFECT_MOTION_TYPE
@ TEMPSUMMON_CORPSE_TIMED_DESPAWN
Definition: ObjectDefines.h:68
@ TYPEID_UNIT
Definition: ObjectGuid.h:40
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
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
if(posix_memalign(&__mallocedMemory, __align, __size)) return NULL
SpellEffIndex
Definition: SharedDefines.h:29
@ EFFECT_0
Definition: SharedDefines.h:30
@ EFFECT_2
Definition: SharedDefines.h:32
@ TARGET_UNIT_SRC_AREA_ENTRY
@ TARGET_UNIT_SRC_AREA_ENEMY
@ EVENT_JUMP
@ SPELL_ATTR1_EXCLUDE_CASTER
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ SPELL_EFFECT_HEAL
@ SPELL_EFFECT_TRIGGER_SPELL
@ SPELL_EFFECT_JUMP_DEST
@ SPELL_EFFECT_APPLY_AURA
@ SPELL_FAILED_NO_VALID_TARGETS
@ GO_FLAG_NOT_SELECTABLE
@ FACTION_FRIENDLY
#define EFFECT_ALL
Definition: SharedDefines.h:72
@ SPELL_AURA_PERIODIC_HEAL
@ SPELL_AURA_PERIODIC_TRIGGER_SPELL
#define sSpellMgr
Definition: SpellMgr.h:849
#define SpellEffectFn(F, I, N)
Definition: SpellScript.h:842
#define SpellObjectAreaTargetSelectFn(F, I, N)
Definition: SpellScript.h:864
#define AuraEffectPeriodicFn(F, I, N)
Definition: SpellScript.h:2046
#define SpellCastFn(F)
Definition: SpellScript.h:825
#define SpellHitFn(F)
Definition: SpellScript.h:854
#define AuraCheckAreaTargetFn(F)
Definition: SpellScript.h:2008
EvadeReason
Definition: UnitAICommon.h:30
@ REACT_PASSIVE
Definition: UnitDefines.h:506
@ REACT_AGGRESSIVE
Definition: UnitDefines.h:508
@ UNIT_STAND_STATE_DEAD
Definition: UnitDefines.h:49
DamageEffectType
Definition: UnitDefines.h:131
@ UNIT_FLAG_RENAME
Definition: UnitDefines.h:148
@ CURRENT_GENERIC_SPELL
Definition: Unit.h:590
@ UNIT_STATE_ROOT
Definition: Unit.h:265
@ UNIT_STATE_CASTING
Definition: Unit.h:270
uint32 const Entry[5]
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_BLINK
Definition: boss_thorim.cpp:69
@ SPELL_RUNE_DETONATION
Definition: boss_thorim.cpp:85
@ SPELL_TOUCH_OF_DOMINION
Definition: boss_thorim.cpp:46
@ SPELL_LIGHTNING_BEAM_CHANNEL
Definition: boss_thorim.cpp:65
@ SPELL_SHEATH_OF_LIGHTNING
Definition: boss_thorim.cpp:38
@ SPELL_LIGHTNING_PILLAR_2
Definition: boss_thorim.cpp:52
@ SPELL_LIGHTNING_FIELD
Definition: boss_thorim.cpp:64
@ SPELL_FROSTBOLT
Definition: boss_thorim.cpp:71
@ SPELL_BERSERK_PHASE_2
Definition: boss_thorim.cpp:56
@ SPELL_TOUCH_OF_DOMINION_TRIGGERED
Definition: boss_thorim.cpp:47
@ SPELL_RUNIC_SMASH_LEFT
Definition: boss_thorim.cpp:81
@ SPELL_UNBALANCING_STRIKE
Definition: boss_thorim.cpp:54
@ SPELL_DEAFENING_THUNDER
Definition: boss_thorim.cpp:42
@ SPELL_BERSERK_PHASE_1
Definition: boss_thorim.cpp:55
@ SPELL_STORMHAMMER_SIF
Definition: boss_thorim.cpp:40
@ SPELL_RUNIC_FORTIFICATION
Definition: boss_thorim.cpp:84
@ SPELL_STORMHAMMER
Definition: boss_thorim.cpp:39
@ SPELL_ACTIVATE_LIGHTNING_ORB_PERIODIC
Definition: boss_thorim.cpp:57
@ SPELL_SUMMON_LIGHTNING_ORB
Definition: boss_thorim.cpp:44
@ SPELL_CHARGE_ORB
Definition: boss_thorim.cpp:43
@ SPELL_LIGHTNING_ORB_CHARGED
Definition: boss_thorim.cpp:49
@ SPELL_BLIZZARD
Definition: boss_thorim.cpp:68
@ SPELL_SMASH
Definition: boss_thorim.cpp:76
@ SPELL_FROSTBOLT_VOLLEY
Definition: boss_thorim.cpp:70
@ SPELL_LIGHTNING_PILLAR_1
Definition: boss_thorim.cpp:53
@ SPELL_LIGHTNING_CHARGE
Definition: boss_thorim.cpp:50
@ SPELL_SIF_TRANSFORM
Definition: boss_thorim.cpp:73
@ SPELL_STORMHAMMER_BOOMERANG
Definition: boss_thorim.cpp:41
@ SPELL_CHAIN_LIGHTNING
Definition: boss_thorim.cpp:48
@ SPELL_FROSTNOVA
Definition: boss_thorim.cpp:72
@ SPELL_LIGHTNING_DESTRUCTION
Definition: boss_thorim.cpp:45
@ SPELL_LIGHTNING_RELEASE
Definition: boss_thorim.cpp:51
@ SPELL_RUNIC_CHARGE
Definition: boss_thorim.cpp:78
@ SPELL_RUNIC_SMASH_RIGHT
Definition: boss_thorim.cpp:80
@ SPELL_CREDIT_KILL
Definition: boss_thorim.cpp:61
@ SPELL_RUNIC_SMASH
Definition: boss_thorim.cpp:79
@ SPELL_RUNIC_BARRIER
Definition: boss_thorim.cpp:77
@ SPELL_CREDIT_SIFFED
Definition: boss_thorim.cpp:60
@ PHASE_NULL
Definition: boss_thorim.cpp:92
@ PHASE_2
Definition: boss_thorim.cpp:94
@ PHASE_1
Definition: boss_thorim.cpp:93
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_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
#define SPELL_STOMP
Definition: boss_thorim.cpp:88
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
DisplayIds
@ THORIM_WEAPON_DISPLAY_ID
SummonLocation const GiantAddLocations[]
Position const SifSpawnPosition
@ 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< EffectPeriodicHandler > OnEffectPeriodic
Definition: SpellScript.h:2045
WorldObject * GetOwner() const
Unit * GetCaster() const
HookList< CheckAreaTargetHandler > DoCheckAreaTarget
Definition: SpellScript.h:2007
uint32 GetId() const
WorldObject * GetOwner() const
Definition: SpellAuras.h:146
uint32 GetId() const
Definition: SpellAuras.h:135
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
void _JustDied()
void DoZoneInCombat()
Definition: CreatureAI.h:161
static bool IsInBounds(CreatureBoundary const &boundary, Position const *who)
Definition: CreatureAI.cpp:437
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
Definition: CreatureAI.cpp:219
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool IsInBoundary(Position const *who=nullptr) const
Definition: CreatureAI.cpp:426
bool UpdateVictim()
Definition: CreatureAI.cpp:245
void SetBoundary(CreatureBoundary const *boundary, bool negativeBoundaries=false)
Definition: CreatureAI.cpp:446
Creature *const me
Definition: CreatureAI.h:61
void SetHomePosition(float x, float y, float z, float o)
Definition: Creature.h:371
void SetCanMelee(bool canMelee, bool fleeFromMelee=false)
Definition: Creature.cpp:2822
void SetImmuneToPC(bool apply) override
Definition: Creature.h:170
void SetReactState(ReactStates st)
Definition: Creature.h:160
CreatureAI * AI() const
Definition: Creature.h:214
uint32 ExecuteEvent()
Definition: EventMap.cpp:73
void Update(uint32 time)
Definition: EventMap.h:56
void Repeat(Milliseconds time)
Definition: EventMap.cpp:63
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition: EventMap.cpp:36
bool IsInPhase(uint8 phase) const
Definition: EventMap.h:217
void SetPhase(uint8 phase)
Definition: EventMap.cpp:28
void RescheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition: EventMap.cpp:52
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, JumpArrivalCastArgs const *arrivalCast=nullptr, Movement::SpellEffectExtraData const *spellEffectExtraData=nullptr)
void Clear()
Definition: ObjectGuid.h:286
static Creature * ToCreature(Object *o)
Definition: Object.h:219
TypeID GetTypeId() const
Definition: Object.h:173
uint32 GetEntry() const
Definition: Object.h:161
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
RunicSmashExplosionEvent(Creature *owner)
bool Execute(uint64, uint32) override
uint32 GetMaxTicks() const
Definition: SpellInfo.cpp:3823
float GetMaxRange(bool positive=false, WorldObject *caster=nullptr, Spell *spell=nullptr) const
Definition: SpellInfo.cpp:3768
uint32 const Id
Definition: SpellInfo.h:325
float GetMinRange(bool positive=false) const
Definition: SpellInfo.cpp:3761
bool HasAttribute(SpellAttr0 attribute) const
Definition: SpellInfo.h:449
std::vector< SpellEffectInfo > const & GetEffects() const
Definition: SpellInfo.h:576
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Definition: SpellScript.h:162
HookList< CastHandler > AfterCast
Definition: SpellScript.h:824
WorldLocation * GetHitDest() const
Unit * GetCaster() const
HookList< HitHandler > AfterHit
Definition: SpellScript.h:852
void PreventHitDefaultEffect(SpellEffIndex effIndex)
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
Definition: SpellScript.h:840
HookList< CastHandler > BeforeCast
Definition: SpellScript.h:820
Spell * GetSpell() const
Definition: SpellScript.h:987
void FinishCast(SpellCastResult result, int32 *param1=nullptr, int32 *param2=nullptr)
WorldObject * GetExplTargetWorldObject() const
HookList< EffectHandler > OnEffectLaunch
Definition: SpellScript.h:837
SpellInfo const * GetSpellInfo() const
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
Definition: SpellScript.h:863
void Despawn(Creature const *summon)
void Summon(Creature const *summon)
bool Execute(uint64 eventTime, uint32) override
TrashJumpEvent(Creature *owner)
Creature * _owner
bool DoSpellAttackIfReady(uint32 spellId)
Definition: UnitAI.cpp:61
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition: UnitAI.cpp:79
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:161
SpellCastResult DoCast(uint32 spellId)
Definition: UnitAI.cpp:89
Definition: Unit.h:627
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition: Unit.h:1321
float GetHealthPct() const
Definition: Unit.h:784
void SetVirtualItem(uint32 slot, uint32 itemId, uint16 appearanceModId=0, uint16 itemVisual=0)
Definition: Unit.cpp:13604
void SetControlled(bool apply, UnitState state)
Definition: Unit.cpp:10911
std::multimap< uint32, AuraApplication * > AuraApplicationMap
Definition: Unit.h:637
void SetFaction(uint32 faction) override
Definition: Unit.h:859
std::forward_list< AuraEffect * > AuraEffectList
Definition: Unit.h:644
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition: Unit.cpp:3089
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
bool IsAlive() const
Definition: Unit.h:1164
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition: Unit.cpp:12725
uint64 GetMaxHealth() const
Definition: Unit.h:777
uint64 GetHealth() const
Definition: Unit.h:776
Unit * GetVictim() const
Definition: Unit.h:715
bool HasUnitState(const uint32 f) const
Definition: Unit.h:732
void RemoveAllAttackers()
Definition: Unit.cpp:5881
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4664
void RemoveAllAuras()
Definition: Unit.cpp:4242
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const
Definition: Unit.h:781
void SetUnitFlag(UnitFlags flags)
Definition: Unit.h:833
AuraApplicationMap & GetAppliedAuras()
Definition: Unit.h:1274
bool AttackStop()
Definition: Unit.cpp:5781
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
void InterruptSpell(CurrentSpellTypes spellType, bool withDelayed=true, bool withInstant=true)
Definition: Unit.cpp:3017
HeightPositionCheck const _check
bool operator()(Creature *target) const
InstanceScript * GetInstanceScript() const
Definition: Object.cpp:1042
void GetCreatureListWithEntryInGrid(Container &creatureContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition: Object.cpp:3312
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
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:2025
void setActive(bool isActiveObject)
Definition: Object.cpp:922
void SetFarVisible(bool on)
Definition: Object.cpp:973
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition: Object.cpp:1147
bool IsInRange(WorldObject const *obj, float minRange, float maxRange, bool is3D=true) const
Definition: Object.cpp:1238
EventProcessor m_Events
Definition: Object.h:777
bool IsFriendlyTo(WorldObject const *target) const
Definition: Object.cpp:2865
Player * GetAffectingPlayer() const
Definition: Object.cpp:2261
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
SpellScript * GetSpellScript() const override
AuraScript * GetAuraScript() const override
void FilterTargets(std::list< WorldObject * > &targets)
SpellScript * GetSpellScript() const override
SpellScript * GetSpellScript() const override
SpellScript * GetSpellScript() const override
SpellScript * GetSpellScript() const override
void FilterTargets(std::list< WorldObject * > &targets)
SpellScript * GetSpellScript() const override
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:109
void RandomResize(C &container, std::size_t requestedSize)
Definition: Containers.h:67
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition: CellImpl.h:179
WorldObject const * mConditionTargets[MAX_CONDITION_TARGETS]
Definition: ConditionMgr.h:220
uint8 ConditionTarget
Definition: ConditionMgr.h:260
bool operator()(Position const *who) const
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77
constexpr float GetExactDist2dSq(const float x, const float y) const
Definition: Position.h:97
constexpr float GetOrientation() const
Definition: Position.h:79
constexpr float GetPositionZ() const
Definition: Position.h:78
void AttackStart(Unit *) override
== Triggered Actions Requested ==================
void SetCombatMovement(bool allowMovement)
bool IsCombatMovementAllowed() const
Difficulty GetDifficulty() const
void ResetThreatList(Unit *who=nullptr)
uint32 SecondaryAbility
void DamageTaken(Unit *attacker, uint32 &damage, DamageEffectType, SpellInfo const *) override
void UpdateAI(uint32 diff) override
boss_thorimAI(Creature *creature)
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 UpdateAI(uint32 diff) 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
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:45
@ DATA_THORIM_LEVER
Definition: ulduar.h:453
@ DATA_RUNIC_DOOR
Definition: ulduar.h:456
@ DATA_RUNE_GIANT
Definition: ulduar.h:455
@ DATA_STONE_DOOR
Definition: ulduar.h:457
@ DATA_SIF
Definition: ulduar.h:452
@ DATA_THORIM_CONTROLLER
Definition: ulduar.h:459
@ DATA_RUNIC_COLOSSUS
Definition: ulduar.h:454
@ NPC_THORIM_EVENT_BUNNY
Definition: ulduar.h:189
@ NPC_GOLEM_LEFT_HAND_BUNNY
Definition: ulduar.h:192
@ NPC_IRON_RING_GUARD
Definition: ulduar.h:182
@ NPC_DARK_RUNE_WARBRINGER
Definition: ulduar.h:185
@ NPC_DARK_RUNE_ACOLYTE_PRE
Definition: ulduar.h:179
@ NPC_DARK_RUNE_CHAMPION
Definition: ulduar.h:184
@ NPC_MERCENARY_CAPTAIN_A
Definition: ulduar.h:175
@ NPC_MERCENARY_SOLDIER_H
Definition: ulduar.h:178
@ NPC_JORMUNGAR_BEHEMOTH
Definition: ulduar.h:174
@ NPC_DARK_RUNE_ACOLYTE
Definition: ulduar.h:188
@ NPC_THUNDER_ORB
Definition: ulduar.h:194
@ NPC_IRON_HONOR_GUARD
Definition: ulduar.h:183
@ NPC_DARK_RUNE_EVOKER
Definition: ulduar.h:186
@ NPC_MERCENARY_CAPTAIN_H
Definition: ulduar.h:176
@ NPC_SIF
Definition: ulduar.h:193
@ NPC_MERCENARY_SOLDIER_A
Definition: ulduar.h:177
@ NPC_GOLEM_RIGHT_HAND_BUNNY
Definition: ulduar.h:191
@ NPC_DARK_RUNE_COMMONER
Definition: ulduar.h:187
@ NPC_LIGHTNING_ORB
Definition: ulduar.h:190