TrinityCore
zone_silverpine_forest.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 "CellImpl.h"
19#include "CombatAI.h"
20#include "CreatureAIImpl.h"
21#include "GameObject.h"
22#include "GameObjectAI.h"
23#include "GridNotifiers.h"
24#include "Group.h"
25#include "MotionMaster.h"
26#include "ObjectAccessor.h"
27#include "ObjectMgr.h"
28#include "Object.h"
29#include "Player.h"
30#include "ScriptMgr.h"
31#include "ScriptedCreature.h"
32#include "ScriptedGossip.h"
33#include "SharedDefines.h"
34#include "SpellAuras.h"
35#include "SpellAuraEffects.h"
36#include "SpellScript.h"
37#include "SpellMgr.h"
38#include "TemporarySummon.h"
39#include "Unit.h"
40#include "Vehicle.h"
41#include "WorldSession.h"
42
44{
49
51
57
62
64 PATH_TROOPER_1 = 3578560,
65 PATH_TROOPER_2 = 3578568,
66 PATH_TROOPER_3 = 3578576,
67 PATH_TROOPER_4 = 3578584,
68 PATH_TROOPER_5 = 3578592,
69
75
82};
83
84// 44731 - Horde Hauler
86{
88
89 void JustAppeared() override
90 {
92 }
93
94 void PassengerBoarded(Unit* passenger, int8 seatId, bool apply) override
95 {
96 if (apply && passenger->IsPlayer())
97 {
98 _playerGUID = passenger->GetGUID();
99
100 if (seatId == SEAT_HAULER_PLAYER)
101 {
102 if (Creature* engineer = me->FindNearestCreature(NPC_HORDE_ENGINEER_HAULER, 15.0f, true))
103 {
105 {
106 if (engineer->IsAIEnabled())
107 engineer->AI()->Talk(TALK_HAULER_BOARDED, player);
108 }
109 }
110 }
111 }
112
113 if (!apply && !passenger->IsPlayer())
114 {
115 uint32 pathId = 0;
116
117 switch (seatId)
118 {
120 pathId = PATH_TROOPER_1;
121 break;
123 pathId = PATH_TROOPER_2;
124 break;
126 pathId = PATH_TROOPER_3;
127 break;
129 pathId = PATH_TROOPER_4;
130 break;
132 pathId = PATH_TROOPER_5;
133 break;
134
135 default:
136 break;
137 }
138
139 passenger->GetMotionMaster()->MovePath(pathId, false);
140 }
141 }
142
143 void WaypointReached(uint32 waypointId, uint32 pathId) override
144 {
145 if (pathId == PATH_FROM_NORTH_TO_SOUTH)
146 {
147 if (waypointId == WAYPOINT_ON_FORSAKEN_HIGH)
149 else if (waypointId == WAYPOINT_ON_SEPULCHER)
151 else if (waypointId == WAYPOINT_ON_FORSAKEN_FRONT)
153 else if (waypointId == WAYPOINT_ON_DESPAWN_POINT_SOUTH)
155 }
156 }
157
158 void UpdateAI(uint32 diff) override
159 {
160 _events.Update(diff);
161
162 while (uint32 eventId = _events.ExecuteEvent())
163 {
164 switch (eventId)
165 {
166 case EVENT_START_PATH:
168 break;
169
171 {
172 if (Creature* engineer = me->FindNearestCreature(NPC_HORDE_ENGINEER_HAULER, 15.0f, true))
173 {
174 if (engineer->IsAIEnabled())
175 engineer->AI()->Talk(TALK_ON_FORSAKEN_HIGH);
176 }
177 break;
178 }
179
181 {
182 if (Creature* engineer = me->FindNearestCreature(NPC_HORDE_ENGINEER_HAULER, 15.0f, true))
183 {
184 if (engineer->IsAIEnabled())
185 engineer->AI()->Talk(TALK_ON_SEPULCHER);
186 }
187 break;
188 }
189
191 {
192 if (Creature* engineer = me->FindNearestCreature(NPC_HORDE_ENGINEER_HAULER, 15.0f, true))
193 {
194 if (engineer->IsAIEnabled())
195 engineer->AI()->Talk(TALK_ON_FORSAKEN_FRONT);
196 }
197
199
201 break;
202 }
203
204 default:
205 break;
206 }
207 }
208 }
209
210private:
213};
214
216{
220
221// 84238 - Magical Chains (Hauler)
223{
224 bool Validate(SpellInfo const* /*spellInfo*/) override
225 {
226 return ValidateSpellInfo
227 ({
230 });
231 }
232
233 void HandlePeriodic(AuraEffect const* /*aurEff*/)
234 {
237 }
238
239 void Register() override
240 {
242 }
243};
244
246{
247 { 1358.62f, 1054.72f, 53.1200f, 0.0f },
248 { 1393.27f, 1021.20f, 53.2225f, 0.0f },
249 { 1404.71f, 1063.73f, 60.5617f, 0.0f }
250};
251
253{
254 { 1387.90f, 1029.71f, 53.21853f, 2.827433f },
255 { 1389.79f, 1024.51f, 53.20833f, 2.827433f },
256 { 1388.05f, 1026.91f, 53.20833f, 2.827433f },
257 { 1388.16f, 1020.88f, 53.25523f, 2.827433f },
258 { 1385.79f, 1025.99f, 53.22593f, 2.827433f },
259 { 1386.69f, 1023.26f, 53.24393f, 2.827433f },
260 { 1384.33f, 1022.04f, 53.28123f, 2.827433f },
261 { 1391.10f, 1027.73f, 53.20483f, 2.827433f },
262
263 { 1359.10f, 1046.55f, 52.97053f, 5.253441f },
264 { 1360.89f, 1051.81f, 53.19793f, 5.253441f },
265 { 1360.75f, 1048.84f, 53.12893f, 5.253441f },
266 { 1364.43f, 1053.62f, 53.29343f, 5.253441f },
267 { 1363.08f, 1048.15f, 53.22223f, 5.253441f },
268 { 1364.08f, 1050.84f, 53.29163f, 5.253441f },
269 { 1366.69f, 1050.31f, 53.34203f, 5.253441f },
270 { 1357.85f, 1050.12f, 52.99823f, 5.253441f }
271};
272
273Position const GarroshPos = { 1402.45f, 1061.62f, 60.56173f, 3.926991f };
274
275Position const GarroshJumpPos = { 1378.65f, 1044.23f, 53.8389f, 5.51524f };
276
277Position const CromushPos = { 1404.71f, 1063.73f, 60.5617f, 2.827433f };
278
279Position const AgathaPreRisePos = { 1364.02f, 1028.54f, 66.99143f };
280
281Position const AgathaRisePos = { 1368.65f, 1032.19f, 63.3033f };
282
283Position const AgathaPreResetPos = { 1364.02f, 1028.54f, 55.9914f };
284
285Position const AgathaResetPos = { 1364.02f, 1028.54f, 58.1319f };
286
288{
290
302
307
311 EVENT_AGATHA_RAISE_FORSAKEN = 4, // Note: 4-8 are used.
312 EVENT_SCENE_TALK_COMETH = 9, // Note: 9-36 are used.
313
315
340
341 PATH_CROMUSH = 3571216,
342 PATH_GARROSH = 3570320,
343
348
355
356// 44615 - Grand Executor Mortuus
358{
360
361 void OnQuestAccept(Player* /*player*/, Quest const* quest) override
362 {
364 {
366 return;
367
369 }
370 }
371
372 void Reset() override
373 {
374 _events.Reset();
379 _summons.clear();
380 _eventInProgress = false;
381 }
382
383 void JustSummoned(Creature* summon) override
384 {
385 _summons.Summon(summon);
386
387 switch (summon->GetEntry())
388 {
390 summon->CastSpell(summon, SPELL_SIMPLE_TELEPORT);
391 _garroshGUID = summon->GetGUID();
392 break;
393
395 summon->CastSpell(summon, SPELL_SIMPLE_TELEPORT);
396 break;
397
398 default:
399 break;
400 }
401 }
402
403 void DoAction(int32 param) override
404 {
405 switch (param)
406 {
408 {
409 _eventInProgress = true;
410
412 {
413 _sylvanasGUID = sylvanas->GetGUID();
414
415 if (Creature* agatha = me->FindNearestCreature(NPC_AGATHA_COMETH, 100.0f))
416 {
417 _agathaGUID = agatha->GetGUID();
418
420 }
421 }
422
423 break;
424 }
425
426 default:
427 break;
428 }
429 }
430
431 void UpdateAI(uint32 diff) override
432 {
433 _events.Update(diff);
434
435 while (uint32 eventId = _events.ExecuteEvent())
436 {
437 switch (eventId)
438 {
443 break;
444
447 break;
448
451 break;
452
454 {
456 {
457 if (sylvanas->IsAIEnabled())
458 sylvanas->AI()->Talk(TALK_SYLVANAS_COMETH_0);
459
461 }
462 break;
463 }
464
466 {
468 {
469 sylvanas->SetFacingTo(0.808979f);
470
471 if (sylvanas->IsAIEnabled())
472 sylvanas->AI()->Talk(TALK_SYLVANAS_COMETH_1);
473
475 }
476 break;
477 }
478
480 {
482 {
483 garrosh->GetMotionMaster()->MoveJump(GarroshJumpPos, 15.595897f, 15.595897f);
484
486 }
487 break;
488 }
489
491 {
493 {
494 sylvanas->SetFacingTo(3.924652f);
495
497 }
498 break;
499 }
500
502 {
504 {
506 garrosh->SetFacingToObject(sylvanas);
507
508 garrosh->PlayOneShotAnimKitId(ANIMKIT_GARROSH_1);
509
510 if (garrosh->IsAIEnabled())
511 garrosh->AI()->Talk(TALK_GARROSH_COMETH_0);
512
514 }
515 break;
516 }
517
519 {
521 {
522 garrosh->SetFacingTo(3.9444442f);
523
524 if (garrosh->IsAIEnabled())
525 garrosh->AI()->Talk(TALK_GARROSH_COMETH_1);
526
528 }
529 break;
530 }
531
533 {
535 {
536 sylvanas->SetFacingTo(2.4260077f);
537
538 if (sylvanas->IsAIEnabled())
539 sylvanas->AI()->Talk(TALK_SYLVANAS_COMETH_2);
540
542 }
543 break;
544 }
545
547 {
549 {
550 sylvanas->SetFacingTo(3.7350047f);
551 sylvanas->PlayOneShotAnimKitId(ANIMKIT_SYLV_1);
552
553 if (sylvanas->IsAIEnabled())
554 sylvanas->AI()->Talk(TALK_SYLVANAS_COMETH_3);
555
557 }
558 break;
559 }
560
562 {
564 {
565 if (sylvanas->IsAIEnabled())
566 sylvanas->AI()->Talk(TALK_SYLVANAS_COMETH_4);
567
569 }
570 break;
571 }
572
574 {
576 {
577 if (garrosh->IsAIEnabled())
578 garrosh->AI()->Talk(TALK_GARROSH_COMETH_2);
579
581 }
582 break;
583 }
584
585 case EVENT_SCENE_TALK_COMETH + 10:
586 {
588 {
589 if (sylvanas->IsAIEnabled())
590 sylvanas->AI()->Talk(TALK_SYLVANAS_COMETH_5);
591
593 }
594 break;
595 }
596
597 case EVENT_SCENE_TALK_COMETH + 11:
598 {
600 {
601 if (sylvanas->IsAIEnabled())
602 sylvanas->AI()->Talk(TALK_SYLVANAS_COMETH_6);
603
605 }
606 break;
607 }
608
609 case EVENT_SCENE_TALK_COMETH + 12:
610 {
612 {
613 sylvanas->PlayOneShotAnimKitId(ANIMKIT_SYLV_2);
614
615 if (sylvanas->IsAIEnabled())
616 sylvanas->AI()->Talk(TALK_SYLVANAS_COMETH_7);
617
619 }
620 break;
621 }
622
623 case EVENT_SCENE_TALK_COMETH + 13:
624 {
626 {
627 if (sylvanas->IsAIEnabled())
628 sylvanas->AI()->Talk(TALK_SYLVANAS_COMETH_8);
629
631 }
632 break;
633 }
634
636 {
638 {
639 agatha->GetMotionMaster()->MovePoint(POINT_AGATHA_PRE_RISE, AgathaPreRisePos, false);
640
642 }
643 break;
644 }
645
647 {
649 {
650 agatha->SetWalk(true);
651 agatha->GetMotionMaster()->MovePoint(POINT_AGATHA_RISE, AgathaRisePos, false);
652
654 }
655 break;
656 }
657
659 {
661 {
662 agatha->CastSpell(agatha, SPELL_RAISE_FORSAKEN_COMETH);
663
665 }
666 break;
667 }
668
670 {
672 {
673 agatha->GetMotionMaster()->MovePoint(POINT_AGATHA_PRE_RESET, AgathaPreResetPos, false, 0.855211f);
674
676 }
677 break;
678 }
679
680 case EVENT_SCENE_TALK_COMETH + 14:
681 {
683 {
684 if (cromush->IsAIEnabled())
685 cromush->AI()->Talk(TALK_CROMUSH_COMETH_0);
686
688 }
689 break;
690 }
691
692 case EVENT_SCENE_TALK_COMETH + 15:
693 {
695 {
696 garrosh->PlayOneShotAnimKitId(ANIMKIT_GENERAL_1);
697
698 if (garrosh->IsAIEnabled())
699 garrosh->AI()->Talk(TALK_GARROSH_COMETH_3);
700
702 agatha->SetWalk(false);
703
705 }
706 break;
707 }
708
710 {
712 {
713 agatha->GetMotionMaster()->MovePoint(POINT_AGATHA_RESET, AgathaResetPos, false, 0.7155f);
714
716 }
717 break;
718 }
719
720 case EVENT_SCENE_TALK_COMETH + 16:
721 {
723 {
724 sylvanas->PlayOneShotAnimKitId(ANIMKIT_GENERAL_1);
725
726 if (sylvanas->IsAIEnabled())
727 sylvanas->AI()->Talk(TALK_SYLVANAS_COMETH_9);
728
730 }
731 break;
732 }
733
734 case EVENT_SCENE_TALK_COMETH + 17:
735 {
737 {
738 if (garrosh->IsAIEnabled())
739 garrosh->AI()->Talk(TALK_GARROSH_COMETH_4);
740
742 }
743 break;
744 }
745
746 case EVENT_SCENE_TALK_COMETH + 18:
747 {
749 {
750 if (garrosh->IsAIEnabled())
751 garrosh->AI()->Talk(TALK_GARROSH_COMETH_5);
752
754 }
755 break;
756 }
757
758 case EVENT_SCENE_TALK_COMETH + 19:
759 {
761 {
762 if (sylvanas->IsAIEnabled())
763 sylvanas->AI()->Talk(TALK_SYLVANAS_COMETH_10);
764
766 }
767 break;
768 }
769
770 case EVENT_SCENE_TALK_COMETH + 20:
771 {
773 {
774 garrosh->SetFacingTo(5.51524f);
775
776 if (garrosh->IsAIEnabled())
777 garrosh->AI()->Talk(TALK_GARROSH_COMETH_6);
778
780 }
781 break;
782 }
783
784 case EVENT_SCENE_TALK_COMETH + 21:
785 {
787 {
789 {
790 garrosh->SetFacingToObject(cromush);
791
793 }
794 }
795 break;
796 }
797
798 case EVENT_SCENE_TALK_COMETH + 22:
799 {
801 {
802 garrosh->PlayOneShotAnimKitId(ANIMKIT_GARROSH_2);
803
804 if (garrosh->IsAIEnabled())
805 garrosh->AI()->Talk(TALK_GARROSH_COMETH_7);
806
808 }
809 break;
810 }
811
812 case EVENT_SCENE_TALK_COMETH + 23:
813 {
815 {
816 if (cromush->IsAIEnabled())
817 cromush->AI()->Talk(TALK_CROMUSH_COMETH_1);
818
820 {
821 cromush->SetFacingToObject(garrosh);
822
824 }
825 }
826 break;
827 }
828
829 case EVENT_SCENE_TALK_COMETH + 24:
830 {
832 {
833 garrosh->SetFacingTo(5.6199603f);
834 garrosh->PlayOneShotAnimKitId(ANIMKIT_GARROSH_2);
835
836 if (garrosh->IsAIEnabled())
837 garrosh->AI()->Talk(TALK_GARROSH_COMETH_8);
838
840 }
841 break;
842 }
843
844 case EVENT_SCENE_TALK_COMETH + 25:
845 {
847 {
848 garrosh->CastSpell(garrosh, SPELL_WELCOME_TO_SILVERPINE_CREDIT, true);
849
850 garrosh->GetMotionMaster()->MovePath(PATH_GARROSH, false);
851
853 }
854 break;
855 }
856
857 case EVENT_SCENE_TALK_COMETH + 26:
860 break;
861
862 case EVENT_SCENE_TALK_COMETH + 27:
864 Reset();
865 break;
866
867 default:
868 break;
869 }
870 }
871
872 if (!UpdateVictim())
873 return;
874 }
875
877 {
878 for (Position const& pos : OrgrimmarPortalPos)
880
881 std::list<Creature*> orgrimmarPortals;
883
884 for (Creature* portal : orgrimmarPortals)
885 portal->CastSpell(portal, SPELL_AIR_REVENANT_ENTRANCE);
886 }
887
889 {
890 for (Position const& pos : HellscreamElitePos)
892
894
896 {
897 _cromushGUID = cromush->GetGUID();
898
899 cromush->RemoveNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
900 cromush->GetMotionMaster()->MovePath(PATH_CROMUSH, false);
901 }
902 }
903
905 {
906 for (ObjectGuid const& summonedCreature : _summons)
907 {
908 if (Creature* summon = ObjectAccessor::GetCreature(*me, summonedCreature))
909 summon->CastSpell(summon, SPELL_SIMPLE_TELEPORT);
910 }
911 }
912
913private:
921};
922
924{
927
929
933
934// 83173 - Raise Forsaken
936{
937 void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
938 {
939 Unit* target = GetTarget();
940
941 if (Creature* fallenHuman = target->ToCreature())
942 {
943 if (fallenHuman->IsAIEnabled())
944 fallenHuman->AI()->DoAction(ACTION_RISE_DURING_RAISE);
945 }
946 }
947
948 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
949 {
950 Unit* target = GetTarget();
951
952 if (Creature* fallenHuman = target->ToCreature())
953 {
954 if (fallenHuman->IsAIEnabled())
955 fallenHuman->AI()->DoAction(ACTION_DESCEND_AFTER_RAISE);
956 }
957 }
958
959 void Register() override
960 {
963 }
964};
965
967{
970
976
977// 44592, 44593 - Fallen Human
979{
981
982 void Reset() override
983 {
984 _transformDone = false;
985 _events.Reset();
986 }
987
988 void DoAction(int32 action) override
989 {
990 switch (action)
991 {
995 break;
996
998 me->SetWalk(false);
1002 break;
1003
1004 default:
1005 break;
1006 }
1007 }
1008
1009 void UpdateAI(uint32 diff) override
1010 {
1011 _events.Update(diff);
1012
1013 while (uint32 eventId = _events.ExecuteEvent())
1014 {
1015 switch (eventId)
1016 {
1017 case EVENT_ASCEND:
1018 me->SetWalk(true);
1020 break;
1021
1023 {
1024 if (_transformDone)
1025 return;
1026
1028
1029 _transformDone = true;
1030
1032 break;
1033 }
1034
1036 me->SetFacingTo(0.706837f);
1038 break;
1039
1042 me->DespawnOrUnsummon(80s);
1043 break;
1044
1045 default:
1046 break;
1047 }
1048 }
1049 }
1050
1051private:
1054};
1055
1057{
1066
1074 DISPLAY_FEMALE_04_HC = 33985
1076
1077// 83149 - Forsaken Trooper Master Script (Forsaken High Command)
1079{
1080 bool Validate(SpellInfo const* /*spellInfo*/) override
1081 {
1082 return ValidateSpellInfo
1083 ({
1092 });
1093 }
1094
1096 {
1097 if (Unit* caster = GetCaster())
1098 {
1099 caster->RemoveAura(SPELL_FEIGNED);
1100
1102
1103 switch (caster->GetDisplayId())
1104 {
1105 case DISPLAY_MALE_01_HC:
1107 break;
1108 case DISPLAY_MALE_02_HC:
1110 break;
1111 case DISPLAY_MALE_03_HC:
1113 break;
1114 case DISPLAY_MALE_04_HC:
1116 break;
1119 break;
1122 break;
1125 break;
1128 break;
1129 default:
1130 break;
1131 }
1132
1133 caster->CastSpell(caster, spellId, true);
1134 }
1135 }
1136
1137 void Register() override
1138 {
1140 }
1141};
1142
1144{
1146
1148
1154
1155// 44365 - Lady Sylvanas Windrunner (Forsaken High Command)
1157{
1159
1160 void JustAppeared() override
1161 {
1163 }
1164
1165 void JustSummoned(Creature* summon) override
1166 {
1167 switch (summon->GetEntry())
1168 {
1170 // Note: the Forsaken Horse must be set in the same visibility mask that Sylvanas is in.
1172 break;
1173 default:
1174 break;
1175 }
1176 }
1177
1178 void OnQuestReward(Player* player, Quest const* quest, LootItemType /*type*/, uint32 /*opt*/) override
1179 {
1180 switch (quest->GetQuestId())
1181 {
1182 case QUEST_NO_ESCAPE:
1183 player->CastSpell(player, SPELL_DESPAWN_ALL_SUMMONS_AGATHA, true);
1184 break;
1185 default:
1186 break;
1187 }
1188 }
1189};
1190
1191// 44789, 44790 - Deathstalker and Deathstalker Commander Belmont
1193{
1195
1196 void JustAppeared() override
1197 {
1198 // @TODO: figure out a common system to allow energy usage without scripts.
1201 me->SetPower(POWER_ENERGY, 100, true);
1202 }
1203};
1204
1206{
1210
1213
1214// 44793 - Worgen Renegade
1216{
1218
1219 void Reset() override
1220 {
1221 _events.Reset();
1222
1223 // Note: this is for a later usage during Lordaeron (questId 27098).
1224 if (me->IsSummon())
1226
1228 }
1229
1230 void JustEngagedWith(Unit* /*who*/) override
1231 {
1233 }
1234
1235 void UpdateAI(uint32 diff) override
1236 {
1237 if (!UpdateVictim())
1238 return;
1239
1240 _events.Update(diff);
1241
1242 while (uint32 eventId = _events.ExecuteEvent())
1243 {
1244 switch (eventId)
1245 {
1248 _events.Repeat(15s, 18s);
1249 break;
1250
1251 default:
1252 break;
1253 }
1254 }
1255 }
1256
1257private:
1259};
1260
1261// 80365 - Flurry of Claws
1263{
1264 bool Validate(SpellInfo const* spellInfo) override
1265 {
1266 return ValidateSpellInfo({ spellInfo->GetEffect(EFFECT_0).TriggerSpell });
1267 }
1268
1269 void HandlePeriodic(AuraEffect const* /*aurEff*/)
1270 {
1271 GetTarget()->CastSpell(nullptr, GetSpellInfo()->GetEffect(EFFECT_0).TriggerSpell, true);
1272 }
1273
1274 void Register() override
1275 {
1277 }
1278};
1279
1281{
1283
1285
1287
1290
1291// 44791, 44792 - Forsaken Trooper
1293{
1295
1296 void Reset() override
1297 {
1298 _events.Reset();
1299
1300 // Note: these texts are sent aswell during Lordaeron (questId 27098).
1301 if (urand(0, 1))
1303 }
1304
1305 void JustEngagedWith(Unit* /*who*/) override
1306 {
1308 }
1309
1310 void UpdateAI(uint32 diff) override
1311 {
1312 if (!UpdateVictim())
1313 return;
1314
1315 _events.Update(diff);
1316
1317 while (uint32 eventId = _events.ExecuteEvent())
1318 {
1319 switch (eventId)
1320 {
1321 case EVENT_CLEAVE:
1323 _events.Repeat(5s, 8s);
1324 break;
1325
1326 default:
1327 break;
1328 }
1329 }
1330 }
1331
1332private:
1334};
1335
1337{
1339
1341
1343
1346
1347// 44825 - Bat Handler Maggotbreath
1349{
1351
1352 bool OnGossipHello(Player* player) override
1353 {
1356
1357 if (me->IsTaxi())
1359
1360 SendGossipMenuFor(player, player->GetGossipTextId(me), me->GetGUID());
1361 return true;
1362 }
1363
1364 bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
1365 {
1366 switch (player->PlayerTalkClass->GetGossipOptionAction(gossipListId))
1367 {
1370 player->CastSpell(player, SPELL_SUMMON_FORSAKEN_BAT, true);
1371 break;
1372
1373 // Note: Blizzard messed up this OptionNpc. It sends GossipOptionNpc::None rather than GossipOptionNpc::TaxiNode,
1374 // making it useless. To keep it blizzlike, we're just sending TaxiMenu forcefully as well.
1375 case GOSSIP_ACTION_INFO_DEF + 1:
1376 player->GetSession()->SendTaxiMenu(me);
1377 break;
1378
1379 default:
1380 break;
1381 }
1382
1383 CloseGossipMenuFor(player);
1384 return true;
1385 }
1386};
1387
1389{
1393
1396
1400
1402
1405
1409
1413
1416
1417// 44821 - Forsaken Bat
1419{
1421 {
1422 Initialize();
1423 }
1424
1426 {
1428 }
1429
1430 void IsSummonedBy(WorldObject* summoner) override
1431 {
1432 if (Player* player = summoner->ToPlayer())
1433 _playerGUID = player->GetGUID();
1434
1435 me->SetDisableGravity(true);
1436 }
1437
1438 void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override
1439 {
1440 if (apply)
1441 {
1442 if (Player* player = passenger->ToPlayer())
1443 {
1444 if (player->GetQuestStatus(QUEST_ITERATING_UPON_SUCCESS) == QUEST_STATUS_INCOMPLETE)
1445 {
1446 player->KilledMonsterCredit(NPC_BAT_HANDLER_MAGGOTBREATH);
1447
1448 me->SetUninteractible(true);
1449
1450 me->SetSpeed(UnitMoveType::MOVE_RUN, 17.794235f);
1452
1454 }
1455 }
1456 }
1457 }
1458
1459 void WaypointReached(uint32 waypointId, uint32 pathId) override
1460 {
1461 switch (pathId)
1462 {
1463 case PATH_BAT_TO_LAKE:
1464 {
1465 if (waypointId == WAYPOINT_LAST_POINT_TO_LAKE)
1466 {
1467 me->SetSpeed(UnitMoveType::MOVE_RUN, 17.982668f);
1469
1471
1473 {
1475
1476 player->VehicleSpellInitialize();
1477 }
1478 }
1479 break;
1480 }
1481
1483 {
1484 if (waypointId == WAYPOINT_LAST_POINT_AROUND_LAKE)
1485 {
1487 {
1488 if (player->GetQuestStatus(QUEST_ITERATING_UPON_SUCCESS) == QUEST_STATUS_INCOMPLETE)
1490 }
1491 }
1492 break;
1493 }
1494
1495 case PATH_BAT_TO_HOME:
1496 {
1497 if (waypointId == WAYPOINT_LAST_POINT_TO_HOME)
1498 {
1501 }
1502 break;
1503 }
1504
1505 default:
1506 break;
1507 }
1508 }
1509
1510 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
1511 {
1512 if (spellInfo->Id == SPELL_GO_HOME)
1514 }
1515
1516 void DoAction(int32 param) override
1517 {
1518 switch (param)
1519 {
1520 case ACTION_GO_HOME:
1521 {
1523 {
1524 me->PauseMovement();
1525 me->GetMotionMaster()->Clear();
1526 me->SetSpeed(UnitMoveType::MOVE_RUN, 35.78791f);
1528
1530
1531 player->VehicleSpellInitialize();
1532
1533 Talk(TALK_BAT_GOING_HOME, player);
1534 }
1535 break;
1536 }
1537
1538 default:
1539 break;
1540 }
1541 }
1542
1543 void UpdateAI(uint32 diff) override
1544 {
1545 _events.Update(diff);
1546
1547 while (uint32 eventId = _events.ExecuteEvent())
1548 {
1549 switch (eventId)
1550 {
1552 {
1554 {
1556 player->CastSpell(me, SPELL_GO_HOME, true);
1557 else
1559 }
1560 break;
1561 }
1562
1563 default:
1564 break;
1565 }
1566 }
1567 }
1568
1570 {
1572 me->m_spells[1] = 0;
1573 }
1574
1576 {
1579 }
1580
1582 {
1583 me->m_spells[0] = 0;
1584 me->m_spells[1] = 0;
1585 }
1586
1587private:
1590};
1591
1593{
1595
1598
1599// 205143 - Abandoned Outhouse
1601{
1603
1604 void OnQuestAccept(Player* player, Quest const* quest) override
1605 {
1607 player->CastSpell(player, SPELL_SUMMON_DEATHSTALKER_YORICK, true);
1608 }
1609
1610 bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override
1611 {
1612 player->CastSpell(player, SPELL_SUMMON_DEATHSTALKER_YORICK, true);
1613 CloseGossipMenuFor(player);
1614 return false;
1615 }
1616};
1617
1618Position const YorickReadyPosition = { 1313.7f, 1211.99f, 58.5f, 4.564474f };
1619
1620Position const YorickDeathPosition = { 1295.52f, 1206.58f, 58.501f };
1621
1623{
1625
1628
1634
1642
1645
1648
1651
1655
1656// 44882 - Deathstalker Rane Yorick
1658{
1660
1661 void JustAppeared() override
1662 {
1665 me->SetPower(POWER_ENERGY, 100, true);
1666 }
1667
1668 void IsSummonedBy(WorldObject* summoner) override
1669 {
1670 me->SetFacingToObject(summoner);
1671
1673 }
1674
1675 void WaypointReached(uint32 waypointId, uint32 pathId) override
1676 {
1677 if (pathId == PATH_YORICK_UP && waypointId == WAYPOINT_CLOSE_TO_ARMOIRE)
1679
1680 if (pathId == PATH_YORICK_HIDE && waypointId == WAYPOINT_HIDDEN_NEXT_TO_ARMOIRE)
1681 {
1682 me->SetFacingTo(4.6425757f);
1683
1685
1686 me->SetUninteractible(true);
1687
1688 _playerSkipped = true;
1689 }
1690 }
1691
1692 void DoAction(int32 param) override
1693 {
1694 switch (param)
1695 {
1697 me->SetDisableGravity(true);
1699 break;
1700
1702 me->PauseMovement();
1703 me->GetMotionMaster()->Clear();
1704 _events.Reset();
1706 break;
1707
1708 default:
1709 break;
1710 }
1711 }
1712
1713 void UpdateAI(uint32 diff) override
1714 {
1715 TempSummon* tempSummon = me->ToTempSummon();
1716 if (!tempSummon)
1717 return;
1718
1719 _events.Update(diff);
1720
1721 if (Unit* summoner = tempSummon->GetSummonerUnit())
1722 {
1723 // Note: SummonPropertiesFlags::DespawnWhenExpired is NYI.
1724 if (!summoner->HasAura(SPELL_SUMMON_YORICK))
1726 }
1727
1728 if (!_playerSkipped)
1729 {
1730 if (Unit* summoner = tempSummon->GetSummonerUnit())
1731 {
1732 if (summoner->HasAura(SPELL_HIDDEN_IN_ARMOIRE))
1733 {
1734 _playerSkipped = true;
1735
1737 }
1738 }
1739 }
1740
1741 while (uint32 eventId = _events.ExecuteEvent())
1742 {
1743 switch (eventId)
1744 {
1746 {
1747 if (Unit* summoner = tempSummon->GetSummonerUnit())
1748 {
1750
1752 }
1753 break;
1754 }
1755
1758 break;
1759
1761 {
1762 if (Unit* summoner = tempSummon->GetSummonerUnit())
1763 {
1764 if (summoner->GetDistance2d(me) <= 5.0f && !_playerArrived)
1765 {
1767 _playerArrived = true;
1768 }
1769 else
1771 }
1772 break;
1773 }
1774
1776 {
1777 if (Unit* summoner = tempSummon->GetSummonerUnit())
1778 {
1780
1783 }
1784 break;
1785 }
1786
1787 case EVENT_RANE_HIDE:
1789 break;
1790
1792 {
1793 if (Unit* summoner = tempSummon->GetSummonerUnit())
1794 {
1795 if (!_bloodfangGUID)
1796 {
1798 {
1799 if (bloodfang->GetOwnerGUID() == summoner->GetGUID())
1800 _bloodfangGUID = bloodfang->GetGUID();
1801 }
1802 }
1803
1804 if (!_armoireGUID)
1805 {
1806 if (Creature* armoire = me->FindNearestCreature(NPC_ARMOIRE_SUMMONED, 30.0f))
1807 {
1808 if (armoire->GetOwnerGUID() == summoner->GetGUID())
1809 {
1810 _armoireGUID = armoire->GetGUID();
1811
1812 if (armoire->IsAIEnabled())
1813 armoire->GetAI()->SetGUID(me->GetGUID(), me->GetEntry());
1814 }
1815 }
1816 }
1817 }
1818
1821 break;
1822 }
1823
1828 break;
1829
1830 case EVENT_RANE_LAST_MOVE + 1:
1831 me->SetDisableGravity(false);
1832 break;
1833
1837 break;
1838
1839 case EVENT_RANE_SKIPS_PATH + 1:
1841 me->SetUninteractible(true);
1843 break;
1844
1845 default:
1846 break;
1847 }
1848 }
1849 }
1850
1851private:
1857};
1858
1860{
1863
1871
1877
1897
1903 PATH_CROWLEY_EXIT = 3590648
1905
1906// 44893 - Armoire
1908{
1909 npc_silverpine_armoire(Creature* creature) : VehicleAI(creature) { }
1910
1911 void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override
1912 {
1913 if (apply)
1914 {
1915 if (Player* player = passenger->ToPlayer())
1916 {
1917 if (player->GetQuestStatus(QUEST_WAITING_TO_EXSANGUINATE) == QUEST_STATUS_INCOMPLETE)
1919 }
1920 }
1921 else
1922 {
1924 crowley->DespawnOrUnsummon();
1925
1927 bloodfang->DespawnOrUnsummon();
1928
1930 yorick->CastSpell(nullptr, SPELL_CANCEL_SUMMON_YORICK, true);
1931
1932 me->DespawnOrUnsummon(1s);
1933 }
1934 }
1935
1936 void SetGUID(ObjectGuid const& guid, int32 id) override
1937 {
1938 switch (id)
1939 {
1941 _yorickGUID = guid;
1942 break;
1943
1945 _crowleyGUID = guid;
1946 break;
1947
1949 _bloodfangGUID = guid;
1950 break;
1951
1952 default:
1953 break;
1954 }
1955 }
1956
1957 void UpdateAI(uint32 diff) override
1958 {
1959 TempSummon* tempSummon = me->ToTempSummon();
1960 if (!tempSummon)
1961 return;
1962
1963 _events.Update(diff);
1964
1965 while (uint32 eventId = _events.ExecuteEvent())
1966 {
1967 switch (eventId)
1968 {
1970 {
1971 if (Unit* summoner = tempSummon->GetSummonerUnit())
1972 {
1973 summoner->CastSpell(summoner, SPELL_SUMMON_CROWLEY_BLOODFANG_MASTER, true);
1974
1976 }
1977 break;
1978 }
1979
1981 {
1983 {
1984 crowley->GetMotionMaster()->MovePath(PATH_CROWLEY_ENTER, false);
1985
1987 {
1988 bloodfang->GetMotionMaster()->MovePath(PATH_BLOODFANG_ENTER, false);
1989
1991 }
1992 }
1993 break;
1994 }
1995
1997 {
1999 {
2001 {
2002 crowley->SetFacingToObject(bloodfang);
2003
2004 bloodfang->SetFacingToObject(crowley);
2005
2007 }
2008 }
2009 break;
2010 }
2011
2013 {
2014 if (Unit* summoner = tempSummon->GetSummonerUnit())
2015 {
2017 {
2018 if (crowley->IsAIEnabled())
2019 crowley->AI()->Talk(TALK_CROWLEY_EXSANGUINATE_0, summoner);
2020
2022 }
2023 }
2024 break;
2025 }
2026
2028 {
2029 if (Unit* summoner = tempSummon->GetSummonerUnit())
2030 {
2031 summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_BLOODFANG, true);
2032
2034 }
2035 break;
2036 }
2037
2039 {
2040 if (Unit* summoner = tempSummon->GetSummonerUnit())
2041 {
2043 {
2044 if (bloodfang->IsAIEnabled())
2045 bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_0, summoner);
2046
2048 }
2049 }
2050 break;
2051 }
2052
2054 {
2056 {
2057 bloodfang->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
2058
2060 }
2061 break;
2062 }
2063
2065 {
2066 if (Unit* summoner = tempSummon->GetSummonerUnit())
2067 {
2068 summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_CROWLEY, true);
2069
2071 }
2072 break;
2073 }
2074
2076 {
2077 if (Unit* summoner = tempSummon->GetSummonerUnit())
2078 {
2080 {
2081 if (crowley->IsAIEnabled())
2082 crowley->AI()->Talk(TALK_CROWLEY_EXSANGUINATE_1, summoner);
2083
2085 }
2086 }
2087 break;
2088 }
2089
2091 {
2093 {
2094 crowley->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
2095
2097 }
2098 break;
2099 }
2100
2102 {
2103 if (Unit* summoner = tempSummon->GetSummonerUnit())
2104 {
2106 {
2107 if (crowley->IsAIEnabled())
2108 crowley->AI()->Talk(TALK_CROWLEY_EXSANGUINATE_2, summoner);
2109
2111 }
2112 }
2113 break;
2114 }
2115
2117 {
2119 {
2120 crowley->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
2121
2123 }
2124 break;
2125 }
2126
2128 {
2129 if (Unit* summoner = tempSummon->GetSummonerUnit())
2130 {
2131 summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_BLOODFANG, true);
2132
2134 }
2135 break;
2136 }
2137
2139 {
2140 if (Unit* summoner = tempSummon->GetSummonerUnit())
2141 {
2143 {
2144 if (bloodfang->IsAIEnabled())
2145 bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_1, summoner);
2146
2148 }
2149 }
2150 break;
2151 }
2152
2154 {
2155 if (Unit* summoner = tempSummon->GetSummonerUnit())
2156 {
2158 {
2159 if (bloodfang->IsAIEnabled())
2160 bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_2, summoner);
2161
2163 }
2164 }
2165 break;
2166 }
2167
2169 {
2170 if (Unit* summoner = tempSummon->GetSummonerUnit())
2171 {
2173 {
2174 if (bloodfang->IsAIEnabled())
2175 bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_3, summoner);
2176
2178 }
2179 }
2180 break;
2181 }
2182
2184 {
2186 {
2187 bloodfang->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
2188
2190 }
2191 break;
2192 }
2193
2195 {
2196 if (Unit* summoner = tempSummon->GetSummonerUnit())
2197 {
2198 summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_CROWLEY, true);
2199
2201 }
2202 break;
2203 }
2204
2206 {
2207 if (Unit* summoner = tempSummon->GetSummonerUnit())
2208 {
2210 {
2211 if (crowley->IsAIEnabled())
2212 crowley->AI()->Talk(TALK_CROWLEY_EXSANGUINATE_3, summoner);
2213
2215 }
2216 }
2217 break;
2218 }
2219
2221 {
2222 if (Unit* summoner = tempSummon->GetSummonerUnit())
2223 {
2224 summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_BLOODFANG, true);
2225
2227 }
2228 break;
2229 }
2230
2232 {
2233 if (Unit* summoner = tempSummon->GetSummonerUnit())
2234 {
2236 {
2237 if (bloodfang->IsAIEnabled())
2238 bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_4, summoner);
2239
2241 }
2242 }
2243 break;
2244 }
2245
2247 {
2249 {
2250 bloodfang->SetFacingTo(0.6457718f);
2251
2253 }
2254 break;
2255 }
2256
2258 {
2259 if (Unit* summoner = tempSummon->GetSummonerUnit())
2260 {
2262 {
2263 if (bloodfang->IsAIEnabled())
2264 bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_5, summoner);
2265
2267 }
2268 }
2269 break;
2270 }
2271
2273 {
2274 if (Unit* summoner = tempSummon->GetSummonerUnit())
2275 {
2277 {
2278 if (bloodfang->IsAIEnabled())
2279 bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_6, summoner);
2280
2282 }
2283 }
2284 break;
2285 }
2286
2288 {
2290 {
2291 bloodfang->HandleEmoteCommand(EMOTE_ONESHOT_YES);
2292
2294 }
2295 break;
2296 }
2297
2299 {
2301 {
2302 bloodfang->GetMotionMaster()->MovePath(PATH_BLOODFANG_NEAR_YORICK, false);
2303
2305 }
2306 break;
2307 }
2308
2310 {
2312 {
2313 bloodfang->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
2314
2316 }
2317 break;
2318 }
2319
2321 {
2322 if (Unit* summoner = tempSummon->GetSummonerUnit())
2323 {
2325 {
2326 if (bloodfang->IsAIEnabled())
2327 bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_7, summoner);
2328
2330 }
2331 }
2332 break;
2333 }
2334
2336 {
2338 {
2340 {
2341 yorick->RemoveAura(SPELL_STEALTH);
2342
2343 yorick->SetUninteractible(false);
2344
2345 bloodfang->CastSpell(yorick, SPELL_RIDE_REVERSE_CAST_EXSANGUINATE, true);
2346
2348 }
2349 }
2350 break;
2351 }
2352
2354 {
2356 {
2357 bloodfang->GetMotionMaster()->MovePath(PATH_BLOODFANG_WITH_YORICK, false);
2358
2360 }
2361 break;
2362 }
2363
2365 {
2366 if (Unit* summoner = tempSummon->GetSummonerUnit())
2367 {
2369 {
2370 bloodfang->SetFacingTo(3.054326f);
2371
2372 if (bloodfang->IsAIEnabled())
2373 bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_8, summoner);
2374
2376 }
2377 }
2378 break;
2379 }
2380
2382 {
2383 if (Unit* summoner = tempSummon->GetSummonerUnit())
2384 {
2386 {
2387 if (yorick->IsAIEnabled())
2388 yorick->AI()->Talk(TALK_YORICK_EXSANGUINATE_DEATH, summoner);
2389
2391 }
2392 }
2393 break;
2394 }
2395
2397 {
2398 if (Unit* summoner = tempSummon->GetSummonerUnit())
2399 {
2401 {
2403 {
2404 bloodfang->CastSpell(yorick, SPELL_EJECT_PASSENGER_01, false);
2405
2406 if (yorick->IsAIEnabled())
2407 yorick->AI()->DoAction(ACTION_RANE_JUMP_DEATH);
2408
2409 if (bloodfang->IsAIEnabled())
2410 bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_9, summoner);
2411
2413 }
2414 }
2415 }
2416 break;
2417 }
2418
2420 {
2422 {
2423 bloodfang->SetFacingTo(0.0f);
2424
2426 }
2427 break;
2428 }
2429
2431 {
2432 if (Unit* summoner = tempSummon->GetSummonerUnit())
2433 {
2435 {
2436 if (bloodfang->IsAIEnabled())
2437 bloodfang->AI()->Talk(TALK_BLOODFANG_EXSANGUINATE_10, summoner);
2438
2440 }
2441 }
2442 break;
2443 }
2444
2446 {
2448 {
2449 bloodfang->HandleEmoteCommand(EMOTE_ONESHOT_TALK);
2450
2452 }
2453 break;
2454 }
2455
2457 {
2458 if (Unit* summoner = tempSummon->GetSummonerUnit())
2459 {
2460 summoner->CastSpell(nullptr, SPELL_ARMOIRE_CAMERA_ON_CROWLEY, true);
2461
2463 {
2464 bloodfang->SetWalk(false);
2465 bloodfang->GetMotionMaster()->MovePath(PATH_BLOODFANG_EXIT, false);
2466
2468 }
2469 }
2470 break;
2471 }
2472
2474 {
2476 {
2477 crowley->GetMotionMaster()->MovePath(PATH_CROWLEY_EXIT, false);
2478
2480 }
2481 break;
2482 }
2483
2485 {
2486 if (Unit* summoner = tempSummon->GetSummonerUnit())
2487 {
2489 crowley->CastSpell(summoner, SPELL_KILL_CREDIT_YORICK, false);
2490
2492 yorick->CastSpell(summoner, SPELL_CANCEL_SUMMON_YORICK, true);
2493
2494 summoner->GetMotionMaster()->Clear();
2495
2496 summoner->RemoveAura(SPELL_HIDE_IN_ARMOIRE);
2497
2498 summoner->ExitVehicle();
2499 }
2500 break;
2501 }
2502
2503 default:
2504 break;
2505 }
2506 }
2507 }
2508
2509private:
2514};
2515
2517{
2520
2521// 44883 - Lord Darius Crowley
2523{
2525
2526 void JustAppeared() override
2527 {
2529 }
2530
2531 void IsSummonedBy(WorldObject* /*summoner*/) override
2532 {
2533 if (Creature* armoire = me->FindNearestCreature(NPC_ARMOIRE_SUMMONED, 100.0f))
2534 {
2535 if (armoire->IsAIEnabled())
2536 armoire->GetAI()->SetGUID(me->GetGUID(), me->GetEntry());
2537 }
2538 }
2539
2540 void WaypointReached(uint32 waypointId, uint32 pathId) override
2541 {
2542 if (pathId == PATH_CROWLEY_EXIT && waypointId == WAYPOINT_ON_CROWLEY_DESPAWN)
2544 }
2545};
2546
2548{
2551
2552// 44884 - Packleader Ivar Bloodfang
2554{
2556
2557 void JustAppeared() override
2558 {
2560 }
2561
2562 void IsSummonedBy(WorldObject* /*summoner*/) override
2563 {
2564 if (Creature* armoire = me->FindNearestCreature(NPC_ARMOIRE_SUMMONED, 30.0f))
2565 {
2566 if (armoire->IsAIEnabled())
2567 armoire->GetAI()->SetGUID(me->GetGUID(), me->GetEntry());
2568 }
2569 }
2570
2571 void WaypointReached(uint32 waypointId, uint32 pathId) override
2572 {
2573 if (pathId == PATH_BLOODFANG_EXIT && waypointId == WAYPOINT_ON_BLOODFANG_DESPAWN)
2575 }
2576};
2577
2579{
2581
2586
2602 TALK_GORGAR_5 = 5
2604
2605// 45498 - "Salty" Rocka
2607{
2609
2610 void JustAppeared() override
2611 {
2613 }
2614
2615 void Reset() override
2616 {
2618 _events.Reset();
2619 }
2620
2621 void MoveInLineOfSight(Unit* who) override
2622 {
2623 if (who->GetTypeId() == TYPEID_PLAYER && who->GetDistance2d(me) < 20.0f)
2625 }
2626
2627 void UpdateAI(uint32 diff) override
2628 {
2629 _events.Update(diff);
2630
2631 while (uint32 eventId = _events.ExecuteEvent())
2632 {
2633 switch (eventId)
2634 {
2637 return;
2641 break;
2642
2644 _events.ScheduleEvent(EVENT_ROCKA_TALK + (urand(0, 4) * 10), 750ms);
2645 break;
2646
2647 case EVENT_ROCKA_TALK:
2650 break;
2651
2652 case EVENT_ROCKA_TALK + 1:
2653 {
2655 {
2656 if (gorgar->IsAIEnabled())
2657 gorgar->AI()->Talk(TALK_GORGAR_0);
2658 }
2660 break;
2661 }
2662
2663 case EVENT_ROCKA_TALK + 2:
2665 break;
2666
2667 case EVENT_ROCKA_TALK + 10:
2670 break;
2671
2672 case EVENT_ROCKA_TALK + 11:
2673 {
2675 {
2676 if (gorgar->IsAIEnabled())
2677 gorgar->AI()->Talk(TALK_GORGAR_1);
2678 }
2680 break;
2681 }
2682
2683 case EVENT_ROCKA_TALK + 12:
2685 break;
2686
2687 case EVENT_ROCKA_TALK + 20:
2690 break;
2691
2692 case EVENT_ROCKA_TALK + 21:
2693 {
2695 {
2696 if (gorgar->IsAIEnabled())
2697 gorgar->AI()->Talk(TALK_GORGAR_2);
2698 }
2700 break;
2701 }
2702
2703 case EVENT_ROCKA_TALK + 22:
2705 break;
2706
2707 case EVENT_ROCKA_TALK + 30:
2710 break;
2711
2712 case EVENT_ROCKA_TALK + 31:
2713 {
2715 {
2716 if (gorgar->IsAIEnabled())
2717 gorgar->AI()->Talk(TALK_GORGAR_3);
2718 }
2720 break;
2721 }
2722
2723 case EVENT_ROCKA_TALK + 32:
2725 break;
2726
2727 case EVENT_ROCKA_TALK + 40:
2730 break;
2731
2732 case EVENT_ROCKA_TALK + 41:
2733 {
2735 {
2736 if (gorgar->IsAIEnabled())
2737 gorgar->AI()->Talk(TALK_GORGAR_4);
2738 }
2740 break;
2741 }
2742
2743 case EVENT_ROCKA_TALK + 42:
2745 break;
2746
2748 Reset();
2749 break;
2750
2751 default:
2752 break;
2753 }
2754 }
2755 }
2756
2758 {
2759 if (!_gorgarGUID)
2760 {
2761 if (Creature* gorgar = me->FindNearestCreature(NPC_SALTY_GORGAR, 50.0f))
2762 _gorgarGUID = gorgar->GetGUID();
2763 }
2764 }
2765
2766private:
2770};
2771
2773{
2777
2780
2784
2785// 6222 - Forsaken Rear Guard
2787{
2788public:
2789 at_silverpine_forsaken_rear_guard() : AreaTriggerScript("at_silverpine_forsaken_rear_guard") { }
2790
2791 bool OnTrigger(Player* player, AreaTriggerEntry const* /*at*/) override
2792 {
2793 if (player->IsAlive())
2794 {
2797 {
2798 if (Creature* hatchet = player->FindNearestCreature(NPC_ADMIRAL_HATCHET, 50.0f))
2799 {
2800 if (hatchet->IsAIEnabled())
2801 hatchet->AI()->DoAction(ACTION_HATCHET_START_CONVERSATION);
2802 }
2803 }
2805 {
2806 if (Creature* wormcrud = player->FindNearestCreature(NPC_APOTHECARY_WORMCRUD, 50.0f))
2807 {
2808 if (wormcrud->IsAIEnabled())
2809 wormcrud->AI()->DoAction(ACTION_WORMCRUD_START_CONVERSATION);
2810 }
2811 }
2812 }
2813
2814 return true;
2815 }
2816};
2817
2819{
2821
2826
2830 TALK_WORMCRUD_0 = 0
2832
2833// 44912 - Apothecary Wormcrud
2835{
2837
2838 void JustAppeared() override
2839 {
2841 }
2842
2843 void Reset() override
2844 {
2845 _events.Reset();
2846
2848 }
2849
2850 void DoAction(int32 param) override
2851 {
2853 {
2855 return;
2856
2858
2861 }
2862 }
2863
2864 void UpdateAI(uint32 diff) override
2865 {
2866 _events.Update(diff);
2867
2868 while (uint32 eventId = _events.ExecuteEvent())
2869 {
2870 switch (eventId)
2871 {
2873 {
2875 {
2876 if (orcsea1->IsAIEnabled())
2877 orcsea1->AI()->Talk(TALK_ORCSEA_0);
2878 }
2880 break;
2881 }
2882
2883 case EVENT_WORMCRUD_TALK + 1:
2884 {
2886 {
2887 if (orcsea2->IsAIEnabled())
2888 orcsea2->AI()->Talk(TALK_ORCSEA_1);
2889 }
2891 break;
2892 }
2893
2894 case EVENT_WORMCRUD_TALK + 2:
2895 {
2897 {
2898 if (orcsea3->IsAIEnabled())
2899 orcsea3->AI()->Talk(TALK_ORCSEA_2);
2900 }
2902 break;
2903 }
2904
2905 case EVENT_WORMCRUD_TALK + 3:
2907 break;
2908
2910 Reset();
2911 break;
2912
2913 default:
2914 break;
2915 }
2916 }
2917 }
2918
2920 {
2921 std::vector<Creature*> orcSeaDogList;
2923
2924 if (orcSeaDogList.size() < 3)
2925 return;
2926
2927 for (uint32 i = 0; i < orcSeaDogList.size(); i++)
2928 _drunkenOrcSeaDog[i] = orcSeaDogList[i]->GetGUID();
2929 }
2930
2931private:
2933 std::array<ObjectGuid, 3> _drunkenOrcSeaDog;
2935};
2936
2938{
2940
2942
2946
2950
2956
2957 ANIMKIT_TOROK = 594
2959
2960// 44916 - Admiral Hatchet
2962{
2964
2965 void JustAppeared() override
2966 {
2967 CheckForTorok();
2968 }
2969
2970 void OnQuestAccept(Player* player, Quest const* quest) override
2971 {
2972 if (quest->GetQuestId() == QUEST_STEEL_THUNDER)
2973 player->CastSpell(player, SPELL_SUMMON_ORC_SEA_PUP);
2974 }
2975
2976 void OnQuestReward(Player* player, Quest const* quest, LootItemType /*type*/, uint32 /*opt*/) override
2977 {
2978 if (quest->GetQuestId() == QUEST_STEEL_THUNDER)
2979 player->CastSpell(player, SPELL_SEA_PUP_TRIGGER, true);
2980 else if (quest->GetQuestId() == QUEST_LOST_IN_THE_DARKNESS)
2982 }
2983
2984 bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override
2985 {
2987 player->CastSpell(player, SPELL_SUMMON_ORC_SEA_PUP);
2988
2989 CloseGossipMenuFor(player);
2990 return false;
2991 }
2992
2993 void Reset() override
2994 {
2995 _events.Reset();
2997 }
2998
2999 void DoAction(int32 param) override
3000 {
3002 {
3004 return;
3005
3007
3010 }
3011 }
3012
3013 void UpdateAI(uint32 diff) override
3014 {
3015 _events.Update(diff);
3016
3017 while (uint32 eventId = _events.ExecuteEvent())
3018 {
3019 switch (eventId)
3020 {
3021 case EVENT_HATCHET_TALK:
3024 break;
3025
3026 case EVENT_HATCHET_TALK + 1:
3027 {
3029 {
3030 if (torok->IsAIEnabled())
3031 torok->AI()->Talk(TALK_TOROK_0);
3032 }
3034 break;
3035 }
3036
3037 case EVENT_HATCHET_TALK + 2:
3040 break;
3041
3042 case EVENT_HATCHET_TALK + 3:
3043 {
3045 {
3046 torok->PlayOneShotAnimKitId(ANIMKIT_TOROK);
3047
3048 if (torok->IsAIEnabled())
3049 torok->AI()->Talk(TALK_TOROK_1);
3050 }
3051 break;
3052 }
3053
3055 Reset();
3056 break;
3057
3058 default:
3059 break;
3060 }
3061 }
3062 }
3063
3065 {
3066 if (!_torokGUID)
3067 {
3068 if (Creature* torok = me->FindNearestCreature(NPC_WARLORD_TOROK, 30.0f))
3069 _torokGUID = torok->GetGUID();
3070 }
3071 }
3072
3073private:
3077};
3078
3080{
3085 SPELL_SICK = 83885,
3086
3090
3096
3097// 44913 - Orc Sea Dog
3099{
3101
3102 void JustAppeared() override
3103 {
3105 {
3110 break;
3113 break;
3117 break;
3118 default:
3119 break;
3120 }
3121 }
3122
3123 void UpdateAI(uint32 diff) override
3124 {
3125 _events.Update(diff);
3126
3127 while (uint32 eventId = _events.ExecuteEvent())
3128 {
3129 switch (eventId)
3130 {
3133 _events.Repeat(6s, 20s);
3134 break;
3135 case EVENT_SEA_DOG_ROAM:
3137 break;
3138 default:
3139 break;
3140 }
3141 }
3142 }
3143
3144private:
3146};
3147
3149{
3151
3152 void JustAppeared() override
3153 {
3155
3157 }
3158
3159 void UpdateAI(uint32 diff) override
3160 {
3161 _events.Update(diff);
3162
3163 while (uint32 eventId = _events.ExecuteEvent())
3164 {
3165 switch (eventId)
3166 {
3168 DoCastSelf(SPELL_SICK, false);
3169 _events.Repeat(25s, 50s);
3170 break;
3171 default:
3172 break;
3173 }
3174 }
3175 }
3176
3177private:
3179};
3180
3181// Note: we're not using the generic spell for this one because Orc Sea Pup is unsummoned 3s later.
3182// 83840 - Despawn All Summons
3184{
3186 {
3187 if (Unit* caster = GetCaster())
3188 {
3189 Creature* target = GetHitCreature();
3190
3191 if (target->GetOwner() == caster)
3192 target->DespawnOrUnsummon(3s);
3193 }
3194 }
3195
3196 void Register() override
3197 {
3199 }
3200};
3201
3203{
3205
3210
3215
3220
3221// 44914 - Orc Sea Pup
3223{
3225
3226 void JustAppeared() override
3227 {
3229 }
3230
3231 void IsSummonedBy(WorldObject* summoner) override
3232 {
3233 if (Player* player = summoner->ToPlayer())
3234 {
3236
3237 // Note: SummonPropertiesFlags::JoinSummonerSpawnGroup is NYI.
3238 me->GetMotionMaster()->MoveFollow(player, 2.0f, float(M_PI / 2.0f));
3239
3240 if (player->GetQuestStatus(QUEST_STEEL_THUNDER) == QUEST_STATUS_INCOMPLETE)
3241 {
3245
3246 int c = player->GetReqKillOrCastCurrentCount(QUEST_STEEL_THUNDER, NPC_ORC_CRATE);
3247
3248 for (int i = 0; i < c; i++)
3250 }
3251 }
3252 }
3253
3254 void PassengerBoarded(Unit* passenger, int8 seatId, bool apply) override
3255 {
3256 TempSummon* tempSummon = me->ToTempSummon();
3257 if (!tempSummon)
3258 return;
3259
3260 Creature* passengerCreature = passenger->ToCreature();
3261 if (!passengerCreature)
3262 return;
3263
3264 if (passenger->GetEntry() != NPC_ORC_CRATE)
3265 return;
3266
3267 if (apply)
3268 {
3269 if (_isJustSummoned)
3270 return;
3271
3272 if (Unit* summoner = tempSummon->GetSummonerUnit())
3273 Talk(seatId + 1, summoner);
3274 }
3275 else
3276 passengerCreature->DespawnOrUnsummon(3s);
3277 }
3278
3279 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
3280 {
3281 TempSummon* tempSummon = me->ToTempSummon();
3282 if (!tempSummon)
3283 return;
3284
3285 switch (spellInfo->Id)
3286 {
3288 {
3289 if (Unit* summoner = tempSummon->GetSummonerUnit())
3290 {
3292
3293 summoner->CastSpell(nullptr, SPELL_DESPAWN_ALL_SUMMONS_STEEL_THUNDER, true);
3294
3296 }
3297 break;
3298 }
3299
3302 break;
3303 default:
3304 break;
3305 }
3306 }
3307
3308 void UpdateAI(uint32 diff) override
3309 {
3310 TempSummon* tempSummon = me->ToTempSummon();
3311 if (!tempSummon)
3312 return;
3313
3314 _events.Update(diff);
3315
3316 while (uint32 eventId = _events.ExecuteEvent())
3317 {
3318 switch (eventId)
3319 {
3321 if (Unit* summoner = tempSummon->GetSummonerUnit())
3322 Talk(TALK_ORC_PUP_SUMMONED, summoner);
3323 break;
3324
3325 case EVENT_ORC_PUP_TALK:
3326 {
3327 if (Vehicle* vehicle = me->GetVehicleKit())
3328 {
3329 if (vehicle->IsVehicleInUse())
3330 {
3331 if (Unit* summoner = tempSummon->GetSummonerUnit())
3332 Talk(TALK_ORC_PUP_WORN_OFF, summoner);
3333 }
3334 }
3336 break;
3337 }
3338
3340 _isJustSummoned = false;
3341 break;
3342
3347 break;
3348
3349 default:
3350 break;
3351 }
3352 }
3353 }
3354
3355private:
3358};
3359
3361{
3362 NPC_ORC_SEA_PUP = 44914
3364
3365// 44915 - Orc Crate
3367{
3369
3370 void IsSummonedBy(WorldObject* summoner) override
3371 {
3372 if (summoner->GetEntry() == NPC_ORC_SEA_PUP)
3373 {
3374 me->SetUninteractible(true);
3375
3376 me->EnterVehicle(summoner->ToUnit());
3377 }
3378 }
3379};
3380
3382{
3385
3386// 83838 - Pick Up Orc Crate
3388{
3389 bool Validate(SpellInfo const* /*spellInfi*/) override
3390 {
3391 return ValidateSpellInfo
3392 ({
3395 });
3396 }
3397
3399 {
3402 }
3403
3404 void Register() override
3405 {
3407 }
3408};
3409
3411{
3413
3415 SPELL_BONK = 80146,
3421
3429
3431
3434
3437
3438// 44367 - Forest Ettin
3440{
3442
3443 void JustAppeared() override
3444 {
3446 }
3447
3448 void Reset() override
3449 {
3450 _events.Reset();
3451
3452 _isGrabbingBushChicken = false;
3453
3454 me->ResumeMovement();
3455
3458 }
3459
3460 void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override
3461 {
3462 if (spellInfo->Id == SPELL_RELEASE_BUSH_CHICKEN)
3463 _playerGUID = caster->GetGUID();
3464 }
3465
3466 void SetGUID(ObjectGuid const& guid, int32 id) override
3467 {
3468 switch (id)
3469 {
3471 _chickenGUID = guid;
3472 break;
3473 default:
3474 break;
3475 }
3476 }
3477
3478 void PassengerBoarded(Unit* /*passenger*/, int8 seatId, bool apply) override
3479 {
3481 return;
3482
3483 if (apply)
3484 {
3485 if (seatId == SEAT_ETTIN_ARM)
3487 else if (seatId == SEAT_ETTIN_MOUTH)
3489 }
3490 }
3491
3492 void DoAction(int32 param) override
3493 {
3494 switch (param)
3495 {
3497 {
3498 if (Creature* mutantBushChicken = ObjectAccessor::GetCreature(*me, _chickenGUID))
3499 {
3500 me->PauseMovement();
3501
3502 me->SetFacingToObject(mutantBushChicken);
3503
3505 }
3506 break;
3507 }
3508
3509 default:
3510 break;
3511 }
3512 }
3513
3514 void DamageTaken(Unit* /*attacker*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* spellInfo /*= nullptr*/) override
3515 {
3516 if (!spellInfo)
3517 return;
3518
3519 // HACKFIX: according to BasePoints damage is around 90k, which is wrong. On retail, it deals 80% of its health points only.
3520 // Also, Mutant Bush Chicken is summoned as not player-controlled (not blue-taped), though it uses the same summonProperties's
3521 // Control and Slot as some other summoning spells from this zone.
3522 if (spellInfo->Id == SPELL_BUSH_EXPLOSION)
3523 damage = 0;
3524 }
3525
3526 void JustEngagedWith(Unit* /*who*/) override
3527 {
3530 }
3531
3532 void UpdateAI(uint32 diff) override
3533 {
3534 _events.Update(diff);
3535
3536 while (uint32 eventId = _events.ExecuteEvent())
3537 {
3538 switch (eventId)
3539 {
3540 case EVENT_BONK:
3542 _events.Repeat(9s, 11s);
3543 break;
3544
3545 case EVENT_LOG_SMASH:
3547 _events.Repeat(15s, 16s);
3548 break;
3549
3551 {
3552 if (Creature* mutantBushChicken = ObjectAccessor::GetCreature(*me, _chickenGUID))
3553 {
3555
3556 me->CastSpell(mutantBushChicken, SPELL_RIDE_REVERSE_CAST_ITS_POISONOUS, true);
3557
3559 }
3560 break;
3561 }
3562
3564 me->ResumeMovement();
3566 break;
3567
3569 {
3570 if (Creature* mutantBushChicken = ObjectAccessor::GetCreature(*me, _chickenGUID))
3571 {
3572 mutantBushChicken->CastSpell(me, SPELL_ETTIN_MOUTH, true);
3573
3575 {
3577 mutantBushChicken->PlayDirectSound(SOUND_CHICKEN_MOUNT_WOUND, player);
3578 }
3579 }
3580 break;
3581 }
3582
3584 {
3585 if (Creature* mutantBushChicken = ObjectAccessor::GetCreature(*me, _chickenGUID))
3586 {
3587 mutantBushChicken->CastSpell(me, SPELL_BUSH_EXPLOSION, true);
3588
3590 AttackStart(player);
3591 }
3592 break;
3593 }
3594
3595 case EVENT_RESET:
3596 Reset();
3597 break;
3598
3599 default:
3600 break;
3601 }
3602 }
3603
3604 if (!UpdateVictim())
3605 return;
3606 }
3607
3608private:
3613};
3614
3616{
3618
3620
3623
3624// 44935 - Mutant Bush Chicken
3626{
3628
3629 void JustAppeared() override
3630 {
3633 }
3634
3635 void IsSummonedBy(WorldObject* summoner) override
3636 {
3637 if (Player* player = summoner->ToPlayer())
3638 {
3641 }
3642 }
3643
3644 void MovementInform(uint32 type, uint32 id) override
3645 {
3646 if (type != POINT_MOTION_TYPE)
3647 return;
3648
3649 if (id == POINT_NEAR_FOREST_ETTIN)
3650 {
3652 {
3653 if (forestEttin->IsAIEnabled())
3654 forestEttin->AI()->DoAction(ACTION_NOTICE_CHICKEN);
3655 }
3656 }
3657 }
3658
3659 void UpdateAI(uint32 diff) override
3660 {
3661 TempSummon* tempSummon = me->ToTempSummon();
3662 if (!tempSummon)
3663 return;
3664
3665 if (Unit* summoner = tempSummon->GetSummonerUnit())
3666 {
3667 // Note: SummonPropertiesFlags::DespawnOnSummonerLogout is NYI.
3668 if (!summoner->IsInWorld())
3670 }
3671
3672 _events.Update(diff);
3673
3674 while (uint32 eventId = _events.ExecuteEvent())
3675 {
3676 switch (eventId)
3677 {
3680 me->GetMotionMaster()->MovePoint(POINT_NEAR_FOREST_ETTIN, forestEttin->GetPosition(), false);
3681 break;
3682 default:
3683 break;
3684 }
3685 }
3686 }
3687
3688 void CheckForForestEttin(Unit* forestEttin)
3689 {
3690 _forestEttinGUID = forestEttin->GetGUID();
3691
3692 me->SetFacingToObject(forestEttin);
3693
3695 }
3696
3697private:
3700};
3701
3702// 83902 - Release Diseased Mutant Bush Chicken
3704{
3705 void HandleHit(SpellEffIndex /*effIndex*/)
3706 {
3707 Unit* target = GetHitUnit();
3708
3709 if (Unit* caster = GetCaster())
3710 {
3711 std::vector<Creature*> chickens;
3712 caster->GetCreatureListWithEntryInGrid(chickens, NPC_MUTANT_BUSH_CHICKEN, 5.0f);
3713 for (Creature* mutantBushChicken : chickens)
3714 {
3715 if (mutantBushChicken->GetOwner() != caster)
3716 continue;
3717
3718 if (target->IsAIEnabled())
3719 target->GetAI()->SetGUID(mutantBushChicken->GetGUID(), NPC_MUTANT_BUSH_CHICKEN);
3720
3721 if (npc_silverpine_mutant_bush_chicken* mutantBushChickenAI = CAST_AI(npc_silverpine_mutant_bush_chicken, mutantBushChicken->AI()))
3722 mutantBushChickenAI->CheckForForestEttin(target);
3723 }
3724 }
3725 }
3726
3727 void Register() override
3728 {
3730 }
3731};
3732
3734{
3738
3739// 44941 - Webbed Victim
3741{
3743
3744 void JustAppeared() override
3745 {
3747 }
3748
3749 void JustDied(Unit* killer) override
3750 {
3751 if (Player* player = killer->ToPlayer())
3752 {
3753 if (player->GetQuestStatus(QUEST_LOST_IN_THE_DARKNESS) == QUEST_STATUS_INCOMPLETE)
3755 }
3756 }
3757};
3758
3760{
3764
3768 DATA_RANDOM_3 = 3
3770
3771// 83919 - Free Webbed Victim
3773{
3774 void HandleHit(SpellEffIndex /*effIndex*/)
3775 {
3776 if (Unit* caster = GetCaster())
3777 {
3778 uint32 randomCreature = 0;
3779
3780 /*
3781 * Note: this spell is always cast when there's nothing in the web or there's a foe. Also,
3782 * there are 4 serverside spells for this, but we're unable to know which one does what exactly:
3783 * 83922 - (Serverside/Non-DB2) Free Webbed Victim, 83923 - (Serverside/Non-DB2) Free Webbed Victim,
3784 * 83924 - (Serverside/Non-DB2) Free Webbed Victim, 83925 - (Serverside/Non-DB2) Free Webbed Victim.
3785 * It is safe to assume that each summons one of the three foes, and the other summons nothing.
3786 * 83927 - Free Webbed Victim summons orcs. We could try finding summonProperties, but it is hard.
3787 */
3788
3790 {
3791 case DATA_RANDOM_0:
3792 randomCreature = NPC_BLOODFANG_SCAVENGER;
3793 break;
3794 case DATA_RANDOM_1:
3795 randomCreature = NPC_RABID_DOG;
3796 break;
3797 case DATA_RANDOM_2:
3798 randomCreature = NPC_GIANT_RABBID_BEAR;
3799 break;
3800 case DATA_RANDOM_3:
3801 randomCreature = 0;
3802 break;
3803 default:
3804 break;
3805 }
3806
3807 if (randomCreature != 0)
3808 {
3809 if (Creature* randomAggresiveCreature = caster->SummonCreature(randomCreature, GetHitUnit()->GetPosition()))
3810 randomAggresiveCreature->Attack(caster, true);
3811 }
3812 }
3813 }
3814
3815 void Register() override
3816 {
3818 }
3819};
3820
3822{
3824
3826
3830
3833
3834// 44942 - Orc Sea Dog
3836{
3838
3839 void JustAppeared() override
3840 {
3843 me->SetPower(POWER_ENERGY, 100, true);
3844
3845 // Note: SummonPropertiesFlags::HelpWhenSummonedInCombat is NYI.
3847 }
3848
3849 void IsSummonedBy(WorldObject* summoner) override
3850 {
3851 if (Player* player = summoner->ToPlayer())
3852 {
3853 player->KilledMonsterCredit(NPC_ORC_SEA_DOG);
3854
3855 // Note: SummonPropertiesFlags::JoinSummonerSpawnGroup is NYI. They should be faned around the back of the player depending on how many summons they have (Pets and Guardians included).
3856 me->GetMotionMaster()->MoveFollow(player, 5.0f, frand(1.57f, 4.71f));
3857
3860 }
3861 }
3862
3863 void Reset() override
3864 {
3866 }
3867
3868 void JustEngagedWith(Unit* /*who*/) override
3869 {
3871 }
3872
3873 void UpdateAI(uint32 diff) override
3874 {
3875 TempSummon* tempSummon = me->ToTempSummon();
3876 if (!tempSummon)
3877 return;
3878
3879 if (Unit* summoner = tempSummon->GetSummonerUnit())
3880 {
3881 // Note: SummonPropertiesFlags::DespawnOnSummonerDeath and SummonPropertiesFlags::DespawnOnSummonerLogout are NYI.
3882 if (!summoner->IsAlive() || !summoner->IsInWorld())
3884 }
3885
3886 _events.Update(diff);
3887
3888 while (uint32 eventId = _events.ExecuteEvent())
3889 {
3890 switch (eventId)
3891 {
3893 if (Unit* summoner = tempSummon->GetSummonerUnit())
3894 Talk(TALK_WEBBEB_ORC_FREED, summoner);
3895 break;
3896
3899 _events.Repeat(6s, 8s);
3900 break;
3901
3902 default:
3903 break;
3904 }
3905 }
3906
3907 if (!UpdateVictim())
3908 return;
3909 }
3910
3911private:
3913};
3914
3916{
3918
3922
3927
3932
3933// 44906 - Skitterweb Matriarch
3935{
3937
3938 void JustAppeared() override
3939 {
3940 me->SetDisableGravity(true);
3941 me->SetHover(true);
3942
3944
3946
3947 me->CastSpell(nullptr, SPELL_SKITTERWEB, true);
3948 }
3949
3950 void Reset() override
3951 {
3952 _events.Reset();
3953 }
3954
3955 void JustReachedHome() override
3956 {
3957 me->SetDisableGravity(true);
3958 me->SetHover(true);
3959
3960 me->CastSpell(nullptr, SPELL_SKITTERWEB, true);
3961
3963
3965
3967 }
3968
3969 void JustSummoned(Creature* summon) override
3970 {
3971 if (Unit* victim = me->GetVictim())
3972 summon->Attack(victim, true);
3973 }
3974
3975 void JustEngagedWith(Unit* who) override
3976 {
3977 _attackerGUID = who->GetGUID();
3978
3979 me->AttackStop();
3980
3983
3985 }
3986
3987 void UpdateAI(uint32 diff) override
3988 {
3989 _events.Update(diff);
3990
3991 while (uint32 eventId = _events.ExecuteEvent())
3992 {
3993 switch (eventId)
3994 {
3996 me->SetDisableGravity(false);
3997 me->SetHover(false);
4000 break;
4001
4002 case EVENT_MATRIARCH_AGGRO + 1:
4004 me->CastStop();
4007 break;
4008
4009 case EVENT_MATRIARCH_AGGRO + 2:
4010 if (Unit* attacker = ObjectAccessor::GetUnit(*me, _attackerGUID))
4011 ScheduleCombatEvents(attacker);
4012 break;
4013
4015 me->SetFacingTo(0.820305f);
4018 break;
4019
4022 break;
4023
4024 case EVENT_VENOM_SPLASH:
4026 _events.Repeat(15s, 18s);
4027 break;
4028
4029 default:
4030 break;
4031 }
4032 }
4033
4034 if (!UpdateVictim())
4035 return;
4036 }
4037
4039 {
4040 me->Attack(who, true);
4041
4044 }
4045
4046private:
4050};
4051
4053{
4056
4057// 83979 - Bond of the Val'kyr
4059{
4060 bool Validate(SpellInfo const* /*spellInfo*/) override
4061 {
4063 }
4064
4065 void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
4066 {
4068 }
4069
4070 void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
4071 {
4073 }
4074
4075 void Register() override
4076 {
4079 }
4080};
4081
4082Position const AgathaBackFrontyardPos = { 982.57f, 671.04f, 77.298f };
4083
4085{
4087
4099
4101
4106
4112
4114
4117
4120
4121// 44951 - Agatha
4123{
4125
4126 void JustAppeared() override
4127 {
4128 // Note: SummonPropertiesFlags::HelpWhenSummonedInCombat is NYI.
4130
4132
4133 // Note: SummonPropertiesFlags::JoinSummonerSpawnGroup is NYI.
4134 me->GetMotionMaster()->Clear();
4135 me->GetMotionMaster()->MoveFollow(me->GetOwner(), 3.0f, float(M_PI / 2.0f));
4136
4138 }
4139
4140 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
4141 {
4142 TempSummon* tempSummon = me->ToTempSummon();
4143 if (!tempSummon)
4144 return;
4145
4146 switch (spellInfo->Id)
4147 {
4149 {
4150 if (_isSceneStarted)
4151 return;
4152
4153 if (Unit* summoner = tempSummon->GetSummonerUnit())
4154 Talk(TALK_AGATHA_BROADCAST, summoner);
4155 break;
4156 }
4157
4159 {
4160 if (!_isSceneStarted)
4162 break;
4163 }
4164
4166 if (Unit* summoner = tempSummon->GetSummonerUnit())
4167 me->CastSpell(summoner, SPELL_ARMORE_CAMERA_1, true);
4168 break;
4169
4172 break;
4173
4176 break;
4177
4180 break;
4181
4182 default:
4183 break;
4184 }
4185 }
4186
4187 void WaypointReached(uint32 waypointId, uint32 pathId) override
4188 {
4189 if (pathId == PATH_AGATHA_TO_FORSAKEN)
4190 {
4191 if (waypointId == WAYPOINT_SPEED_UP)
4192 me->SetSpeed(MOVE_RUN, 15.880999f);
4193 else if (waypointId == WAYPOINT_ARRIVED_TO_FORSAKEN)
4195 }
4196 }
4197
4198 void Reset() override
4199 {
4202
4203 // Note: SummonPropertiesFlags::JoinSummonerSpawnGroup is NYI.
4204 me->GetMotionMaster()->Clear();
4205 me->GetMotionMaster()->MoveFollow(me->GetOwner(), 3.0f, float(M_PI / 2.0f));
4206 }
4207
4208 void JustEngagedWith(Unit* /*who*/) override
4209 {
4212 }
4213
4214 void UpdateAI(uint32 diff) override
4215 {
4216 TempSummon* tempSummon = me->ToTempSummon();
4217 if (!tempSummon)
4218 return;
4219
4220 // Note: SummonPropertiesFlags::DespawnOnSummonerDeath, SummonPropertiesFlags::DespawnOnSummonerLogout and SummonPropertiesFlags::DespawnWhenExpired are NYI.
4221 if (Unit* summoner = tempSummon->GetSummonerUnit())
4222 {
4223 if (!summoner->IsAlive() || !summoner->IsInWorld() || !summoner->HasAura(SPELL_SUMMON_AGATHA_FENRIS))
4225 }
4226
4227 _events.Update(diff);
4228
4229 while (uint32 eventId = _events.ExecuteEvent())
4230 {
4231 switch (eventId)
4232 {
4234 {
4235 if (Unit* summoner = tempSummon->GetSummonerUnit())
4236 {
4237 if (!me->HasUnitState(UNIT_STATE_CASTING) && summoner->GetHealthPct() < 75.0f)
4238 me->CastSpell(summoner, SPELL_UNHOLY_DARKNESS, false);
4239
4240 _events.Repeat(1s);
4241 }
4242 break;
4243 }
4244
4245 case EVENT_DOOMHOWL:
4247 _events.Repeat(14s, 18s);
4248 break;
4249
4250 case EVENT_UNHOLY_SMITE:
4252 _events.Repeat(4s, 6s);
4253 break;
4254
4255 case EVENT_FLEE_FROM_FENRIS + 1:
4256 {
4257 if (Unit* summoner = tempSummon->GetSummonerUnit())
4258 {
4259 me->SetFacingTo(3.159046f);
4260
4261 Talk(TALK_AGATHA_POST_EVENT1, summoner);
4262 }
4263 break;
4264 }
4265
4266 case EVENT_FLEE_FROM_FENRIS + 2:
4267 {
4268 if (Unit* summoner = tempSummon->GetSummonerUnit())
4269 {
4271
4272 Talk(TALK_AGATHA_POST_EVENT2, summoner);
4273
4274 if (Player* player = summoner->ToPlayer())
4275 player->KilledMonsterCredit(NPC_AGATHA_FENRIS);
4276
4277 me->SetDisableGravity(true);
4278 me->SetCanFly(true);
4279
4280 me->SetSpeed(MOVE_RUN, 7.7937083f);
4281 me->GetMotionMaster()->Clear();
4283 }
4284 break;
4285 }
4286
4287 case EVENT_FLEE_FROM_FENRIS + 3:
4288 {
4289 if (Unit* summoner = tempSummon->GetSummonerUnit())
4290 {
4291 summoner->ExitVehicle();
4292
4293 _isSceneStarted = false;
4294
4295 me->SetSpeed(MOVE_RUN, 1.14286f);
4296
4297 // Note: SummonPropertiesFlags::JoinSummonerSpawnGroup is NYI.
4298 me->GetMotionMaster()->Clear();
4299 me->GetMotionMaster()->MoveFollow(summoner, 3.0f, float(M_PI / 2.0f));
4300
4303
4305 }
4306 break;
4307 }
4308
4309 default:
4310 break;
4311 }
4312 }
4313
4314 if (!UpdateVictim())
4315 return;
4316 }
4317
4319 {
4320 TempSummon* tempSummon = me->ToTempSummon();
4321 if (!tempSummon)
4322 return;
4323
4324 if (_isSceneStarted)
4325 return;
4326
4327 _isSceneStarted = true;
4328
4331
4333
4334 me->GetMotionMaster()->Clear();
4336
4337 if (Unit* summoner = tempSummon->GetSummonerUnit())
4338 Talk(TALK_AGATHA_PRE_EVENT, summoner);
4339 }
4340
4341private:
4344};
4345
4347{
4350
4351// 83990 - Notify Agatha
4353{
4354 bool Validate(SpellInfo const* /*spellInfo*/) override
4355 {
4357 }
4358
4360 {
4361 Unit* caster = GetCaster();
4362 Unit* target = GetExplTargetUnit();
4363
4364 if (caster)
4365 {
4366 if (Creature* agatha = target->FindNearestCreature(NPC_AGATHA_FENRIS, 50.0f, true))
4367 {
4368 if (agatha->GetOwner() == target)
4369 {
4370 agatha->CastSpell(caster, SPELL_RISE_FORSAKEN_FENRIS, true);
4371
4372 if (Player* player = target->ToPlayer())
4373 {
4374 if (roll_chance_i(50))
4375 {
4376 if (agatha->IsAIEnabled())
4377 agatha->AI()->Talk(TALK_AGATHA_RISE_FORSAKEN, player);
4378 }
4379 }
4380 }
4381 }
4382 }
4383 }
4384
4385 void Register() override
4386 {
4388 }
4389};
4390
4392{
4401
4409 DISPLAY_FEMALE_04_F = 33985
4411
4412// 83997 - Forsaken Trooper Master Script (Fenris Isle)
4414{
4415 bool Validate(SpellInfo const* /*spellInfo*/) override
4416 {
4417 return ValidateSpellInfo
4418 ({
4427 });
4428 }
4429
4431 {
4432 Unit* unit = GetCaster();
4433
4434 if (Creature* hillsbradRefugee = unit->ToCreature())
4435 {
4437
4438 switch (hillsbradRefugee->GetDisplayId())
4439 {
4440 case DISPLAY_MALE_01_F:
4442 break;
4443 case DISPLAY_MALE_02_F:
4445 break;
4446 case DISPLAY_MALE_03_F:
4448 break;
4449 case DISPLAY_MALE_04_F:
4451 break;
4454 break;
4457 break;
4460 break;
4463 break;
4464 default:
4465 break;
4466 }
4467
4468 hillsbradRefugee->CastSpell(hillsbradRefugee, spellId, true);
4469 }
4470 }
4471
4472 void Register() override
4473 {
4475 }
4476};
4477
4479{
4481
4485
4488
4489// 44954, 44966 - Hillsbrad Refugee
4491{
4493
4494 void Reset() override
4495 {
4496 _events.Reset();
4497 }
4498
4499 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
4500 {
4501 switch (spellInfo->Id)
4502 {
4505 me->DespawnOrUnsummon(2s);
4506 break;
4507 default:
4508 break;
4509 }
4510 }
4511
4512 void JustDied(Unit* killer) override
4513 {
4514 if (Player* player = killer->ToPlayer())
4515 {
4516 if (player->GetQuestStatus(QUEST_RISE_FORSAKEN) == QUEST_STATUS_INCOMPLETE)
4517 me->CastSpell(player, SPELL_NOTIFY_AGATHA_FENRIS, true);
4518 }
4519 }
4520
4521 void JustEngagedWith(Unit* /*who*/) override
4522 {
4524 }
4525
4526 void UpdateAI(uint32 diff) override
4527 {
4528 _events.Update(diff);
4529
4530 if (!UpdateVictim())
4531 return;
4532
4533 while (uint32 eventId = _events.ExecuteEvent())
4534 {
4535 switch (eventId)
4536 {
4539 _events.Repeat(15s, 18s);
4540 break;
4541 default:
4542 break;
4543 }
4544 }
4545 }
4546
4547private:
4549};
4550
4552{
4554
4556
4564 DISPLAY_FEMALE_04_D_F = 33994
4566
4567// 44958, 44959, 44960, 44961 - Forsaken Trooper (Male)
4568// 44962, 44963, 44964, 44965 - Forsaken Trooper (Female)
4570{
4572
4573 void IsSummonedBy(WorldObject* summoner) override
4574 {
4575 if (!summoner->IsCreature())
4576 return;
4577
4580
4582
4584
4585 switch (summoner->ToCreature()->GetDisplayId())
4586 {
4587 case DISPLAY_MALE_01_F:
4588 displayId = DISPLAY_MALE_01_D_F;
4589 break;
4590 case DISPLAY_MALE_02_F:
4591 displayId = DISPLAY_MALE_02_D_F;
4592 break;
4593 case DISPLAY_MALE_03_F:
4594 displayId = DISPLAY_MALE_03_D_F;
4595 break;
4596 case DISPLAY_MALE_04_F:
4597 displayId = DISPLAY_MALE_04_D_F;
4598 break;
4600 displayId = DISPLAY_FEMALE_01_D_F;
4601 break;
4603 displayId = DISPLAY_FEMALE_02_D_F;
4604 break;
4606 displayId = DISPLAY_FEMALE_03_D_F;
4607 break;
4609 displayId = DISPLAY_FEMALE_04_D_F;
4610 break;
4611 default:
4612 break;
4613 }
4614
4615 me->SetDisplayId(displayId);
4616
4618
4619 me->DespawnOrUnsummon(4s);
4620 }
4621
4622 void Reset() override
4623 {
4624 _events.Reset();
4625 }
4626
4627 void UpdateAI(uint32 diff) override
4628 {
4629 _events.Update(diff);
4630
4631 while (uint32 eventId = _events.ExecuteEvent())
4632 {
4633 switch (eventId)
4634 {
4637 break;
4638 default:
4639 break;
4640 }
4641 }
4642 }
4643
4644private:
4646};
4647
4649{
4652
4654
4657
4658// 44987 - Worgen Sentry
4660{
4662
4663 void Reset() override
4664 {
4665 _events.Reset();
4666 }
4667
4668 void JustDied(Unit* /*killer*/) override
4669 {
4671 }
4672
4673 void JustEngagedWith(Unit* /*who*/) override
4674 {
4676
4678 }
4679
4680 void UpdateAI(uint32 diff) override
4681 {
4682 _events.Update(diff);
4683
4684 if (!UpdateVictim())
4685 return;
4686
4687 while (uint32 eventId = _events.ExecuteEvent())
4688 {
4689 switch (eventId)
4690 {
4693 _events.Repeat(10s, 12s);
4694 break;
4695 default:
4696 break;
4697 }
4698 }
4699 }
4700
4701private:
4703};
4704
4705Position const NoEscapeStartPos = { 981.782f, 670.953f, 74.898f, 3.1887f };
4706
4708{
4711
4712// 45032 - Fenris Keep Stalker
4714{
4716
4717 void Reset() override
4718 {
4719 eventIsTriggered = false;
4720 }
4721
4722 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
4723 {
4724 switch (spellInfo->Id)
4725 {
4727 Reset();
4728 break;
4729 default:
4730 break;
4731 }
4732 }
4733
4735 {
4736 if (eventIsTriggered)
4737 return;
4738
4739 if (Player* player = ObjectAccessor::GetPlayer(*me, playerGuid))
4740 {
4741 eventIsTriggered = true;
4742
4744
4745 player->NearTeleportTo(NoEscapeStartPos, true);
4746 }
4747 }
4748
4749private:
4751};
4752
4754{
4757
4758// 6230 - No Escape
4760{
4761public:
4762 at_silverpine_no_escape() : AreaTriggerScript("at_silverpine_no_escape") { }
4763
4764 bool OnTrigger(Player* player, AreaTriggerEntry const* /*at*/) override
4765 {
4766 if (!player->IsAlive() || player->GetQuestStatus(QUEST_NO_ESCAPE) != QUEST_STATUS_INCOMPLETE)
4767 return true;
4768
4769 if (Creature* agatha = player->FindNearestCreature(NPC_AGATHA_FENRIS, 10.0f, true))
4770 {
4771 if (agatha->GetOwner() == player)
4772 {
4773 if (Creature* fenrisStalker = player->FindNearestCreature(NPC_FENRIS_KEEP_STALKER, 50.0f, true))
4774 {
4775 if (npc_silverpine_fenris_keep_stalker* fenrisKeepStalkerAI = CAST_AI(npc_silverpine_fenris_keep_stalker, fenrisStalker->AI()))
4776 fenrisKeepStalkerAI->OnTriggerNoEscape(player->GetGUID());
4777 }
4778 }
4779 }
4780
4781 return true;
4782 }
4783};
4784
4786{
4794 SPELL_SUMMON_SOPHIA = 84061
4796
4797// 84053 - Summon Fenris Actors
4799{
4800 bool Validate(SpellInfo const* /*spellInfo*/) override
4801 {
4802 return ValidateSpellInfo
4803 ({
4812 });
4813 }
4814
4816 {
4817 Unit* target = GetHitUnit();
4818
4819 target->CastSpell(target, SPELL_SUMMON_BLOODFANG_FENRIS, true);
4820 target->CastSpell(target, SPELL_SUMMON_CROWLEY_FENRIS, true);
4821 target->CastSpell(target, SPELL_SUMMON_PHIN_ODELIC, true);
4822 target->CastSpell(target, SPELL_SUMMON_BARTOLO_GINSETTI, true);
4823 target->CastSpell(target, SPELL_SUMMON_LOREMASTER_DIBBS, true);
4824 target->CastSpell(target, SPELL_SUMMON_MAGISTRATE_HENRY, true);
4825 target->CastSpell(target, SPELL_SUMMON_CARETAKER_SMITHERS, true);
4826 target->CastSpell(target, SPELL_SUMMON_SOPHIA, true);
4827 }
4828
4829 void Register() override
4830 {
4832 }
4833};
4834
4835Position const CameraFrontyardPos = { 980.7f, 689.14f, 76.9f };
4836
4838{
4843
4848
4850
4854
4855// 45003 - Fenris Keep Camera
4857{
4859
4860 void IsSummonedBy(WorldObject* summoner) override
4861 {
4862 if (Unit* unit = summoner->ToUnit())
4863 unit->EnterVehicle(me, SEAT_FENRIS_CAMERA);
4864
4867
4869 }
4870
4871 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
4872 {
4873 switch (spellInfo->Id)
4874 {
4877 break;
4878 default:
4879 break;
4880 }
4881 }
4882
4883 void PassengerBoarded(Unit* passenger, int8 seatId, bool apply) override
4884 {
4885 if (apply)
4886 {
4887 if (seatId == SEAT_FENRIS_CAMERA)
4888 {
4890
4891 me->CastSpell(passenger, SPELL_SUMMON_FENRIS_ACTORS, true);
4892 }
4893 else if (seatId == SEAT_FENRIS_CAMERA_FORCE)
4894 passenger->SetFacingTo(0.0f);
4895 }
4896 else
4897 {
4898 if (seatId == SEAT_FENRIS_CAMERA_FORCE)
4900 }
4901 }
4902
4903 void MovementInform(uint32 type, uint32 id) override
4904 {
4905 if (type == POINT_MOTION_TYPE && id == POINT_CAMERA_FRONTYARD)
4907 }
4908
4909 void UpdateAI(uint32 diff) override
4910 {
4911 TempSummon* summon = me->ToTempSummon();
4912 if (!summon)
4913 return;
4914
4915 Unit* summoner = summon->GetSummonerUnit();
4916 if (!summoner)
4917 return;
4918
4919 _events.Update(diff);
4920
4921 while (uint32 eventId = _events.ExecuteEvent())
4922 {
4923 switch (eventId)
4924 {
4927 break;
4928
4930 me->CastSpell(summoner, SPELL_FORCE_SEAT_2, true);
4932 break;
4933
4935 summoner->CastSpell(summoner, SPELL_GENERAL_TRIGGER_84102, true);
4936 break;
4937
4939 if (Creature* agatha = me->FindNearestCreature(NPC_AGATHA_FENRIS, 60.0f))
4941 me->SetFacingTo(0.08278348f);
4943 break;
4944
4947 break;
4948
4949 default:
4950 break;
4951 }
4952 }
4953 }
4954
4955private:
4957};
4958
4960{
4963
4966
4968
4977
4978// 44989 - Lord Darius Crowley, 44990 - Packleader Ivar Bloodfang
4980{
4982
4983 void JustAppeared() override
4984 {
4987
4989 }
4990
4991 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
4992 {
4993 TempSummon* tempSummon = me->ToTempSummon();
4994 if (!tempSummon)
4995 return;
4996
4997 if (me->GetEntry() != NPC_CROWLEY_FENRIS)
4998 return;
4999
5000 switch (spellInfo->Id)
5001 {
5003 {
5004 if (Unit* summoner = tempSummon->GetSummonerUnit())
5005 {
5006 me->CastSpell(summoner, SPELL_ARMORE_CAMERA_FENRIS, true);
5007
5008 Talk(TALK_CROWLEY_NO_ESCAPE_6, summoner);
5009
5011 }
5012 break;
5013 }
5014
5015 default:
5016 break;
5017 }
5018 }
5019
5020 void UpdateAI(uint32 diff) override
5021 {
5022 TempSummon* tempSummon = me->ToTempSummon();
5023 if (!tempSummon)
5024 return;
5025
5026 Unit* summoner = tempSummon->GetSummonerUnit();
5027 if (!summoner)
5028 return;
5029
5030 _events.Update(diff);
5031
5032 if (me->GetEntry() != NPC_CROWLEY_FENRIS)
5033 return;
5034
5035 while (uint32 eventId = _events.ExecuteEvent())
5036 {
5037 switch (eventId)
5038 {
5040 Talk(TALK_CROWLEY_NO_ESCAPE_0, summoner);
5042 break;
5043
5045 Talk(TALK_CROWLEY_NO_ESCAPE_1, summoner);
5047 break;
5048
5050 Talk(TALK_CROWLEY_NO_ESCAPE_2, summoner);
5052 break;
5053
5055 Talk(TALK_CROWLEY_NO_ESCAPE_3, summoner);
5057 break;
5058
5060 Talk(TALK_CROWLEY_NO_ESCAPE_4, summoner);
5062 break;
5063
5065 Talk(TALK_CROWLEY_NO_ESCAPE_5, summoner);
5067 break;
5068
5072 break;
5073
5074 default:
5075 break;
5076 }
5077 }
5078 }
5079
5080private:
5082};
5083
5085{
5093
5103
5107
5110
5111 SOUND_HOWLING = 17671
5113
5114// 44993 - Phin Odelic, 44994 - Bartolo Ginsetti, 44995 - Loremaster Dibbs, 44996 - Magistrate Henry Maleb, 44997 - Caretaker Smithers, 45002 - Sophia Zwoski
5116{
5118
5119 void JustAppeared() override
5120 {
5121 if (Creature* fenrisStalker = me->FindNearestCreature(NPC_FENRIS_KEEP_STALKER, 50.0f, true))
5122 me->SetFacingToObject(fenrisStalker);
5123
5126
5128 }
5129
5130 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
5131 {
5132 TempSummon* tempSummon = me->ToTempSummon();
5133 if (!tempSummon)
5134 return;
5135
5136 switch (spellInfo->Id)
5137 {
5139 if (Unit* summoner = tempSummon->GetSummonerUnit())
5140 me->CastSpell(summoner, SPELL_ARMORE_CAMERA_2, true);
5141 break;
5142
5145 break;
5146
5149 break;
5150
5151 default:
5152 break;
5153 }
5154 }
5155
5156 void UpdateAI(uint32 diff) override
5157 {
5158 TempSummon* tempSummon = me->ToTempSummon();
5159 if (!tempSummon)
5160 return;
5161
5162 _events.Update(diff);
5163
5164 while (uint32 eventId = _events.ExecuteEvent())
5165 {
5166 switch (eventId)
5167 {
5169 if (Unit* summoner = tempSummon->GetSummonerUnit())
5170 Talk(TALK_HENRY_NO_ESCAPE_0, summoner);
5172 break;
5173
5175 if (Unit* summoner = tempSummon->GetSummonerUnit())
5176 Talk(TALK_HENRY_NO_ESCAPE_1, summoner);
5178 break;
5179
5182 break;
5183
5186 break;
5187
5189 {
5190 _isWorgen = true;
5191
5192 uint32 spellId = 0;
5193
5194 switch (me->GetEntry())
5195 {
5196 case NPC_PHIN_ODELIC:
5197 spellId = SPELL_BLOOD_ODELIC;
5198 break;
5200 spellId = SPELL_BLOOD_BARTOLO;
5201 break;
5203 spellId = SPELL_BLOOD_DIBBS;
5204 break;
5206 spellId = SPELL_BLOOD_HENRY;
5207 break;
5209 spellId = SPELL_BLOOD_SMITHERS;
5210 break;
5211 case NPC_SOPHIA_ZWOSKI:
5212 spellId = SPELL_BLOOD_ZWOSKI;
5214 break;
5215 default:
5216 break;
5217 }
5218
5219 DoCastSelf(spellId);
5220
5222 break;
5223 }
5224
5225 case EVENT_ACTOR_FENRIS_MORPH + 1:
5229 break;
5230
5231 case EVENT_ACTOR_FENRIS_MORPH + 2:
5232 if (Creature* agatha = me->FindNearestCreature(NPC_AGATHA_FENRIS, 60.0f))
5234 break;
5235
5236 default:
5237 break;
5238 }
5239 }
5240 }
5241
5242private:
5245};
5246
5248{
5249 /* Vehicles */
5250
5253
5254 /* Forsaken High Command */
5255
5267
5268 /* Ivar Patch */
5269
5275
5276 /* Forsaken Rear Guard */
5277
5284
5285 /* North Tide's Beachhead */
5286
5294
5295 /* The Skittering Dark */
5296
5301
5302 /* Fenris Isle */
5303
5317}
#define M_PI
Definition: Common.h:115
int8_t int8
Definition: Define.h:140
int32_t int32
Definition: Define.h:138
uint32_t uint32
Definition: Define.h:142
LootItemType
Definition: LootItemType.h:24
@ POINT_MOTION_TYPE
@ TEMPSUMMON_TIMED_DESPAWN
Definition: ObjectDefines.h:65
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
@ QUEST_STATUS_REWARDED
Definition: QuestDef.h:148
@ QUEST_STATUS_INCOMPLETE
Definition: QuestDef.h:145
@ QUEST_STATUS_COMPLETE
Definition: QuestDef.h:143
float frand(float min, float max)
Definition: Random.cpp:55
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:42
bool roll_chance_i(int chance)
Definition: Random.h:59
#define RegisterCreatureAI(ai_name)
Definition: ScriptMgr.h:1380
#define RegisterGameObjectAI(ai_name)
Definition: ScriptMgr.h:1398
#define RegisterSpellScript(spell_script)
Definition: ScriptMgr.h:1369
void GetCreatureListWithEntryInGrid(Container &container, WorldObject *source, uint32 entry, float maxSearchRange)
void AddGossipItemFor(Player *player, GossipOptionNpc optionNpc, std::string text, uint32 sender, uint32 action)
void SendGossipMenuFor(Player *player, uint32 npcTextID, ObjectGuid const &guid)
void CloseGossipMenuFor(Player *player)
@ GOSSIP_SENDER_MAIN
@ GOSSIP_ACTION_INFO_DEF
SpellEffIndex
Definition: SharedDefines.h:29
@ EFFECT_1
Definition: SharedDefines.h:31
@ EFFECT_0
Definition: SharedDefines.h:30
@ GENDER_MALE
@ EMOTE_ONESHOT_POINT
@ EMOTE_ONESHOT_YES
@ EMOTE_ONESHOT_EXCLAMATION
@ EMOTE_STATE_READY_UNARMED
@ EMOTE_ONESHOT_ROAR
@ EMOTE_ONESHOT_SALUTE
@ EMOTE_ONESHOT_TALK
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_SCRIPT_EFFECT
@ POWER_ENERGY
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL
@ SPELL_AURA_DUMMY
@ SPELL_AURA_PERIODIC_DUMMY
#define SpellEffectFn(F, I, N)
Definition: SpellScript.h:842
#define AuraEffectPeriodicFn(F, I, N)
Definition: SpellScript.h:2046
#define AuraEffectApplyFn(F, I, N, M)
Definition: SpellScript.h:2029
#define AuraEffectRemoveFn(F, I, N, M)
Definition: SpellScript.h:2040
#define CAST_AI(a, b)
Definition: UnitAI.h:28
@ MOVE_RUN
Definition: UnitDefines.h:118
@ REACT_PASSIVE
Definition: UnitDefines.h:506
@ REACT_AGGRESSIVE
Definition: UnitDefines.h:508
@ REACT_ASSIST
Definition: UnitDefines.h:509
@ UNIT_STAND_STATE_DEAD
Definition: UnitDefines.h:49
@ UNIT_NPC_FLAG_QUESTGIVER
Definition: UnitDefines.h:298
@ UNIT_NPC_FLAG_SPELLCLICK
Definition: UnitDefines.h:321
DamageEffectType
Definition: UnitDefines.h:131
@ UNIT_FLAG3_UNTARGETABLE_FROM_UI
Definition: UnitDefines.h:261
@ UNIT_FLAG_IMMUNE_TO_NPC
Definition: UnitDefines.h:153
@ UNIT_FLAG_IMMUNE_TO_PC
Definition: UnitDefines.h:152
@ UNIT_STATE_CASTING
Definition: Unit.h:270
HookList< EffectPeriodicHandler > OnEffectPeriodic
Definition: SpellScript.h:2045
SpellInfo const * GetSpellInfo() const
AuraEffect * GetEffect(uint8 effIndex) const
Unit * GetTarget() const
HookList< EffectApplyHandler > OnEffectRemove
Definition: SpellScript.h:2035
HookList< EffectApplyHandler > OnEffectApply
Definition: SpellScript.h:2024
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool UpdateVictim()
Definition: CreatureAI.cpp:245
Creature *const me
Definition: CreatureAI.h:61
void SetHomePosition(float x, float y, float z, float o)
Definition: Creature.h:371
uint32 m_spells[MAX_CREATURE_SPELLS]
Definition: Creature.h:302
void SetReactState(ReactStates st)
Definition: Creature.h:160
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
Definition: Creature.cpp:2415
void SetDisplayId(uint32 displayId, bool setNative=false) override
Definition: Creature.cpp:3402
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
void CancelEvent(uint32 eventId)
Definition: EventMap.cpp:131
void Reset()
Definition: EventMap.cpp:21
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 MovePath(uint32 pathId, bool repeatable, Optional< Milliseconds > duration={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< std::pair< Milliseconds, Milliseconds > > waitTimeRangeAtPathEnd={}, Optional< float > wanderDistanceAtPathEnds={}, Optional< bool > followPathBackwardsFromEndToStart={}, bool generatePath=true)
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< float > closeEnoughDistance={})
void MoveFollow(Unit *target, float dist, ChaseAngle angle, Optional< Milliseconds > duration={}, MovementSlot slot=MOTION_SLOT_ACTIVE)
void MoveFall(uint32 id=0)
void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount, Optional< Milliseconds > duration={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default)
void Clear()
Definition: ObjectGuid.h:286
static Creature * ToCreature(Object *o)
Definition: Object.h:219
bool IsPlayer() const
Definition: Object.h:212
static Unit * ToUnit(Object *o)
Definition: Object.h:225
TypeID GetTypeId() const
Definition: Object.h:173
uint32 GetEntry() const
Definition: Object.h:161
bool IsCreature() const
Definition: Object.h:218
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
static Player * ToPlayer(Object *o)
Definition: Object.h:213
WorldSession * GetSession() const
Definition: Player.h:2101
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition: Player.cpp:16050
uint32 GetGossipTextId(uint32 menuId, WorldObject *source)
Definition: Player.cpp:14367
std::unique_ptr< PlayerMenu > PlayerTalkClass
Definition: Player.h:2380
uint32 GetQuestId() const
Definition: QuestDef.h:587
uint32 const Id
Definition: SpellInfo.h:325
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition: SpellInfo.h:577
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
Definition: SpellScript.h:162
Creature * GetHitCreature() const
Unit * GetCaster() const
Unit * GetHitUnit() const
HookList< EffectHandler > OnEffectHitTarget
Definition: SpellScript.h:840
Unit * GetExplTargetUnit() const
void Summon(Creature const *summon)
Unit * GetSummonerUnit() const
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:159
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
virtual ObjectGuid GetGUID(int32=0) const
Definition: UnitAI.h:76
virtual void SetGUID(ObjectGuid const &, int32=0)
Definition: UnitAI.h:75
Definition: Unit.h:627
void EnterVehicle(Unit *base, int8 seatId=-1)
Definition: Unit.cpp:12118
void CastStop(uint32 except_spellid=0)
Definition: Unit.cpp:1135
void SetUnitFlag3(UnitFlags3 flags)
Definition: Unit.h:843
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3685
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition: Unit.cpp:10100
void PlayOneShotAnimKitId(uint16 animKitId)
Definition: Unit.cpp:10529
void SetSpeed(UnitMoveType mtype, float newValue)
Definition: Unit.cpp:8520
void SetPower(Powers power, int32 val, bool withPowerUpdate=true)
Definition: Unit.cpp:9419
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
bool SetHover(bool enable, bool updateAnimTier=true)
Definition: Unit.cpp:12938
void SetFacingToObject(WorldObject const *object, bool force=true)
Definition: Unit.cpp:12671
void ResumeMovement(uint32 timer=0, uint8 slot=0)
Definition: Unit.cpp:10076
void PauseMovement(uint32 timer=0, uint8 slot=0, bool forced=true)
Definition: Unit.cpp:10064
bool IsAlive() const
Definition: Unit.h:1164
void RemoveNpcFlag(NPCFlags flags)
Definition: Unit.h:983
TempSummon * ToTempSummon()
Definition: Unit.h:1756
UnitAI * GetAI() const
Definition: Unit.h:660
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition: Unit.cpp:12725
void SetUninteractible(bool apply)
Definition: Unit.cpp:8147
bool IsTaxi() const
Definition: Unit.h:996
Gender GetGender() const
Definition: Unit.h:755
uint32 GetDisplayId() const
Definition: Unit.h:1567
bool IsAIEnabled() const
Definition: Unit.h:658
bool Attack(Unit *victim, bool meleeAttack)
Definition: Unit.cpp:5670
bool SetCanFly(bool enable)
Definition: Unit.cpp:12820
bool IsSummon() const
Definition: Unit.h:738
bool SetWalk(bool enable)
Definition: Unit.cpp:12707
void NearTeleportTo(Position const &pos, bool casting=false)
Definition: Unit.cpp:12327
void SetPowerType(Powers power, bool sendUpdate=true)
Definition: Unit.cpp:5534
Unit * GetVictim() const
Definition: Unit.h:715
void SetFacingTo(float const ori, bool force=true)
Definition: Unit.cpp:12653
bool HasUnitState(const uint32 f) const
Definition: Unit.h:732
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4664
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition: Unit.cpp:1598
void SetMaxPower(Powers power, int32 val)
Definition: Unit.cpp:9456
void SetUnitFlag(UnitFlags flags)
Definition: Unit.h:833
Vehicle * GetVehicleKit() const
Definition: Unit.h:1711
bool AttackStop()
Definition: Unit.cpp:5781
void RemoveUnitFlag(UnitFlags flags)
Definition: Unit.h:834
void SetAIAnimKitId(uint16 animKitId)
Definition: Unit.cpp:10543
void RemoveAllPassengers()
Removes all current and pending passengers from the vehicle.
Definition: Vehicle.cpp:226
void PlayDirectSound(uint32 soundId, Player const *target=nullptr, uint32 broadcastTextId=0) const
Definition: Object.cpp:3592
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
Unit * GetOwner() const
Definition: Object.cpp:2229
float GetDistance2d(WorldObject const *obj) const
Definition: Object.cpp:1096
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition: Object.cpp:2148
void SendTaxiMenu(Creature *unit)
Definition: TaxiHandler.cpp:92
bool OnTrigger(Player *player, AreaTriggerEntry const *) override
bool OnTrigger(Player *player, AreaTriggerEntry const *) override
void OnApply(AuraEffect const *, AuraEffectHandleModes)
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *spellInfo) override
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
bool Validate(SpellInfo const *) override
void OnRemove(AuraEffect const *, AuraEffectHandleModes)
void OnApply(AuraEffect const *, AuraEffectHandleModes)
void apply(T *val)
Definition: ByteConverter.h:41
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:81
constexpr float GetPositionZ() const
Definition: Position.h:78
void AttackStart(Unit *) override
== Triggered Actions Requested ==================
void OnQuestAccept(Player *player, Quest const *quest) override
bool OnGossipSelect(Player *player, uint32, uint32) override
bool OnGossipSelect(Player *player, uint32, uint32) override
npc_silverpine_admiral_hatchet(Creature *creature)
void OnQuestAccept(Player *player, Quest const *quest) override
void OnQuestReward(Player *player, Quest const *quest, LootItemType, uint32) override
void WaypointReached(uint32 waypointId, uint32 pathId) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
std::array< ObjectGuid, 3 > _drunkenOrcSeaDog
void UpdateAI(uint32 diff) override
void PassengerBoarded(Unit *passenger, int8, bool apply) override
== Fields =======================================
void SetGUID(ObjectGuid const &guid, int32 id) override
npc_silverpine_armoire(Creature *creature)
bool OnGossipSelect(Player *player, uint32, uint32 gossipListId) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void WaypointReached(uint32 waypointId, uint32 pathId) override
void IsSummonedBy(WorldObject *summoner) override
npc_silverpine_deathstalker(Creature *creature)
npc_silverpine_fallen_human(Creature *creature)
void UpdateAI(uint32 diff) override
void DoAction(int32 action) override
void MovementInform(uint32 type, uint32 id) override
void IsSummonedBy(WorldObject *summoner) override
void PassengerBoarded(Unit *passenger, int8 seatId, bool apply) override
== Fields =======================================
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void OnTriggerNoEscape(ObjectGuid playerGuid)
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
npc_silverpine_forest_ettin(Creature *creature)
void SetGUID(ObjectGuid const &guid, int32 id) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *spellInfo) override
void SpellHit(WorldObject *caster, SpellInfo const *spellInfo) override
void DoAction(int32 param) override
void PassengerBoarded(Unit *, int8 seatId, bool apply) override
== Fields =======================================
void UpdateAI(uint32 diff) override
npc_silverpine_forsaken_bat(Creature *creature)
void DoAction(int32 param) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void IsSummonedBy(WorldObject *summoner) override
void PassengerBoarded(Unit *passenger, int8, bool apply) override
== Fields =======================================
void UpdateAI(uint32 diff) override
void WaypointReached(uint32 waypointId, uint32 pathId) override
void IsSummonedBy(WorldObject *summoner) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void OnQuestAccept(Player *, Quest const *quest) override
void JustSummoned(Creature *summon) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void UpdateAI(uint32 diff) override
npc_silverpine_horde_hauler(Creature *creature)
void WaypointReached(uint32 waypointId, uint32 pathId) override
void PassengerBoarded(Unit *passenger, int8 seatId, bool apply) override
== Fields =======================================
void WaypointReached(uint32 waypointId, uint32 pathId) override
void IsSummonedBy(WorldObject *summoner) override
void MovementInform(uint32 type, uint32 id) override
void IsSummonedBy(WorldObject *summoner) override
npc_silverpine_orc_crate(Creature *creature)
npc_silverpine_orc_sea_dog(Creature *creature)
void IsSummonedBy(WorldObject *summoner) override
void UpdateAI(uint32 diff) override
npc_silverpine_orc_sea_pup(Creature *creature)
void PassengerBoarded(Unit *passenger, int8 seatId, bool apply) override
== Fields =======================================
void UpdateAI(uint32 diff) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void IsSummonedBy(WorldObject *summoner) override
void WaypointReached(uint32 waypointId, uint32 pathId) override
npc_silverpine_salty_rocka(Creature *creature)
void UpdateAI(uint32 diff) override
void MoveInLineOfSight(Unit *who) override
void JustSummoned(Creature *summon) override
void OnQuestReward(Player *player, Quest const *quest, LootItemType, uint32) override
npc_silverpine_webbed_victim(Creature *creature)
void JustDied(Unit *killer) override
npc_silverpine_worgen_renegade(Creature *creature)
npc_silverpine_worgen_sentry(Creature *creature)
void UpdateAI(uint32 diff) override
Position const YorickReadyPosition
@ EVENT_FLURRY_OF_CLAWS
@ SPELL_FLURRY_OF_CLAWS
@ EVENT_MOVE_TO_FOREST_ETTIN
@ POINT_NEAR_FOREST_ETTIN
Position const AgathaPreRisePos
Position const GarroshJumpPos
@ DISPLAY_FEMALE_02_D_F
@ DISPLAY_FEMALE_04_D_F
@ DISPLAY_FEMALE_03_D_F
@ DISPLAY_FEMALE_01_D_F
@ TALK_REFUGEE_JUST_RISEN
@ EVENT_REFUGEE_JUST_RISEN
@ WAYPOINT_CLOSE_TO_ARMOIRE
@ TALK_YORICK_EXSANGUINATE_HIDE
@ EVENT_SET_GUID_FOR_ARMOIRE
@ SPELL_CANCEL_SUMMON_YORICK
@ PHASE_WAITING_TO_EXSANGUINATE
@ TALK_YORICK_EXSANGUINATE_SUMMON
@ EVENT_RANE_SKIPS_PATH
@ WAYPOINT_HIDDEN_NEXT_TO_ARMOIRE
@ NPC_PACKLEADER_IVAR_BLOODFANG
@ ACTION_RANE_JUMP_DEATH
@ SPELL_HIDDEN_IN_ARMOIRE
@ EVENT_RANE_TALK_TO_PLAYER
@ EVENT_START_QUEST_EXSANGUINATE
@ EVENT_WAIT_FOR_PLAYER_EXSANGUINATE
@ ACTION_RANE_SKIP_PATH
@ NPC_ARMOIRE_SUMMONED
@ EVENT_RANE_LAST_MOVE
@ SPELL_PERMANENT_FEIGN_DEATH
@ SPELL_COSMETIC_NOT_FEELING_SICK
@ COSMETIC_GO_TO_SLEEP
@ COSMETIC_SIT_ON_THE_FLOOR
@ SPELL_COSMETIC_FEELING_SICK
@ SPELL_COSMETIC_SLEEP
@ COSMETIC_SIT_ON_THE_FLOOR_TWICE
@ COSMETIC_START_TO_FEEL_UNEASY
void AddSC_silverpine_forest()
Position const NoEscapeStartPos
SpellForsakenTrooperMasterScriptCometh
@ SPELL_FORSAKEN_TROOPER_MALE_02_HC
@ SPELL_FORSAKEN_TROOPER_MALE_03_HC
@ SPELL_FORSAKEN_TROOPER_FEMALE_03_HC
@ SPELL_FORSAKEN_TROOPER_MALE_01_HC
@ SPELL_FORSAKEN_TROOPER_FEMALE_02_HC
@ SPELL_FORSAKEN_TROOPER_FEMALE_04_HC
@ DISPLAY_FEMALE_01_HC
@ SPELL_FORSAKEN_TROOPER_MALE_04_HC
@ DISPLAY_FEMALE_04_HC
@ DISPLAY_FEMALE_02_HC
@ SPELL_FORSAKEN_TROOPER_FEMALE_01_HC
@ DISPLAY_FEMALE_03_HC
@ WAYPOINT_ON_TROOPER_DESPAWN
@ WAYPOINT_ON_FORSAKEN_FRONT
@ SEAT_HAULER_TROOPER_4
@ EVENT_TROOPERS_RUN
@ NPC_HORDE_ENGINEER_HAULER
@ SEAT_HAULER_TROOPER_3
@ WAYPOINT_ON_DESPAWN_POINT_SOUTH
@ SEAT_HAULER_TROOPER_1
@ WAYPOINT_ON_SEPULCHER
@ SEAT_HAULER_TROOPER_5
@ SPELL_EJECT_PASSENGERS_3_8
@ EVENT_START_PATH
@ EVENT_YELL_ON_FORSAKEN_HIGH
@ NPC_FORSAKEN_TROOPER_F
@ EVENT_YELL_ON_FORSAKEN_FRONT
@ TALK_ON_SEPULCHER
@ NPC_FORSAKEN_TROOPER_M
@ TALK_ON_FORSAKEN_HIGH
@ PATH_FROM_NORTH_TO_SOUTH
@ TALK_ON_FORSAKEN_FRONT
@ SEAT_HAULER_PLAYER
@ SEAT_HAULER_TROOPER_2
@ EVENT_YELL_ON_SEPULCHER
@ NPC_SUBDUED_FOREST_ETTIN_HAULER
@ TALK_HAULER_BOARDED
@ WAYPOINT_ON_FORSAKEN_HIGH
@ SPELL_SUMMON_CROWLEY_FENRIS
@ SPELL_SUMMON_LOREMASTER_DIBBS
@ SPELL_SUMMON_BLOODFANG_FENRIS
@ SPELL_SUMMON_PHIN_ODELIC
@ SPELL_SUMMON_CARETAKER_SMITHERS
@ SPELL_SUMMON_MAGISTRATE_HENRY
@ SPELL_SUMMON_BARTOLO_GINSETTI
@ EVENT_AGATHA_CHECK_PLAYER_HEALTH
@ WAYPOINT_ARRIVED_TO_FORSAKEN
@ TALK_AGATHA_POST_EVENT2
@ TALK_AGATHA_RISE_FORSAKEN
@ SPELL_ARMORE_CAMERA_1
@ PATH_AGATHA_TO_FORSAKEN
@ EVENT_FLEE_FROM_FENRIS
@ SPELL_RIDE_REVERSE_CAST_NO_ESCAPE
@ POINT_AGATHA_BACK_FRONTYARD
@ SPELL_GENERAL_TRIGGER_84079
@ TALK_AGATHA_BROADCAST
@ SPELL_GENERAL_TRIGGER_84107
@ SPELL_AGATHA_BROADCAST
@ SPELL_GENERAL_TRIGGER_84114
@ SPELL_BOND_OF_THE_VALKYR
@ TALK_AGATHA_PRE_EVENT
@ SPELL_ARMORE_CAMERA_4
@ TALK_AGATHA_POST_EVENT1
@ SPELL_MARK_MASTER_AS_DESUMMONED
@ SPELL_UNHOLY_DARKNESS
@ SPELL_ARMORE_CAMERA_3
@ NPC_BLOODFANG_FENRIS
@ NPC_CARETAKER_SMITHERS
@ EVENT_ACTOR_FENRIS_MORPH
@ SPELL_CONVERSATION_TRIGGER_84077
@ EVENT_MAGISTRATE_ANIMATION
@ SPELL_ARMORE_CAMERA_2
@ SPELL_BLOOD_SMITHERS
@ NPC_FENRIS_KEEP_CAMERA
@ NPC_LOREMASTER_DIBBS
@ NPC_BARTOLO_GINSETTI
@ TALK_HENRY_NO_ESCAPE_0
@ TALK_HENRY_NO_ESCAPE_1
@ EVENT_ACTOR_FENRIS_DRINK
@ EVENT_ROCKA_CHOOSE_CONVERSATION
@ EVENT_ROCKA_CONVERSATION_COOLDOWN
@ EVENT_ROCKA_CHECK_CONVERSATION
@ SPELL_RISE_FORSAKEN_FENRIS
@ NPC_MUTANT_BUSH_CHICKEN
@ EVENT_GRAB_BUSH_CHICKEN
@ EVENT_BUSH_CHICKEN_CHANGE_SITS
@ SOUND_CHICKEN_MOUNT_WOUND
@ ACTION_NOTICE_CHICKEN
@ SPELL_RELEASE_BUSH_CHICKEN
@ EVENT_BUSH_CHICKEN_BLASTS
@ SPELL_RIDE_REVERSE_CAST_ITS_POISONOUS
@ SPELL_HAULING_TIMBER
@ EVENT_AFTER_GRABBING_BUSH_CHICKEN
@ SPELL_BUSH_EXPLOSION
@ ANIMKIT_FALLEN_HUMAN
@ ACTION_DESCEND_AFTER_RAISE
@ ACTION_RISE_DURING_RAISE
@ WAYPOINT_ON_CROWLEY_DESPAWN
@ SPELL_DESPAWN_ALL_SUMMONS_STEEL_THUNDER
@ EVENT_ORC_PUP_DELIVER_CRATES
@ EVENT_ORC_PUP_JUST_SUMMONED
@ TALK_ORC_PUP_SUMMONED
@ EVENT_ORC_PUP_REMOVE_PROTECTION
@ TALK_ORC_PUP_DELIVER_CRATES
@ TALK_ORC_PUP_WORN_OFF
@ SPELL_EJECT_ALL_PASSENGERS
@ SPELL_SUMMON_ORC_CRATE
@ NPC_BLOODFANG_SCAVENGER
@ NPC_GIANT_RABBID_BEAR
@ NPC_MAGISTRATE_HENRY_MALEB
@ TALK_CROWLEY_NO_ESCAPE_2
@ TALK_CROWLEY_NO_ESCAPE_0
@ TALK_CROWLEY_NO_ESCAPE_6
@ TALK_CROWLEY_NO_ESCAPE_5
@ EVENT_CROWLEY_ANIMATION_FENRIS
@ SPELL_ARMORE_CAMERA_FENRIS
@ TALK_CROWLEY_NO_ESCAPE_4
@ SPELL_CONVERSATION_TRIGGER_84076
@ TALK_CROWLEY_NO_ESCAPE_1
@ TALK_CROWLEY_NO_ESCAPE_3
@ SPELL_KILL_CREDIT_YORICK
@ SPELL_EJECT_PASSENGER_01
@ PATH_BLOODFANG_WITH_YORICK
@ TALK_CROWLEY_EXSANGUINATE_3
@ TALK_CROWLEY_EXSANGUINATE_0
@ SPELL_SUMMON_CROWLEY_BLOODFANG_MASTER
@ TALK_BLOODFANG_EXSANGUINATE_7
@ TALK_CROWLEY_EXSANGUINATE_6
@ TALK_BLOODFANG_EXSANGUINATE_2
@ TALK_CROWLEY_EXSANGUINATE_2
@ NPC_DEATHSTALKER_RANE_YORICK
@ TALK_BLOODFANG_EXSANGUINATE_1
@ TALK_BLOODFANG_EXSANGUINATE_6
@ TALK_BLOODFANG_EXSANGUINATE_0
@ TALK_CROWLEY_EXSANGUINATE_4
@ PATH_BLOODFANG_ENTER
@ SPELL_ARMOIRE_CAMERA_ON_BLOODFANG
@ EVENT_ACTION_SCENE_EXSANGUINATE
@ TALK_CROWLEY_EXSANGUINATE_5
@ NPC_LORD_DARIUS_CROWLEY
@ TALK_BLOODFANG_EXSANGUINATE_5
@ TALK_CROWLEY_EXSANGUINATE_1
@ EVENT_FINISH_SCENE_EXSANGUINATE
@ TALK_YORICK_EXSANGUINATE_DEATH
@ TALK_BLOODFANG_EXSANGUINATE_10
@ TALK_BLOODFANG_EXSANGUINATE_9
@ PATH_BLOODFANG_NEAR_YORICK
@ EVENT_SWITCH_SCENE_CAMERA
@ EVENT_START_SCENE_EXSANGUINATE
@ EVENT_TALK_SCENE_EXSANGUINATE
@ SPELL_HIDE_IN_ARMOIRE
@ SPELL_ARMOIRE_CAMERA_ON_CROWLEY
@ TALK_BLOODFANG_EXSANGUINATE_4
@ SPELL_RIDE_REVERSE_CAST_EXSANGUINATE
@ TALK_BLOODFANG_EXSANGUINATE_8
@ TALK_BLOODFANG_EXSANGUINATE_3
SylvanasForsakenHighCommand
@ SPELL_DESPAWN_ALL_SUMMONS_AGATHA
@ NPC_FORSAKEN_WARHORSE_SERVERSIDE
@ SPELL_SUMMON_FORSAKEN_WARHORSE_SERVERSIDE
@ SPELL_APPLY_INVIS_ZONE_1
@ SPELL_APPLY_INVIS_ZONE_4
@ SPELL_LORDAERON_MIGHT
@ SPELL_NOTIFY_AGATHA_FENRIS
@ SPELL_TROOPER_MASTERSCRIPT_FENRIS
@ EVENT_LORDAERON_MIGHT
@ SPELL_SUMMON_AGATHA_FENRIS
@ SPELL_FORCE_CAST_FENRIS_CAMERA
@ NPC_FENRIS_KEEP_STALKER
Position const AgathaPreResetPos
@ TALK_SYLVANAS_COMETH_7
@ POINT_AGATHA_PRE_RESET
@ QUEST_THE_WARCHIEF_COMETH
@ SPELL_RAISE_FORSAKEN_COMETH
@ EVENT_SUMMON_PORTAL_COMETH
@ TALK_SYLVANAS_COMETH_8
@ ACTION_START_SCENE_COMETH
@ TALK_SYLVANAS_COMETH_4
@ TALK_GARROSH_COMETH_3
@ TALK_SYLVANAS_COMETH_10
@ TALK_GARROSH_COMETH_9
@ TALK_SYLVANAS_COMETH_3
@ TALK_SYLVANAS_COMETH_1
@ TALK_SYLVANAS_COMETH_6
@ SPELL_SIMPLE_TELEPORT
@ SPELL_WELCOME_TO_SILVERPINE_CREDIT
@ TALK_SYLVANAS_COMETH_0
@ TALK_GARROSH_COMETH_7
@ NPC_GRAND_EXECUTOR_MORTUUS
@ POINT_AGATHA_PRE_RISE
@ EVENT_SUMMON_GARROSH_COMETH
@ SPELL_AIR_REVENANT_ENTRANCE
@ TALK_SYLVANAS_COMETH_9
@ EVENT_START_SCENE_COMETH
@ EVENT_SCENE_TALK_COMETH
@ TALK_CROMUSH_COMETH_0
@ TALK_GARROSH_COMETH_0
@ NPC_HIGH_WARLORD_CROMUSH_COMETH
@ NPC_PORTAL_FROM_ORGRIMMAR
@ NPC_FORSAKEN_WARHORSE_UNPHASED
@ TALK_SYLVANAS_COMETH_2
@ NPC_QUEST_MONSTER_CREDIT
@ TALK_CROMUSH_COMETH_1
@ TALK_GARROSH_COMETH_8
@ TALK_GARROSH_COMETH_1
@ POINT_AGATHA_RESET
@ NPC_FEMALE_FALLEN_HUMAN
@ TALK_GARROSH_COMETH_6
@ NPC_MALE_FALLEN_HUMAN
@ NPC_GARROSH_HELLSCREAM
@ TALK_SYLVANAS_COMETH_5
@ TALK_GARROSH_COMETH_10
@ TALK_GARROSH_COMETH_4
@ NPC_LADY_SYLVANAS_WINDRUNNER_COMETH
@ TALK_GARROSH_COMETH_5
@ NPC_HELLSCREAM_ELITE_COMETH
@ EVENT_AGATHA_RAISE_FORSAKEN
@ TALK_GARROSH_COMETH_2
@ SPELL_KILL_CREDIT_SEA_DOG_CRATE
Position const CameraFrontyardPos
Position const HellscreamElitePos[16]
@ EVENT_SINISTER_STRIKE
@ SPELL_SINISTER_STRIKE
@ EVENT_WEBBEB_ORC_CHECK_PLAYER
@ TALK_WEBBEB_ORC_FREED
@ EVENT_WEBBEB_ORC_TALK
@ EVENT_MATRIARCH_AGGRO
@ ANIMKIT_MATRIARCH_INTERACT
@ EVENT_SUMMON_SPIDERLINGS
@ NPC_SKITTERWEB_STALKER
@ ANIMKIT_MATRIARCH_HANGING_BY_WEB
@ EVENT_RESET_POSITION
@ ANIMKIT_MATRIARCH_LURKING_ON_CEILING
@ SPELL_SUMMNON_SPIDERLINGS
@ QUEST_LOST_IN_THE_DARKNESS
@ ACTION_WORMCRUD_START_CONVERSATION
@ QUEST_DEEPER_INTO_DARKNESS
@ ACTION_HATCHET_START_CONVERSATION
@ QUEST_ITS_ONLY_POISONOUS_IF_YOU_INGEST_IT
@ NPC_APOTHECARY_WORMCRUD
@ WAYPOINT_LAST_POINT_AROUND_LAKE
@ WAYPOINT_LAST_POINT_TO_HOME
@ SPELL_BLIGHT_CONCOCTION
@ EVENT_CHECK_FINISH_ITERATING
@ DATA_ITERATING_UPON_SUCCESS_QUEST_REQ
@ WAYPOINT_LAST_POINT_TO_LAKE
@ PATH_BAT_AROUND_LAKE
@ TALK_BAT_ARRIVED_TO_ISLE
@ NPC_BAT_HANDLER_MAGGOTBREATH
@ EVENT_START_MOVEMENT_ITERATING
@ EVENT_GO_HOME_ITERATING
@ SPELL_SUMMON_FORSAKEN_BAT
@ QUEST_ITERATING_UPON_SUCCESS
@ TALK_MAGGOTHBREATH_ITERATING_UPON_SUCCESS
@ DATA_GOSSIP_MENU_MAGGOT
@ SPELL_CHAIN_LEFT_HAULER
@ SPELL_CHAIN_RIGHT_HAULER
@ SPELL_SUMMON_FENRIS_ACTORS
@ EVENT_CHANGE_TO_SEAT_2
@ SPELL_GENERAL_TRIGGER_84102
@ EVENT_MOVE_TO_START_POINT
@ POINT_CAMERA_FRONTYARD
@ SPELL_DESPAWN_ALL_SUMMONS_FENRIS
@ SEAT_FENRIS_CAMERA_FORCE
@ EVENT_SCENE_FINISH_FENRIS
Position const AgathaResetPos
SpellForsakenTrooperMasterScriptFenrisIsle
@ SPELL_FORSAKEN_TROOPER_MALE_04_F
@ SPELL_FORSAKEN_TROOPER_MALE_03_F
@ SPELL_FORSAKEN_TROOPER_MALE_01_F
@ SPELL_FORSAKEN_TROOPER_FEMALE_03_F
@ SPELL_FORSAKEN_TROOPER_MALE_02_F
@ SPELL_FORSAKEN_TROOPER_FEMALE_01_F
@ SPELL_FORSAKEN_TROOPER_FEMALE_02_F
@ SPELL_FORSAKEN_TROOPER_FEMALE_04_F
@ EVENT_FACE_TOWARDS_SYLVANAS
@ EVENT_EMOTE_TO_SYLVANAS
@ EVENT_TRANSFORM_INTO_FORSAKEN
@ SPELL_FORSAKEN_TROOPER_MS_COMETH
@ EVENT_HATCHET_CONVERSATION_COOLDOWN
@ SPELL_DESPAWN_ALL_SUMMONS_LOST_IN_DARKNESS
@ SPELL_SEA_PUP_TRIGGER
@ SPELL_SUMMON_ORC_SEA_PUP
@ EVENT_HATCHET_CHECK_CONVERSATION
@ EVENT_UNDYING_FRENZY
@ SPELL_UNDYING_FRENZY
@ SPELL_SUMMON_DEATHSTALKER_YORICK
@ QUEST_WAITING_TO_EXSANGUINATE
@ WAYPOINT_ON_BLOODFANG_DESPAWN
@ SPELL_FREE_WEBBED_VICTIM_RANDOM
@ SPELL_FREE_WEBBED_VICTIM
@ NPC_DRUNKEN_ORC_SEA_DOG
@ EVENT_WORMCRUD_CHOOSE_CONVERSATION
@ EVENT_WORMCRUD_CHECK_CONVERSATION
@ EVENT_WORMCRUD_CONVERSATION_COOLDOWN
Position const GarroshPos
Position const CromushPos
Position const YorickDeathPosition
Position const AgathaBackFrontyardPos
Position const AgathaRisePos
Position const OrgrimmarPortalPos[3]