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 "SpellMgr.h"
37#include "TemporarySummon.h"
38#include "ulduar.h"
39#include <span>
40
52
54{
55 // Hodir - Initial
59
60 // Hodir - Combat
61 SPELL_FREEZE = 62469,
65
66 // Hodir - Combat - Misc
69
70 // Hodir - Outro
74
75 // Generic
79
80 // Invisible Stalker (Float, Uninteractible, LargeAOI)
82
83 // Snowpacked Icicle Target
86
87 // Icicle
88 // Snowpacked Icicle
92
93 // Priests
94 SPELL_SMITE = 61923,
97
98 // Shamans
101
102 // Druids
104 SPELL_WRATH = 62793,
106
107 // Mages
111
112 // Toasty Fire
114
115 // Flash Freeze (Init)
118
119 // Flash Freeze (Combat)
121
122 // Scripts
126
128
131
134
135 // Misc
137 SPELL_STORM_POWER_H = 65134
139
157
167
169{
170 GO_TOASTY_FIRE = 194300
172
181
183{
184 { 1983.75f, -243.36f, 432.767f, 1.57f }, // Field Medic Penny && Battle-Priest Eliza
185 { 1999.90f, -230.49f, 432.767f, 1.57f }, // Eivi Nightfeather && Tor Greycloud
186 { 2010.06f, -243.45f, 432.767f, 1.57f }, // Elementalist Mahfuun && Spiritwalker Tara
187 { 2021.12f, -236.65f, 432.767f, 1.57f }, // Missy Flamecuffs && Amira Blazeweaver
188 { 2028.10f, -244.66f, 432.767f, 1.57f }, // Field Medic Jessi && Battle-Priest Gina
189 { 2014.18f, -232.80f, 432.767f, 1.57f }, // Ellie Nightfeather && Kar Greycloud
190 { 1992.90f, -237.54f, 432.767f, 1.57f }, // Elementalist Avuun && Spiritwalker Yona
191 { 1976.60f, -233.53f, 432.767f, 1.57f } // Sissy Flamecuffs && Veesha Blazeweaver
192};
193
205
217
218// 32845 - Hodir
219struct boss_hodir : public BossAI
220{
221 boss_hodir(Creature* creature) : BossAI(creature, DATA_HODIR)
222 {
223 _isDefeated = false;
228 }
229
230 void JustAppeared() override
231 {
232 int32 count = RAID_MODE(4, 8);
233 std::span<uint32 const> entries = instance->GetData(WORLD_STATE_ULDUAR_TEAM_IN_INSTANCE) == 2
236 for (int32 i = 0; i < count; ++i)
238 }
239
240 void JustEngagedWith(Unit* who) override
241 {
243
245
249
254
255 std::vector<Creature*> coolestFriends;
256 GetCreatureListWithOptionsInGrid(coolestFriends, me, 100.0f, { .StringId = "HodirCoolestFriend" });
257 for (Creature* coolestFriend : coolestFriends)
258 coolestFriend->AI()->DoAction(ACTION_COOLEST_FRIEND_PREPARE);
259 }
260
261 void DoAction(int32 action) override
262 {
263 switch (action)
264 {
266 if (!me->IsInCombat())
268 break;
271 break;
274 break;
277 break;
281 break;
284 break;
285 default:
286 break;
287 }
288 }
289
290 uint32 GetData(uint32 type) const override
291 {
292 // TODO: Replace with real worldstates
293 switch (type)
294 {
296 return _cheeseTheFreezeFailed ? 1 : 0;
298 return _gettingColdInHereFailed ? 1 : 0;
300 return _thisCacheWasRareFailed ? 1 : 0;
302 return _iHaveTheCoolestFriendsFailed ? 1 : 0;
303 }
304
305 return 0;
306 }
307
318
319 void OnSpellCast(SpellInfo const* spellInfo) override
320 {
321 if (spellInfo->Id == sSpellMgr->GetSpellIdForDifficulty(SPELL_FROZEN_BLOWS, me))
323
324 if (spellInfo->Id == SPELL_BERSERK)
326 }
327
328 void DamageTaken(Unit* /*who*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
329 {
330 if (damage >= me->GetHealth())
331 {
332 damage = me->GetHealth() - 1;
333
334 if (_isDefeated)
335 return;
336
337 _isDefeated = true;
338
340 }
341 }
342
343 void EnterEvadeMode(EvadeReason /*why*/) override
344 {
345 if (!_isDefeated)
346 {
349 }
350 else
351 {
353 me->CombatStop(true);
354 }
355 }
356
357 void KilledUnit(Unit* who) override
358 {
359 if (who->GetTypeId() == TYPEID_PLAYER)
360 Talk(SAY_SLAY);
361 }
362
363 void UpdateAI(uint32 diff) override
364 {
366
368 return;
369
370 while (uint32 eventId = _epilogueEvents.ExecuteEvent())
371 {
372 switch (eventId)
373 {
374 case EVENT_EPILOGUE_1:
375 {
376 std::vector<Creature*> coolestFriends;
377 GetCreatureListWithOptionsInGrid(coolestFriends, me, 100.0f, { .StringId = "HodirCoolestFriend" });
378 for (Creature* coolestFriend : coolestFriends)
379 if (coolestFriend->IsAlive())
380 coolestFriend->AI()->DoAction(ACTION_COOLEST_FRIEND_VICTORY);
381
382 // This is not correct, they don't despawn, we just want to prevent combat stuck
385
389 me->AttackStop();
393 me->SetImmuneToNPC(true);
395
396 events.Reset();
397
399
401 break;
402 }
403 case EVENT_EPILOGUE_2:
406 break;
407 case EVENT_EPILOGUE_3:
410 break;
411 case EVENT_EPILOGUE_4:
414 break;
415 case EVENT_EPILOGUE_5:
417 break;
418 default:
419 break;
420 }
421 }
422
423 if (!UpdateVictim())
424 return;
425
426 events.Update(diff);
427
429 return;
430
431 while (uint32 eventId = events.ExecuteEvent())
432 {
433 switch (eventId)
434 {
435 case EVENT_FREEZE:
436 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 55.0f, true))
437 DoCast(target, SPELL_FREEZE);
438 events.Repeat(10s, 25s);
439 break;
442 events.Repeat(60s, 65s);
443 break;
446 events.Repeat(60s, 90s);
447 break;
448 case EVENT_BERSERK:
450 break;
451
454 trigger->CastSpell(trigger, SPELL_FLASH_FREEZE_VISUAL);
455
457 break;
459 {
460 std::vector<Creature*> firesCreatures;
461 GetCreatureListWithEntryInGrid(firesCreatures, me, NPC_TOASTY_FIRE, 100.0f);
462 for (Creature* fire : firesCreatures)
463 fire->DespawnOrUnsummon();
464
465 std::vector<GameObject*> firesObjects;
466 GetGameObjectListWithEntryInGrid(firesObjects, me, GO_TOASTY_FIRE, 100.0f);
467 for (GameObject* fire : firesObjects)
468 fire->ActivateObject(GameObjectActions(GameObjectActions::Despawn));
469
471 break;
472 }
475 break;
476 default:
477 break;
478 }
479
481 return;
482 }
483
485 }
486
487private:
494};
495
497{
498 CoolestFriendBaseAI(Creature* creature) : ScriptedAI(creature), Instance(creature->GetInstanceScript()) { }
499
500 void InitializeAI() override
501 {
503 {
505 });
506 }
507
508 void JustAppeared() override
509 {
511 }
512
513 void Reset() override
514 {
516 }
517
518 void JustEngagedWith(Unit* /*who*/) override
519 {
521 }
522
523 virtual void ScheduleEvents() = 0;
524
525 void AttackStart(Unit* who) override
526 {
528 }
529
530 void DoAction(int32 action) override
531 {
532 switch (action)
533 {
535 {
536 me->SetImmuneToNPC(false);
537
538 // Not sure if below is correct approach, we just want friends to help
539 std::vector<Creature*> flashes;
541 for (Creature* flash : flashes)
542 me->EngageWithTarget(flash);
543
545 me->EngageWithTarget(hodir);
546
547 break;
548 }
550 EpilogueScheduler.Schedule(3s, [this](TaskContext task)
551 {
552 switch (task.GetRepeatCounter())
553 {
554 case 0:
555 me->SetImmuneToNPC(true);
557 task.Repeat(5s);
558 break;
559 case 1:
561 task.Repeat(5s);
562 break;
563 case 2:
565 task.Repeat(5s);
566 break;
567 case 3:
569 task.Repeat(randtime(15s, 30s));
570 break;
571 case 4:
573 break;
574 default:
575 break;
576 }
577 });
578 break;
579 default:
580 break;
581 }
582 }
583
584 void EnterEvadeMode(EvadeReason why) override
585 {
588 }
589
590 void JustDied(Unit* /*killer*/) override
591 {
593 hodir->AI()->DoAction(ACTION_COOLEST_FRIEND_DIES);
594 }
595
596 void UpdateAI(uint32 diff) override
597 {
599
601 return;
602
603 Scheduler.Update(diff);
604
606 }
607
608protected:
612};
613
614// 32897 - Field Medic Penny
615// 32948 - Battle-Priest Eliza
616// 33326 - Field Medic Jessi
617// 33330 - Battle-Priest Gina
619{
621
622 void ScheduleEvents() override
623 {
625 .Schedule(0s, [this](TaskContext task)
626 {
628 task.Repeat(2400ms);
629 })
630 .Schedule(0s, 5s, [this](TaskContext task)
631 {
633 task.Repeat(7s, 9s);
634 })
635 .Schedule(0s, [this](TaskContext task)
636 {
637 std::list<Creature*> targets = DoFindFriendlyCC(40.0f);
638 if (!targets.empty())
639 {
641 task.Repeat(2400ms);
642 }
643 else
644 task.Repeat(1200ms);
645 });
646 }
647};
648
649// 32900 - Elementalist Avuun
650// 32950 - Spiritwalker Yona
651// 33328 - Elementalist Mahfuun
652// 33332 - Spiritwalker Tara
654{
656
657 void ScheduleEvents() override
658 {
660 .Schedule(0s, [this](TaskContext task)
661 {
663 task.Repeat(3600ms);
664 })
665 .Schedule(0s, [this](TaskContext task)
666 {
668 task.Repeat(30s);
669 });
670 }
671};
672
673// 32901 - Ellie Nightfeather
674// 32941 - Tor Greycloud
675// 33325 - Eivi Nightfeather
676// 33333 - Kar Greycloud
678{
680
686
687 void ScheduleEvents() override
688 {
690 .Schedule(0s, [this](TaskContext task)
691 {
693 task.Repeat(2400ms);
694 })
695 .Schedule(0s, 5s, [this](TaskContext task)
696 {
698 task.Repeat(15s);
699 });
700 }
701};
702
703// 32893 - Missy Flamecuffs
704// 32946 - Veesha Blazeweaver
705// 33327 - Sissy Flamecuffs
706// 33331 - Amira Blazeweaver
708{
709 npc_hodir_mage(Creature* creature) : CoolestFriendBaseAI(creature) { }
710
711 void ScheduleEvents() override
712 {
714 .Schedule(0s, [this](TaskContext task)
715 {
717 task.Repeat(3600ms);
718 })
719 .Schedule(5s, 10s, [this](TaskContext task)
720 {
722 task.Repeat(10s, 20s);
723 })
724 .Schedule(0s, [this](TaskContext task)
725 {
727 task.Repeat(1200ms);
728 });
729 }
730};
731
732// 33342 - Toasty Fire
734{
735 npc_toasty_fire(Creature* creature) : ScriptedAI(creature) { }
736
737 void InitializeAI() override
738 {
740 }
741
747
748 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
749 {
750 // Actually this does not happen in sniffs or videos. Initially wrong behavior or something is missing?
751 if (spellInfo->Id == SPELL_ICE_SHARDS_DAMAGE_1 || spellInfo->Id == SPELL_ICE_SHARDS_DAMAGE_2)
752 {
754 fire->ActivateObject(GameObjectActions(GameObjectActions::Despawn));
755
757 }
758 }
759};
760
761// 33169 - Icicle
762// 33173 - Snowpacked Icicle
763struct npc_icicle : public ScriptedAI
764{
765 npc_icicle(Creature* creature) : ScriptedAI(creature) { }
766
772
773 void JustAppeared() override
774 {
775 _scheduler.Schedule(3500ms, [this](TaskContext /*task*/)
776 {
777 switch (me->GetEntry())
778 {
779 case NPC_ICICLE:
780 DoCastSelf(SPELL_ICICLE_PERIODIC_1);
781 DoCastSelf(SPELL_ICICLE_DUMMY);
782 break;
783 case NPC_SNOWPACKED_ICICLE:
784 DoCastSelf(SPELL_ICICLE_PERIODIC_2);
785 DoCastSelf(SPELL_ICICLE_DUMMY);
786 break;
787 default:
788 break;
789 }
790 });
791 }
792
793 void UpdateAI(uint32 diff) override
794 {
795 _scheduler.Update(diff);
796 }
797
798private:
800};
801
802// 33174 - Snowpacked Icicle Target
804{
806
807 void InitializeAI() override
808 {
810 }
811
817};
818
819// 32938 - Flash Freeze
821{
822 npc_flash_freeze_init(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _isShattered(false) { }
823
829
830 void JustAppeared() override
831 {
834
836 hodir->AI()->JustSummoned(me);
837
838 // This part requires sniff verification
839 _scheduler.Schedule(1s, [this](TaskContext task)
840 {
841 if (TempSummon* summon = me->ToTempSummon())
842 if (Unit* summoner = summon->GetSummonerUnit())
843 if (!summoner->IsAlive())
845
846 task.Repeat(1s);
847 });
848 }
849
850 void DamageTaken(Unit* /*who*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
851 {
852 if (damage >= me->GetHealth())
853 {
854 damage = me->GetHealth() - 1;
855
856 if (_isShattered)
857 return;
858
859 _isShattered = true;
860
861 _scheduler.Schedule(1s, [this](TaskContext task)
862 {
863 switch (task.GetRepeatCounter())
864 {
865 case 0:
866 me->InterruptNonMeleeSpells(false);
867 me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
868 task.Repeat(1s);
869 break;
870 case 1:
871 me->DespawnOrUnsummon();
872 break;
873 default:
874 break;
875 }
876 });
877 }
878 }
879
880 void UpdateAI(uint32 diff) override
881 {
882 UpdateVictim();
883
884 _scheduler.Update(diff);
885 }
886
887private:
891};
892
893// 32926 - Flash Freeze
895{
896 npc_flash_freeze_combat(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _isShattered(false) { }
897
903
904 void JustAppeared() override
905 {
907
909 hodir->AI()->JustSummoned(me);
910
911 // This part requires sniff verification
912 _scheduler.Schedule(1s, [this](TaskContext task)
913 {
914 if (TempSummon* summon = me->ToTempSummon())
915 if (Unit* summoner = summon->GetSummonerUnit())
916 if (!summoner->IsAlive())
918
919 task.Repeat(1s);
920 });
921 }
922
923 void DamageTaken(Unit* /*who*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
924 {
925 if (damage >= me->GetHealth())
926 {
927 damage = me->GetHealth() - 1;
928
929 if (_isShattered)
930 return;
931
932 _isShattered = true;
933
934 _scheduler.Schedule(1s, [this](TaskContext task)
935 {
936 switch (task.GetRepeatCounter())
937 {
938 case 0:
939 me->InterruptNonMeleeSpells(false);
940 me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
941 task.Repeat(1s);
942 break;
943 case 1:
944 me->DespawnOrUnsummon();
945 break;
946 default:
947 break;
948 }
949 });
950 }
951 }
952
953 void UpdateAI(uint32 diff) override
954 {
955 UpdateVictim();
956
957 _scheduler.Update(diff);
958 }
959
960private:
964};
965
966// 62469 - Freeze
968{
970
971 bool Validate(SpellInfo const* spellInfo) override
972 {
973 return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_1).CalcValue()) });
974 }
975
976 void FilterTargets(std::list<WorldObject*>& targets)
977 {
978 targets.remove_if(Trinity::UnitAuraCheck(true, uint32(GetEffectInfo(EFFECT_1).CalcValue())));
979 }
980
985};
986
987// 61968 - Flash Freeze
989{
991
1003
1004 void OnPeriodic(AuraEffect const* aurEff)
1005 {
1006 Unit* target = GetTarget();
1007
1008 if (aurEff->GetTickNumber() == 1 && !target->HasAura(SPELL_SAFE_AREA_AURA))
1009 {
1011 {
1012 // This part requires sniff verification
1013 if (Unit* caster = GetCaster())
1014 caster->CastSpell(target, SPELL_FLASH_FREEZE_KILL, true);
1015 }
1016 else
1017 {
1018 target->CastSpell(target, SPELL_FLASH_FREEZE_SUMMON_COMBAT, true);
1019
1020 if (target->IsPlayer())
1021 if (Unit* caster = GetCaster())
1022 if (Creature* creatureCaster = caster->ToCreature())
1023 if (CreatureAI* ai = creatureCaster->AI())
1024 ai->DoAction(ACTION_PLAYER_IS_FROZEN);
1025 }
1026 }
1027 }
1028
1033};
1034
1035// 65272 - Shatter Chest
1055
1056// 63545 - Icicle
1058{
1060
1061 bool Validate(SpellInfo const* spellInfo) override
1062 {
1063 return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
1064 }
1065
1066 void FilterTargets(std::list<WorldObject*>& targets)
1067 {
1069 }
1070
1071 void HandleDummy(SpellEffIndex /*effIndex*/)
1072 {
1073 GetCaster()->CastSpell(GetHitUnit(), uint32(GetEffectInfo(EFFECT_0).CalcValue()), true);
1074 }
1075
1081};
1082
1083// 62476 - Icicle
1084// 62477 - Icicle
1099
1100// 62038 - Biting Cold
1102{
1104
1105 bool Validate(SpellInfo const* /*spellInfo*/) override
1106 {
1108 }
1109
1110 void OnPeriodic(AuraEffect const* aurEff)
1111 {
1112 Unit* target = GetTarget();
1113
1114 if (target->isMoving() || target->HasAura(SPELL_TOASTY_FIRE_AREA_AURA))
1115 {
1117 const_cast<AuraEffect*>(aurEff)->ResetTicks();
1118 }
1119 else if (!(aurEff->GetTickNumber() % 4) && !target->HasAura(SPELL_TOASTY_FIRE_AREA_AURA))
1120 target->CastSpell(target, SPELL_BITING_COLD_PERIODIC, true);
1121 }
1122
1127};
1128
1129// 62039 - Biting Cold
1131{
1133
1134 bool Validate(SpellInfo const* /*spellInfo*/) override
1135 {
1137 }
1138
1139 void OnPeriodic(AuraEffect const* /*aurEff*/)
1140 {
1142 .SetTriggerFlags(TRIGGERED_FULL_MASK)
1143 .AddSpellMod(SPELLVALUE_BASE_POINT0, int32(200 * std::pow(2.0f, GetStackAmount()))));
1144
1145 if (GetStackAmount() > 2)
1146 if (InstanceScript* instance = GetTarget()->GetInstanceScript())
1147 if (Creature* hodir = instance->GetCreature(DATA_HODIR))
1148 hodir->AI()->DoAction(ACTION_BITING_COLD_TOO_MUCH_STACKS);
1149 }
1150
1155};
1156
1157// 63499 - Dispel Magic
1159{
1161
1162 bool Validate(SpellInfo const* spellInfo) override
1163 {
1164 return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_1).CalcValue()) });
1165 }
1166
1167 void FilterTargets(std::list<WorldObject*>& targets)
1168 {
1169 targets.remove_if(Trinity::UnitAuraCheck(false, uint32(GetEffectInfo(EFFECT_1).CalcValue())));
1171 }
1172
1177};
1178
1179// 62797 - Storm Cloud
1206
1207// 64543 - Melt Ice
1209{
1211
1212 bool Validate(SpellInfo const* spellInfo) override
1213 {
1214 return ValidateSpellInfo({ uint32(spellInfo->GetEffect(EFFECT_0).CalcValue()) });
1215 }
1216
1217 void FilterTargets(std::list<WorldObject*>& targets)
1218 {
1219 targets.remove_if(Trinity::UnitAuraCheck(true, uint32(GetEffectInfo(EFFECT_0).CalcValue())));
1221 }
1222
1223 void HandleDummy(SpellEffIndex /*effIndex*/)
1224 {
1226 }
1227
1233};
1234
1236{
1237public:
1238 achievement_cheese_the_freeze() : AchievementCriteriaScript("achievement_cheese_the_freeze") { }
1239
1240 bool OnCheck(Player* /*player*/, Unit* target) override
1241 {
1242 return target && target->GetAI() && !target->GetAI()->GetData(WORLD_STATE_HODIR_CHEESE_THE_FREEZE_FAILED);
1243 }
1244};
1245
1247{
1248public:
1249 achievement_getting_cold_in_here() : AchievementCriteriaScript("achievement_getting_cold_in_here") { }
1250
1251 bool OnCheck(Player* /*player*/, Unit* target) override
1252 {
1253 return target && target->GetAI() && !target->GetAI()->GetData(WORLD_STATE_HODIR_GETTING_COLD_FAILED);
1254 }
1255};
1256
1258{
1259public:
1260 achievement_this_cache_was_rare() : AchievementCriteriaScript("achievement_this_cache_was_rare") { }
1261
1262 bool OnCheck(Player* /*player*/, Unit* target) override
1263 {
1264 return target && target->GetAI() && !target->GetAI()->GetData(WORLD_STATE_HODIR_THIS_CACHE_WAS_RARE_FAILED);
1265 }
1266};
1267
1269{
1270public:
1271 achievement_i_have_the_coolest_friends() : AchievementCriteriaScript("achievement_i_have_the_coolest_friends") { }
1272
1273 bool OnCheck(Player* /*player*/, Unit* target) override
1274 {
1275 return target && target->GetAI() && !target->GetAI()->GetData(WORLD_STATE_HODIR_COOLEST_FRIENDS_FAILED);
1276 }
1277};
1278
1280{
1281public:
1282 achievement_staying_buffed_all_winter() : AchievementCriteriaScript("achievement_staying_buffed_all_winter") { }
1283
1284 bool OnCheck(Player* player, Unit* /*target*/) override
1285 {
1287 }
1288};
1289
1291{
1292public:
1293 achievement_staying_buffed_all_winter_25() : AchievementCriteriaScript("achievement_staying_buffed_all_winter_25") { }
1294
1295 bool OnCheck(Player* player, Unit* /*target*/) override
1296 {
1298 }
1299};
1300
@ RAID_DIFFICULTY_10MAN_NORMAL
Definition DBCEnums.h:286
int32_t int32
Definition Define.h:129
uint32_t uint32
Definition Define.h:133
GameObjectActions
@ DONE
@ TEMPSUMMON_MANUAL_DESPAWN
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
Milliseconds randtime(Milliseconds min, Milliseconds max)
Definition Random.cpp:62
if(posix_memalign(&__mallocedMemory, __align, __size)) return NULL
#define RegisterSpellScript(spell_script)
Definition ScriptMgr.h:1128
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
@ FACTION_FRIENDLY
#define EFFECT_ALL
@ SPELL_AURA_PERIODIC_DUMMY
@ TRIGGERED_FULL_MASK
Will return SPELL_FAILED_DONT_REPORT in CheckCast functions.
@ SPELLVALUE_BASE_POINT0
#define sSpellMgr
Definition SpellMgr.h:738
#define SpellEffectFn(F, I, N)
#define SpellObjectAreaTargetSelectFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
@ REACT_PASSIVE
@ UNIT_STATE_CASTING
Definition Unit.h:235
DamageEffectType
Definition Unit.h:352
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_FORCE_CAST_H
@ 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
InstanceScript *const instance
void JustEngagedWith(Unit *who) override
void _DespawnAtEvade(Seconds delayToRespawn=30s, Creature *who=nullptr)
SummonList summons
EventMap events
@ EVADE_REASON_OTHER
Definition CreatureAI.h:98
void DoZoneInCombat(Creature *creature=nullptr)
bool UpdateVictim()
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 SetDisplayId(uint32 modelId) override
void SetReactState(ReactStates st)
Definition Creature.h:119
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:186
void SetImmuneToNPC(bool apply) override
Definition Creature.h:132
void Update(uint32 time)
Definition EventMap.h:67
void Repeat(Milliseconds time)
Definition EventMap.cpp:63
EventId ExecuteEvent()
Definition EventMap.cpp:73
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
void Reset()
Definition EventMap.cpp:21
virtual bool SetBossState(uint32 id, EncounterState state)
Creature * GetCreature(uint32 type)
static Creature * ToCreature(Object *o)
Definition Object.h:186
bool IsPlayer() const
Definition Object.h:179
TypeID GetTypeId() const
Definition Object.h:93
uint32 GetEntry() const
Definition Object.h:81
int32 CalcValue(WorldObject const *caster=nullptr, int32 const *basePoints=nullptr) const
uint32 Id
Definition SpellInfo.h:289
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:483
Unit * GetCaster() const
Unit * GetHitUnit() const
SpellEffectInfo const & GetEffectInfo() const
HookList< EffectHandler > OnEffectHitTarget
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
void DespawnEntry(uint32 entry)
TaskContext & Repeat(std::chrono::duration< _Rep, _Period > const &duration)
TaskScheduler::repeated_t GetRepeatCounter() const
Returns the repeat counter which increases every time the task is repeated.
TaskScheduler & CancelAll()
TaskScheduler & Schedule(std::chrono::duration< _Rep, _Period > const &time, task_handler_t const &task)
TaskScheduler & Update(success_t const &callback=EmptyCallback)
TaskScheduler & SetValidator(P &&predicate)
Sets a validator which is asked if tasks are allowed to be executed.
void AttackStartCaster(Unit *victim, float dist)
Definition UnitAI.cpp:48
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:241
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
SpellCastResult DoCastAOE(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:243
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
void SetFaction(uint32 faction) override
Definition Unit.h:974
TempSummon * ToTempSummon()
Definition Unit.h:1794
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
void SetEmoteState(Emote emote)
Definition Unit.h:967
uint32 GetHealth() const
Definition Unit.h:913
void RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3800
bool isMoving() const
Definition Unit.h:1759
void EngageWithTarget(Unit *who)
Definition Unit.cpp:8292
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
bool HasUnitState(const uint32 f) const
Definition Unit.h:876
void HandleEmoteCommand(Emote emoteId)
Definition Unit.cpp:1568
void RemoveAllAttackers()
Definition Unit.cpp:5736
void CombatStop(bool includingCast=false, bool mutualPvP=true)
Definition Unit.cpp:5691
bool AttackStop()
Definition Unit.cpp:5645
void RemoveAurasOnEvade()
Definition Unit.cpp:4218
bool IsInCombat() const
Definition Unit.h:1144
GameObject * FindNearestGameObject(uint32 entry, float range, bool spawnedOnly=true) const
Definition Object.cpp:2121
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
virtual uint32 GetData(uint32) const
Definition ZoneScript.h:55
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
bool OnCheck(Player *, Unit *target) override
bool OnCheck(Player *, Unit *target) override
bool OnCheck(Player *, Unit *target) override
bool OnCheck(Player *player, Unit *) override
bool OnCheck(Player *player, Unit *) override
bool OnCheck(Player *, Unit *target) override
PrepareAuraScript(spell_hodir_biting_cold_area_aura)
bool Validate(SpellInfo const *) override
void OnPeriodic(AuraEffect const *aurEff)
bool Validate(SpellInfo const *) override
void OnPeriodic(AuraEffect const *)
PrepareAuraScript(spell_hodir_biting_cold_periodic)
PrepareSpellScript(spell_hodir_dispel_magic)
bool Validate(SpellInfo const *spellInfo) override
void FilterTargets(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
PrepareAuraScript(spell_hodir_flash_freeze)
void OnPeriodic(AuraEffect const *aurEff)
bool Validate(SpellInfo const *spellInfo) override
void FilterTargets(std::list< WorldObject * > &targets)
void Register() override
PrepareSpellScript(spell_hodir_freeze)
PrepareSpellScript(spell_hodir_icicle_force_cast)
void FilterTargets(std::list< WorldObject * > &targets)
PrepareSpellScript(spell_hodir_icicle)
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)
PrepareSpellScript(spell_hodir_melt_ice)
void Register() override
bool Validate(SpellInfo const *spellInfo) override
PrepareAuraScript(spell_hodir_shatter_chest)
void OnPeriodic(AuraEffect const *)
bool Validate(SpellInfo const *) override
void HandleDummy(SpellEffIndex)
PrepareSpellScript(spell_hodir_storm_cloud_primer)
void FilterTargets(std::list< WorldObject * > &targets)
bool Validate(SpellInfo const *) override
void RandomResize(C &container, std::size_t requestedSize)
Definition Containers.h:66
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
void GetPosition(float &x, float &y) const
Definition Position.h:84
T const & RAID_MODE(T const &normal10, T const &normal25) const
Difficulty GetDifficulty() 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
uint32 GetData(uint32 type) const override
void OnSpellCast(SpellInfo const *spellInfo) override
void OnSpellStart(SpellInfo const *spellInfo) override
bool _cheeseTheFreezeFailed
void JustEngagedWith(Unit *who) override
void KilledUnit(Unit *who) override
bool _iHaveTheCoolestFriendsFailed
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
bool _thisCacheWasRareFailed
bool _gettingColdInHereFailed
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:43
#define RegisterUlduarCreatureAI(ai_name)
Definition ulduar.h:541
@ WORLD_STATE_HODIR_THIS_CACHE_WAS_RARE_FAILED
Definition ulduar.h:488
@ WORLD_STATE_HODIR_COOLEST_FRIENDS_FAILED
Definition ulduar.h:487
@ WORLD_STATE_ULDUAR_TEAM_IN_INSTANCE
Definition ulduar.h:482
@ WORLD_STATE_HODIR_CHEESE_THE_FREEZE_FAILED
Definition ulduar.h:486
@ WORLD_STATE_HODIR_GETTING_COLD_FAILED
Definition ulduar.h:485
@ NPC_FIELD_MEDIC_PENNY
Definition ulduar.h:155
@ NPC_AMIRA_BLAZEWEAVER
Definition ulduar.h:149
@ NPC_BATTLE_PRIEST_ELIZA
Definition ulduar.h:153
@ NPC_SISSY_FLAMECUFFS
Definition ulduar.h:152
@ NPC_EIVI_NIGHTFEATHER
Definition ulduar.h:143
@ NPC_KAR_GREYCLOUD
Definition ulduar.h:142
@ NPC_MISSY_FLAMECUFFS
Definition ulduar.h:151
@ NPC_BATTLE_PRIEST_GINA
Definition ulduar.h:154
@ NPC_SPIRITWALKER_YONA
Definition ulduar.h:146
@ NPC_ELEMENTALIST_MAHFUUN
Definition ulduar.h:147
@ NPC_TOR_GREYCLOUD
Definition ulduar.h:141
@ NPC_SPIRITWALKER_TARA
Definition ulduar.h:145
@ NPC_ELLIE_NIGHTFEATHER
Definition ulduar.h:144
@ NPC_VEESHA_BLAZEWEAVER
Definition ulduar.h:150
@ NPC_ELEMENTALIST_AVUUN
Definition ulduar.h:148
@ NPC_FIELD_MEDIC_JESSI
Definition ulduar.h:156
@ ACTION_FLASH_FREEZE_FINISHED
Definition ulduar.h:349
@ ACTION_INITIAL_AGGRO_HODIR
Definition ulduar.h:347
@ ACTION_CACHE_SHATTERED
Definition ulduar.h:348