TrinityCore
Loading...
Searching...
No Matches
boss_hodir.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/*
19 * Spell 64540 is used in sniffs but the exact purpose and how to use it is unknown
20 * Combat timers requires to be revisited
21 * What does spell 64547?
22 * What does periodic of spells 61969 & 61990?
23 * Priest's Dispel Magic should work on both players and creatures
24 */
25
26#include "ScriptMgr.h"
27#include "Containers.h"
28#include "GameObject.h"
29#include "GridNotifiers.h"
30#include "InstanceScript.h"
31#include "Map.h"
32#include "ScriptedCreature.h"
33#include "SpellAuraEffects.h"
34#include "SpellScript.h"
35#include "SpellInfo.h"
36#include "TemporarySummon.h"
37#include "ulduar.h"
38#include <span>
39
51
53{
54 // Hodir - Initial
58
59 // Hodir - Combat
60 SPELL_FREEZE = 62469,
64
65 // Hodir - Combat - Misc
67
68 // Hodir - Outro
72
73 // Generic
77
78 // Invisible Stalker (Float, Uninteractible, LargeAOI)
80
81 // Snowpacked Icicle Target
84
85 // Icicle
86 // Snowpacked Icicle
90
91 // Priests
92 SPELL_SMITE = 61923,
95
96 // Shamans
99
100 // Druids
102 SPELL_WRATH = 62793,
104
105 // Mages
109
110 // Toasty Fire
112
113 // Flash Freeze (Init)
116
117 // Flash Freeze (Combat)
119
120 // Scripts
124
126
129
132
133 // Misc
135 SPELL_STORM_POWER_H = 65134
137
155
165
167{
168 GO_TOASTY_FIRE = 194300
170
179
181{
182 { 1983.75f, -243.36f, 432.767f, 1.57f }, // Field Medic Penny && Battle-Priest Eliza
183 { 1999.90f, -230.49f, 432.767f, 1.57f }, // Eivi Nightfeather && Tor Greycloud
184 { 2010.06f, -243.45f, 432.767f, 1.57f }, // Elementalist Mahfuun && Spiritwalker Tara
185 { 2021.12f, -236.65f, 432.767f, 1.57f }, // Missy Flamecuffs && Amira Blazeweaver
186 { 2028.10f, -244.66f, 432.767f, 1.57f }, // Field Medic Jessi && Battle-Priest Gina
187 { 2014.18f, -232.80f, 432.767f, 1.57f }, // Ellie Nightfeather && Kar Greycloud
188 { 1992.90f, -237.54f, 432.767f, 1.57f }, // Elementalist Avuun && Spiritwalker Yona
189 { 1976.60f, -233.53f, 432.767f, 1.57f } // Sissy Flamecuffs && Veesha Blazeweaver
190};
191
203
215
216// 32845 - Hodir
217struct boss_hodir : public BossAI
218{
219 boss_hodir(Creature* creature) : BossAI(creature, DATA_HODIR)
220 {
221 _isDefeated = false;
222 }
223
224 void JustAppeared() override
225 {
226 int32 count = RAID_MODE(4, 8);
227 std::span<uint32 const> entries = instance->instance->GetTeamIdInInstance() == TEAM_HORDE
230 for (int32 i = 0; i < count; ++i)
232 }
233
234 void JustEngagedWith(Unit* who) override
235 {
237
239
243
248
249 std::vector<Creature*> coolestFriends;
250 GetCreatureListWithOptionsInGrid(coolestFriends, me, 100.0f, { .StringId = "HodirCoolestFriend" });
251 for (Creature* coolestFriend : coolestFriends)
252 coolestFriend->AI()->DoAction(ACTION_COOLEST_FRIEND_PREPARE);
253
255 }
256
285
286 void OnSpellStart(SpellInfo const* spellInfo) override
287 {
288 if (spellInfo->Id == SPELL_FLASH_FREEZE)
289 {
294 }
295 }
296
297 void OnSpellCast(SpellInfo const* spellInfo) override
298 {
299 if (spellInfo->Id == SPELL_FROZEN_BLOWS)
301
302 if (spellInfo->Id == SPELL_BERSERK)
304 }
305
306 void DamageTaken(Unit* /*who*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
307 {
308 if (damage >= me->GetHealth())
309 {
310 damage = me->GetHealth() - 1;
311
312 if (_isDefeated)
313 return;
314
315 _isDefeated = true;
316
318 }
319 }
320
321 void EnterEvadeMode(EvadeReason /*why*/) override
322 {
323 if (!_isDefeated)
324 {
327 }
328 else
329 {
331 me->CombatStop(true);
332 }
333 }
334
335 void KilledUnit(Unit* who) override
336 {
337 if (who->GetTypeId() == TYPEID_PLAYER)
338 Talk(SAY_SLAY);
339 }
340
341 void UpdateAI(uint32 diff) override
342 {
344
346 return;
347
348 while (uint32 eventId = _epilogueEvents.ExecuteEvent())
349 {
350 switch (eventId)
351 {
352 case EVENT_EPILOGUE_1:
353 {
354 std::vector<Creature*> coolestFriends;
355 GetCreatureListWithOptionsInGrid(coolestFriends, me, 100.0f, { .StringId = "HodirCoolestFriend" });
356 for (Creature* coolestFriend : coolestFriends)
357 if (coolestFriend->IsAlive())
358 coolestFriend->AI()->DoAction(ACTION_COOLEST_FRIEND_VICTORY);
359
360 // This is not correct, they don't despawn, we just want to prevent combat stuck
363
367 me->AttackStop();
371 me->SetImmuneToNPC(true);
373
374 events.Reset();
375
377
379 break;
380 }
381 case EVENT_EPILOGUE_2:
384 break;
385 case EVENT_EPILOGUE_3:
388 break;
389 case EVENT_EPILOGUE_4:
392 break;
393 case EVENT_EPILOGUE_5:
395 break;
396 default:
397 break;
398 }
399 }
400
401 if (!UpdateVictim())
402 return;
403
404 events.Update(diff);
405
407 return;
408
409 while (uint32 eventId = events.ExecuteEvent())
410 {
411 switch (eventId)
412 {
413 case EVENT_FREEZE:
414 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 55.0f, true))
415 DoCast(target, SPELL_FREEZE);
416 events.Repeat(10s, 25s);
417 break;
420 events.Repeat(60s, 65s);
421 break;
424 events.Repeat(60s, 90s);
425 break;
426 case EVENT_BERSERK:
428 break;
429
432 trigger->CastSpell(trigger, SPELL_FLASH_FREEZE_VISUAL);
433
435 break;
437 {
438 std::vector<Creature*> firesCreatures;
439 GetCreatureListWithEntryInGrid(firesCreatures, me, NPC_TOASTY_FIRE, 100.0f);
440 for (Creature* fire : firesCreatures)
441 fire->DespawnOrUnsummon();
442
443 std::vector<GameObject*> firesObjects;
444 GetGameObjectListWithEntryInGrid(firesObjects, me, GO_TOASTY_FIRE, 100.0f);
445 for (GameObject* fire : firesObjects)
446 fire->ActivateObject(GameObjectActions::Despawn, 0);
447
449 break;
450 }
453 break;
454 default:
455 break;
456 }
457
459 return;
460 }
461 }
462
463private:
466};
467
469{
470 CoolestFriendBaseAI(Creature* creature) : ScriptedAI(creature), Instance(creature->GetInstanceScript()) { }
471
472 void InitializeAI() override
473 {
475 {
477 });
478 }
479
480 void JustAppeared() override
481 {
483 }
484
485 void Reset() override
486 {
488 }
489
490 void JustEngagedWith(Unit* /*who*/) override
491 {
493 }
494
495 virtual void ScheduleEvents() = 0;
496
497 void AttackStart(Unit* who) override
498 {
500 }
501
502 void DoAction(int32 action) override
503 {
504 switch (action)
505 {
507 {
508 me->SetImmuneToNPC(false);
509
510 // Not sure if below is correct approach, we just want friends to help
511 std::vector<Creature*> flashes;
513 for (Creature* flash : flashes)
514 me->EngageWithTarget(flash);
515
517 me->EngageWithTarget(hodir);
518
519 break;
520 }
522 EpilogueScheduler.Schedule(3s, [this](TaskContext& task)
523 {
524 switch (task.GetRepeatCounter())
525 {
526 case 0:
527 me->SetImmuneToNPC(true);
529 task.Repeat(5s);
530 break;
531 case 1:
533 task.Repeat(5s);
534 break;
535 case 2:
537 task.Repeat(5s);
538 break;
539 case 3:
541 task.Repeat(randtime(15s, 30s));
542 break;
543 case 4:
545 break;
546 default:
547 break;
548 }
549 });
550 break;
551 default:
552 break;
553 }
554 }
555
556 void EnterEvadeMode(EvadeReason why) override
557 {
560 }
561
562 void JustDied(Unit* /*killer*/) override
563 {
565 hodir->AI()->DoAction(ACTION_COOLEST_FRIEND_DIES);
566 }
567
568 void UpdateAI(uint32 diff) override
569 {
571
573 return;
574
575 Scheduler.Update(diff);
576 }
577
578protected:
582};
583
584// 32897 - Field Medic Penny
585// 32948 - Battle-Priest Eliza
586// 33326 - Field Medic Jessi
587// 33330 - Battle-Priest Gina
589{
591
592 void ScheduleEvents() override
593 {
595 .Schedule(0s, [this](TaskContext& task)
596 {
598 task.Repeat(2400ms);
599 })
600 .Schedule(0s, 5s, [this](TaskContext& task)
601 {
603 task.Repeat(7s, 9s);
604 })
605 .Schedule(0s, [this](TaskContext& task)
606 {
607 std::list<Creature*> targets = DoFindFriendlyCC(40.0f);
608 if (!targets.empty())
609 {
611 task.Repeat(2400ms);
612 }
613 else
614 task.Repeat(1200ms);
615 });
616 }
617};
618
619// 32900 - Elementalist Avuun
620// 32950 - Spiritwalker Yona
621// 33328 - Elementalist Mahfuun
622// 33332 - Spiritwalker Tara
624{
626
627 void ScheduleEvents() override
628 {
630 .Schedule(0s, [this](TaskContext& task)
631 {
633 task.Repeat(3600ms);
634 })
635 .Schedule(0s, [this](TaskContext& task)
636 {
638 task.Repeat(30s);
639 });
640 }
641};
642
643// 32901 - Ellie Nightfeather
644// 32941 - Tor Greycloud
645// 33325 - Eivi Nightfeather
646// 33333 - Kar Greycloud
648{
650
656
657 void ScheduleEvents() override
658 {
660 .Schedule(0s, [this](TaskContext& task)
661 {
663 task.Repeat(2400ms);
664 })
665 .Schedule(0s, 5s, [this](TaskContext& task)
666 {
668 task.Repeat(15s);
669 });
670 }
671};
672
673// 32893 - Missy Flamecuffs
674// 32946 - Veesha Blazeweaver
675// 33327 - Sissy Flamecuffs
676// 33331 - Amira Blazeweaver
678{
679 npc_hodir_mage(Creature* creature) : CoolestFriendBaseAI(creature) { }
680
681 void ScheduleEvents() override
682 {
684 .Schedule(0s, [this](TaskContext& task)
685 {
687 task.Repeat(3600ms);
688 })
689 .Schedule(5s, 10s, [this](TaskContext& task)
690 {
692 task.Repeat(10s, 20s);
693 })
694 .Schedule(0s, [this](TaskContext& task)
695 {
697 task.Repeat(1200ms);
698 });
699 }
700};
701
702// 33342 - Toasty Fire
704{
705 npc_toasty_fire(Creature* creature) : ScriptedAI(creature) { }
706
707 void InitializeAI() override
708 {
710 }
711
717
718 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
719 {
720 // Actually this does not happen in sniffs or videos. Initially wrong behavior or something is missing?
721 if (spellInfo->Id == SPELL_ICE_SHARDS_DAMAGE_1 || spellInfo->Id == SPELL_ICE_SHARDS_DAMAGE_2)
722 {
724 fire->ActivateObject(GameObjectActions::Despawn, 0);
725
727 }
728 }
729};
730
731// 33169 - Icicle
732// 33173 - Snowpacked Icicle
733struct npc_icicle : public ScriptedAI
734{
735 npc_icicle(Creature* creature) : ScriptedAI(creature) { }
736
737 void InitializeAI() override
738 {
741 }
742
743 void JustAppeared() override
744 {
745 _scheduler.Schedule(3500ms, [this](TaskContext const& /*task*/)
746 {
747 switch (me->GetEntry())
748 {
749 case NPC_ICICLE:
750 DoCastSelf(SPELL_ICICLE_PERIODIC_1);
751 DoCastSelf(SPELL_ICICLE_DUMMY);
752 break;
753 case NPC_SNOWPACKED_ICICLE:
754 DoCastSelf(SPELL_ICICLE_PERIODIC_2);
755 DoCastSelf(SPELL_ICICLE_DUMMY);
756 break;
757 default:
758 break;
759 }
760 });
761 }
762
763 void UpdateAI(uint32 diff) override
764 {
765 _scheduler.Update(diff);
766 }
767
768private:
770};
771
772// 33174 - Snowpacked Icicle Target
774{
776
777 void InitializeAI() override
778 {
780 }
781
787};
788
789// 32938 - Flash Freeze
791{
792 npc_flash_freeze_init(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _isShattered(false) { }
793
794 void InitializeAI() override
795 {
798 }
799
800 void JustAppeared() override
801 {
804
806 hodir->AI()->JustSummoned(me);
807
808 // This part requires sniff verification
809 _scheduler.Schedule(1s, [this](TaskContext& task)
810 {
811 if (TempSummon* summon = me->ToTempSummon())
812 if (Unit* summoner = summon->GetSummonerUnit())
813 if (!summoner->IsAlive())
815
816 task.Repeat(1s);
817 });
818 }
819
820 void DamageTaken(Unit* /*who*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
821 {
822 if (damage >= me->GetHealth())
823 {
824 damage = me->GetHealth() - 1;
825
826 if (_isShattered)
827 return;
828
829 _isShattered = true;
830
831 _scheduler.Schedule(1s, [this](TaskContext& task)
832 {
833 switch (task.GetRepeatCounter())
834 {
835 case 0:
836 me->InterruptNonMeleeSpells(false);
837 me->SetUninteractible(true);
838 task.Repeat(1s);
839 break;
840 case 1:
841 me->DespawnOrUnsummon();
842 break;
843 default:
844 break;
845 }
846 });
847 }
848 }
849
850 void UpdateAI(uint32 diff) override
851 {
852 UpdateVictim();
853
854 _scheduler.Update(diff);
855 }
856
857private:
861};
862
863// 32926 - Flash Freeze
865{
866 npc_flash_freeze_combat(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _isShattered(false) { }
867
868 void InitializeAI() override
869 {
872 }
873
874 void JustAppeared() override
875 {
877
879 hodir->AI()->JustSummoned(me);
880
881 // This part requires sniff verification
882 _scheduler.Schedule(1s, [this](TaskContext& task)
883 {
884 if (TempSummon* summon = me->ToTempSummon())
885 if (Unit* summoner = summon->GetSummonerUnit())
886 if (!summoner->IsAlive())
888
889 task.Repeat(1s);
890 });
891 }
892
893 void DamageTaken(Unit* /*who*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
894 {
895 if (damage >= me->GetHealth())
896 {
897 damage = me->GetHealth() - 1;
898
899 if (_isShattered)
900 return;
901
902 _isShattered = true;
903
904 _scheduler.Schedule(1s, [this](TaskContext& task)
905 {
906 switch (task.GetRepeatCounter())
907 {
908 case 0:
909 me->InterruptNonMeleeSpells(false);
910 me->SetUninteractible(true);
911 task.Repeat(1s);
912 break;
913 case 1:
914 me->DespawnOrUnsummon();
915 break;
916 default:
917 break;
918 }
919 });
920 }
921 }
922
923 void UpdateAI(uint32 diff) override
924 {
925 UpdateVictim();
926
927 _scheduler.Update(diff);
928 }
929
930private:
934};
935
936// 62469 - Freeze
938{
939 bool Validate(SpellInfo const* spellInfo) override
940 {
941 return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } })
943 }
944
945 void FilterTargets(std::list<WorldObject*>& targets)
946 {
947 targets.remove_if(Trinity::UnitAuraCheck(true, uint32(GetEffectInfo(EFFECT_1).CalcValueAsInt())));
948 }
949
954};
955
956// 61968 - Flash Freeze
958{
970
971 void OnPeriodic(AuraEffect const* aurEff)
972 {
973 Unit* target = GetTarget();
974
975 if (aurEff->GetTickNumber() == 1 && !target->HasAura(SPELL_SAFE_AREA_AURA))
976 {
978 {
979 // This part requires sniff verification
980 if (Unit* caster = GetCaster())
981 caster->CastSpell(target, SPELL_FLASH_FREEZE_KILL, true);
982 }
983 else
984 {
985 target->CastSpell(target, SPELL_FLASH_FREEZE_SUMMON_COMBAT, true);
986
987 if (target->IsPlayer())
988 if (Unit* caster = GetCaster())
989 if (Creature* creatureCaster = caster->ToCreature())
990 if (CreatureAI* ai = creatureCaster->AI())
991 ai->DoAction(ACTION_PLAYER_IS_FROZEN);
992 }
993 }
994 }
995
1000};
1001
1002// 65272 - Shatter Chest
1004{
1005 bool Validate(SpellInfo const* /*spellInfo*/) override
1006 {
1008 }
1009
1010 void OnPeriodic(AuraEffect const* /*aurEff*/)
1011 {
1013 }
1014
1019};
1020
1021// 63545 - Icicle
1023{
1024 bool Validate(SpellInfo const* spellInfo) override
1025 {
1026 return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValueAsInt()) });
1027 }
1028
1029 void FilterTargets(std::list<WorldObject*>& targets)
1030 {
1032 }
1033
1034 void HandleDummy(SpellEffIndex /*effIndex*/)
1035 {
1036 GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectInfo(EFFECT_0).CalcValueAsInt()), true);
1037 }
1038
1044};
1045
1046// 62476 - Icicle
1047// 62477 - Icicle
1060
1061// 62038 - Biting Cold
1063{
1064 bool Validate(SpellInfo const* /*spellInfo*/) override
1065 {
1067 }
1068
1069 void OnPeriodic(AuraEffect const* aurEff)
1070 {
1071 Unit* target = GetTarget();
1072
1073 if (target->isMoving() || target->HasAura(SPELL_TOASTY_FIRE_AREA_AURA))
1074 {
1076 const_cast<AuraEffect*>(aurEff)->ResetTicks();
1077 }
1078 else if (!(aurEff->GetTickNumber() % 4) && !target->HasAura(SPELL_TOASTY_FIRE_AREA_AURA))
1079 target->CastSpell(target, SPELL_BITING_COLD_PERIODIC, true);
1080 }
1081
1086};
1087
1088// 62039 - Biting Cold
1090{
1091 bool Validate(SpellInfo const* /*spellInfo*/) override
1092 {
1094 }
1095
1096 void OnPeriodic(AuraEffect const* /*aurEff*/)
1097 {
1099 .SetTriggerFlags(TRIGGERED_FULL_MASK)
1100 .AddSpellMod(SPELLVALUE_BASE_POINT0, int32(200 * std::pow(2.0f, GetStackAmount()))));
1101
1102 if (GetStackAmount() > 2)
1103 if (InstanceScript* instance = GetTarget()->GetInstanceScript())
1104 if (Creature* hodir = instance->GetCreature(DATA_HODIR))
1105 hodir->AI()->DoAction(ACTION_BITING_COLD_TOO_MUCH_STACKS);
1106 }
1107
1112};
1113
1114// 63499 - Dispel Magic
1116{
1117 bool Validate(SpellInfo const* spellInfo) override
1118 {
1119 return ValidateSpellEffect({ { spellInfo->Id, EFFECT_1 } })
1121 }
1122
1123 void FilterTargets(std::list<WorldObject*>& targets)
1124 {
1125 targets.remove_if(Trinity::UnitAuraCheck(false, uint32(GetEffectInfo(EFFECT_1).CalcValueAsInt())));
1127 }
1128
1133};
1134
1135// 62797 - Storm Cloud
1159
1160// 64543 - Melt Ice
1162{
1163 bool Validate(SpellInfo const* spellInfo) override
1164 {
1165 return ValidateSpellEffect({ { spellInfo->Id, EFFECT_0 } })
1167 }
1168
1169 void FilterTargets(std::list<WorldObject*>& targets)
1170 {
1171 targets.remove_if(Trinity::UnitAuraCheck(true, uint32(GetEffectInfo(EFFECT_0).CalcValueAsInt())));
1173 }
1174
1175 void HandleDummy(SpellEffIndex /*effIndex*/)
1176 {
1178 }
1179
1185};
1186
int32_t int32
Definition Define.h:150
uint32_t uint32
Definition Define.h:154
@ DONE
@ TEMPSUMMON_MANUAL_DESPAWN
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
Milliseconds randtime(Milliseconds min, Milliseconds max)
Definition Random.cpp:63
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1383
void GetCreatureListWithEntryInGrid(Container &container, WorldObject *source, uint32 entry, float maxSearchRange)
void GetCreatureListWithOptionsInGrid(Container &container, WorldObject *source, float maxSearchRange, FindCreatureOptions const &options)
Creature * GetClosestCreatureWithEntry(WorldObject *source, uint32 entry, float maxSearchRange, bool alive=true)
void GetGameObjectListWithEntryInGrid(Container &container, WorldObject *source, uint32 entry, float maxSearchRange)
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ SPELL_EFFECT_DUMMY
@ TARGET_UNIT_SRC_AREA_ENTRY
@ TARGET_UNIT_DEST_AREA_ENEMY
@ TARGET_UNIT_SRC_AREA_ENEMY
@ EMOTE_ONESHOT_CHEER_NO_SHEATHE
@ EMOTE_ONESHOT_DANCE
@ TEAM_HORDE
@ FACTION_FRIENDLY
#define EFFECT_ALL
@ SPELL_AURA_PERIODIC_DUMMY
@ TRIGGERED_FULL_MASK
Used when doing CastSpell with triggered == true.
@ SPELLVALUE_BASE_POINT0
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
EvadeReason
@ REACT_PASSIVE
DamageEffectType
@ UNIT_STATE_CASTING
Definition Unit.h:290
HodirCreatures
@ NPC_FLASH_FREEZE_INIT
@ NPC_FLASH_FREEZE_COMBAT
@ NPC_ICICLE
@ NPC_TOASTY_FIRE
@ NPC_SNOWPACKED_ICICLE
@ NPC_INVISIBLE_STALKER
HodirGameObjects
@ GO_TOASTY_FIRE
HodirSpells
@ SPELL_ICE_SHARDS_DAMAGE_1
@ SPELL_FLASH_FREEZE_KILL
@ SPELL_STORM_POWER
@ SPELL_STORM_CLOUD_EFFECT
@ SPELL_GREATER_HEAL
@ SPELL_MELT_ICE
@ SPELL_SHATTER_CHEST_MISSILE
@ SPELL_ICICLE_PERIODIC
@ SPELL_STARLIGHT
@ SPELL_ICICLE_DUMMY
@ SPELL_FLASH_FREEZE_STUN_COMBAT
@ SPELL_SAFE_AREA
@ SPELL_LAVA_BURST
@ SPELL_FREEZE
@ SPELL_KILL_CREDIT
@ SPELL_FLASH_FREEZE_STUN_INIT
@ SPELL_FLASH_FREEZE
@ SPELL_ICICLE_PERIODIC_1
@ SPELL_BITING_COLD
@ SPELL_TELEPORT
@ SPELL_DISPEL_MAGIC
@ SPELL_MOONKIN_FORM_SHAPESHIFT
@ SPELL_TOASTY_FIRE_AREA_AURA
@ SPELL_STORM_POWER_H
@ SPELL_FIREBALL
@ SPELL_BITING_COLD_DAMAGE
@ SPELL_FLASH_FREEZE_VISUAL
@ SPELL_ICICLE_PERIODIC_2
@ SPELL_FLASH_FREEZE_INITIAL_AGGRO
@ SPELL_SMITE
@ SPELL_FLASH_FREEZE_SUMMON_INIT
@ SPELL_ICE_SHARDS_DAMAGE_2
@ SPELL_STORM_CLOUD_EFFECT_H
@ SPELL_FROZEN_BLOWS
@ SPELL_FLASH_FREEZE_SUMMON_COMBAT
@ SPELL_WRATH
@ SPELL_STORM_CLOUD
@ SPELL_SHATTER_CHEST
@ SPELL_CONJURE_TOASTY_FIRE
@ SPELL_BERSERK
@ SPELL_BITING_COLD_PERIODIC
@ SPELL_CHECK_FOR_PLAYERS
@ SPELL_ICICLE_FORCE_CAST
@ SPELL_BIRTH_NO_VISUAL
@ SPELL_SAFE_AREA_AURA
static constexpr std::array< uint32, 8 > CoolestFriendsEntriesHorde
HodirEvents
@ EVENT_FLASH_FREEZE_FINISHED_2
@ EVENT_EPILOGUE_5
@ EVENT_EPILOGUE_1
@ EVENT_EPILOGUE_4
@ EVENT_FLASH_FREEZE
@ EVENT_FROZEN_BLOWS
@ EVENT_BERSERK
@ EVENT_FREEZE
@ EVENT_FLASH_FREEZE_FINISHED_1
@ EVENT_EPILOGUE_2
@ EVENT_EPILOGUE_3
@ EVENT_FLASH_FREEZE_FINISHED_3
static constexpr std::array< uint32, 8 > CoolestFriendsEntriesAlliance
void AddSC_boss_hodir()
HodirTexts
@ SAY_DEATH
@ EMOTE_BLOWS
@ SAY_AGGRO
@ EMOTE_FREEZE
@ SAY_FLASH_FREEZE
@ SAY_SLAY
@ EMOTE_SHATTER
@ SAY_BERSERK
Position const SummonPositions[8]
HodirActions
@ ACTION_PLAYER_IS_FROZEN
@ ACTION_COOLEST_FRIEND_VICTORY
@ ACTION_COOLEST_FRIEND_DIES
@ ACTION_COOLEST_FRIEND_PREPARE
@ ACTION_BITING_COLD_TOO_MUCH_STACKS
uint32 GetTickNumber() const
HookList< EffectPeriodicHandler > OnEffectPeriodic
Unit * GetCaster() const
Unit * GetTarget() const
uint8 GetStackAmount() const
bool IsPlayer() const
Definition BaseEntity.h:173
TypeID GetTypeId() const
Definition BaseEntity.h:166
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
SummonList summons
EventMap events
void DoZoneInCombat()
Definition CreatureAI.h:169
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:63
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:394
void SetDisplayFromModel(uint32 modelIdx)
void SetReactState(ReactStates st)
Definition Creature.h:180
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
void SetImmuneToNPC(bool apply) override
Definition Creature.h:193
void Update(uint32 time)
Definition EventMap.h:77
void Repeat(Milliseconds time)
Definition EventMap.cpp:67
EventId ExecuteEvent()
Definition EventMap.cpp:77
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:40
void Reset()
Definition EventMap.cpp:25
TeamId GetTeamIdInInstance() const
Definition Map.cpp:3441
virtual bool SetBossState(uint32 id, EncounterState state)
Creature * GetCreature(uint32 type)
void DoUpdateWorldState(int32 worldStateId, int32 value)
InstanceMap * instance
void TriggerGameEvent(uint32 gameEventId, WorldObject *source=nullptr, WorldObject *target=nullptr) override
uint32 GetEntry() const
Definition Object.h:89
Creature * ToCreature()
Definition Object.h:121
int32 CalcValueAsInt(WorldObject const *caster=nullptr, SpellEffectValue const *basePoints=nullptr, Unit const *target=nullptr, float *variance=nullptr, uint32 castItemId=0, int32 itemLevel=-1) const
uint32 const Id
Definition SpellInfo.h:328
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:590
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
static bool ValidateSpellEffect(std::initializer_list< std::pair< uint32, SpellEffIndex > > effects)
Unit * GetCaster() const
int32 GetEffectValueAsInt() const
Unit * GetHitUnit() const
SpellEffectInfo const & GetEffectInfo() const
HookList< EffectHandler > OnEffectHitTarget
SpellInfo const * GetSpellInfo() const
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
void DespawnEntry(uint32 entry)
TaskScheduler::repeated_t GetRepeatCounter() const
Returns the repeat counter which increases every time the task is repeated.
TaskContext & Repeat(TaskScheduler::duration_t duration)
TaskScheduler & CancelAll()
TaskScheduler & Schedule(duration_t time, task_handler_t task)
TaskScheduler & SetValidator(P &&predicate)
Sets a validator which is asked if tasks are allowed to be executed.
TaskScheduler & Update()
Update the scheduler to the current time.
void AttackStartCaster(Unit *victim, float dist)
Definition UnitAI.cpp:47
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:160
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:172
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:71
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:162
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:81
Definition Unit.h:647
void CombatStop(bool includingCast=false, bool mutualPvP=true, bool(*unitFilter)(Unit const *otherUnit)=nullptr)
Definition Unit.cpp:6031
void SetFaction(uint32 faction) override
Definition Unit.h:887
TempSummon * ToTempSummon()
Definition Unit.h:1844
void SetEmoteState(Emote emote)
Definition Unit.h:880
uint64 GetHealth() const
Definition Unit.h:800
bool isMoving() const
Definition Unit.h:1820
void EngageWithTarget(Unit *who)
Definition Unit.cpp:8513
void RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT, uint16 num=1)
Definition Unit.cpp:4008
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
void RemoveAllAttackers()
Definition Unit.cpp:6085
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4822
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition Unit.cpp:1662
bool AttackStop()
Definition Unit.cpp:5984
void RemoveAurasOnEvade()
Definition Unit.cpp:4461
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3992
bool IsInCombat() const
Definition Unit.h:1073
GameObject * FindNearestGameObject(uint32 entry, float range, bool spawnedOnly=true) const
Definition Object.cpp:1544
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
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:1403
bool Validate(SpellInfo const *) override
void OnPeriodic(AuraEffect const *aurEff)
bool Validate(SpellInfo const *) override
void OnPeriodic(AuraEffect const *)
bool Validate(SpellInfo const *spellInfo) override
void FilterTargets(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
void Register() override
void OnPeriodic(AuraEffect const *aurEff)
bool Validate(SpellInfo const *spellInfo) override
void FilterTargets(std::list< WorldObject * > &targets)
void Register() override
void FilterTargets(std::list< WorldObject * > &targets)
void Register() override
void FilterTargets(std::list< WorldObject * > &targets)
void HandleDummy(SpellEffIndex)
bool Validate(SpellInfo const *spellInfo) override
void FilterTargets(std::list< WorldObject * > &targets)
void HandleDummy(SpellEffIndex)
void Register() override
bool Validate(SpellInfo const *spellInfo) override
void OnPeriodic(AuraEffect const *)
bool Validate(SpellInfo const *) override
void HandleDummy(SpellEffIndex)
void FilterTargets(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
void RandomResize(C &container, std::size_t requestedSize)
Definition Containers.h:67
void EnterEvadeMode(EvadeReason why) override
void JustEngagedWith(Unit *) override
void UpdateAI(uint32 diff) override
void AttackStart(Unit *who) override
CoolestFriendBaseAI(Creature *creature)
TaskScheduler EpilogueScheduler
virtual void ScheduleEvents()=0
void JustAppeared() override
void Reset() override
void InitializeAI() override
InstanceScript * Instance
TaskScheduler Scheduler
void DoAction(int32 action) override
void JustDied(Unit *) override
constexpr void GetPosition(float &x, float &y) const
Definition Position.h:92
T const & RAID_MODE(T const &normal10, T const &normal25) const
std::list< Creature * > DoFindFriendlyCC(float range)
boss_hodir(Creature *creature)
EventMap _epilogueEvents
void UpdateAI(uint32 diff) override
void DoAction(int32 action) override
void EnterEvadeMode(EvadeReason) override
void JustAppeared() override
void OnSpellCast(SpellInfo const *spellInfo) override
void OnSpellStart(SpellInfo const *spellInfo) override
void JustEngagedWith(Unit *who) override
void KilledUnit(Unit *who) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
void JustAppeared() override
void UpdateAI(uint32 diff) override
void InitializeAI() override
npc_flash_freeze_combat(Creature *creature)
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
InstanceScript * _instance
void InitializeAI() override
TaskScheduler _scheduler
npc_flash_freeze_init(Creature *creature)
void JustAppeared() override
void UpdateAI(uint32 diff) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
InstanceScript * _instance
void ScheduleEvents() override
npc_hodir_druid(Creature *creature)
void JustAppeared() override
npc_hodir_mage(Creature *creature)
void ScheduleEvents() override
npc_hodir_priest(Creature *creature)
void ScheduleEvents() override
void ScheduleEvents() override
npc_hodir_shaman(Creature *creature)
void UpdateAI(uint32 diff) override
void InitializeAI() override
TaskScheduler _scheduler
void JustAppeared() override
npc_icicle(Creature *creature)
npc_snowpacked_icicle_target(Creature *creature)
void InitializeAI() override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void JustAppeared() override
npc_toasty_fire(Creature *creature)
@ DATA_HODIR
Definition ulduar.h:44
#define RegisterUlduarCreatureAI(ai_name)
Definition ulduar.h:537
@ EVENT_ID_ENGAGE_HODIR
Definition ulduar.h:473
@ WORLD_STATE_HODIR_THIS_CACHE_WAS_RARE_FAILED
Definition ulduar.h:484
@ WORLD_STATE_HODIR_COOLEST_FRIENDS_FAILED
Definition ulduar.h:483
@ WORLD_STATE_HODIR_CHEESE_THE_FREEZE_FAILED
Definition ulduar.h:482
@ WORLD_STATE_HODIR_GETTING_COLD_FAILED
Definition ulduar.h:481
@ NPC_FIELD_MEDIC_PENNY
Definition ulduar.h:156
@ NPC_AMIRA_BLAZEWEAVER
Definition ulduar.h:150
@ NPC_BATTLE_PRIEST_ELIZA
Definition ulduar.h:154
@ NPC_SISSY_FLAMECUFFS
Definition ulduar.h:153
@ NPC_EIVI_NIGHTFEATHER
Definition ulduar.h:144
@ NPC_KAR_GREYCLOUD
Definition ulduar.h:143
@ NPC_MISSY_FLAMECUFFS
Definition ulduar.h:152
@ NPC_BATTLE_PRIEST_GINA
Definition ulduar.h:155
@ NPC_SPIRITWALKER_YONA
Definition ulduar.h:147
@ NPC_ELEMENTALIST_MAHFUUN
Definition ulduar.h:148
@ NPC_TOR_GREYCLOUD
Definition ulduar.h:142
@ NPC_SPIRITWALKER_TARA
Definition ulduar.h:146
@ NPC_ELLIE_NIGHTFEATHER
Definition ulduar.h:145
@ NPC_VEESHA_BLAZEWEAVER
Definition ulduar.h:151
@ NPC_ELEMENTALIST_AVUUN
Definition ulduar.h:149
@ NPC_FIELD_MEDIC_JESSI
Definition ulduar.h:157
@ ACTION_FLASH_FREEZE_FINISHED
Definition ulduar.h:350
@ ACTION_INITIAL_AGGRO_HODIR
Definition ulduar.h:348
@ ACTION_CACHE_SHATTERED
Definition ulduar.h:349