Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
zone_shadowmoon_valley.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6/* ScriptData
7SDName: Shadowmoon_Valley
8SD%Complete: 100
9SDComment: Quest support: 10519, 10583, 10601, 10804, 10854, 10458, 10481, 10480, 11082, 10781, 10451. Vendor Drake Dealer Hurlunk.
10SDCategory: Shadowmoon Valley
11EndScriptData */
12
13/* ContentData
14npc_mature_netherwing_drake
15npc_enslaved_netherwing_drake
16npc_drake_dealer_hurlunk
17npcs_flanis_swiftwing_and_kagrosh
18npc_murkblood_overseer
19npc_karynaku
20npc_oronok_tornheart
21npc_overlord_morghor
22npc_earthmender_wilda
23npc_torloth_the_magnificent
24npc_illidari_spawn
25npc_lord_illidan_stormrage
26go_crystal_prison
27npc_enraged_spirit
28EndContentData */
29
30#include "ScriptMgr.h"
31#include "ScriptedCreature.h"
32#include "ScriptedGossip.h"
33#include "ScriptedEscortAI.h"
34#include "Group.h"
35#include "SpellScript.h"
36#include "Player.h"
37#include "WorldSession.h"
38
39/*#####
40# npc_mature_netherwing_drake
41#####*/
42
57
59{
60public:
61 npc_mature_netherwing_drake() : CreatureScript("npc_mature_netherwing_drake") { }
62
64 {
65 return new npc_mature_netherwing_drakeAI(creature);
66 }
67
69 {
71
73
74 bool bCanEat;
76
79
81 {
82 uiPlayerGUID = 0;
83
84 bCanEat = false;
85 bIsEating = false;
86
87 EatTimer = 5000;
88 CastTimer = 5000;
89 }
90
91 void SpellHit(Unit* pCaster, SpellInfo const* spell) OVERRIDE
92 {
93 if (bCanEat || bIsEating)
94 return;
95
96 if (pCaster->GetTypeId() == TypeID::TYPEID_PLAYER && spell->Id == SPELL_PLACE_CARCASS && !me->HasAura(SPELL_JUST_EATEN))
97 {
98 uiPlayerGUID = pCaster->GetGUID();
99 bCanEat = true;
100 }
101 }
102
104 {
105 if (type != POINT_MOTION_TYPE)
106 return;
107
108 if (id == POINT_ID)
109 {
110 bIsEating = true;
111 EatTimer = 7000;
112 me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK_UNARMED);
113 }
114 }
115
117 {
118 if (bCanEat || bIsEating)
119 {
120 if (EatTimer <= diff)
121 {
122 if (bCanEat && !bIsEating)
123 {
124 if (Unit* unit = Unit::GetUnit(*me, uiPlayerGUID))
125 {
126 if (GameObject* go = unit->FindNearestGameObject(GO_CARCASS, 10))
127 {
128 if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
129 me->GetMotionMaster()->MovementExpired();
130
131 me->GetMotionMaster()->MoveIdle();
132 me->StopMoving();
133
134 me->GetMotionMaster()->MovePoint(POINT_ID, go->GetPositionX(), go->GetPositionY(), go->GetPositionZ());
135 }
136 }
137 bCanEat = false;
138 }
139 else if (bIsEating)
140 {
143
145 {
146 player->KilledMonsterCredit(NPC_EVENT_PINGER, 0);
147
148 if (GameObject* go = player->FindNearestGameObject(GO_CARCASS, 10))
149 go->Delete();
150 }
151
152 Reset();
153 me->GetMotionMaster()->Clear();
154 }
155 }
156 else
157 EatTimer -= diff;
158
159 return;
160 }
161
162 if (!UpdateVictim())
163 return;
164
165 if (CastTimer <= diff)
166 {
168 CastTimer = 5000;
169 } else CastTimer -= diff;
170
172 }
173 };
174};
175
176/*###
177# npc_enslaved_netherwing_drake
178####*/
179
181{
182 // Factions
184 FACTION_FRIENDLY = 1840, // Not sure if this is correct, it was taken off of Mordenai.
185
186 // Spells
189
190 // Creatures
193};
194
196{
197public:
198 npc_enslaved_netherwing_drake() : CreatureScript("npc_enslaved_netherwing_drake") { }
199
201 {
202 return new npc_enslaved_netherwing_drakeAI(creature);
203 }
204
206 {
208 {
209 PlayerGUID = 0;
210 Tapped = false;
211 Reset();
212 }
213
216 bool Tapped;
217
219 {
220 if (!Tapped)
221 me->setFaction(FACTION_DEFAULT);
222
223 FlyTimer = 10000;
224 me->SetDisableGravity(false);
225 me->SetVisible(true);
226 }
227
228 void SpellHit(Unit* caster, const SpellInfo* spell) OVERRIDE
229 {
230 if (!caster)
231 return;
232
233 if (caster->GetTypeId() == TypeID::TYPEID_PLAYER && spell->Id == SPELL_HIT_FORCE_OF_NELTHARAKU && !Tapped)
234 {
235 Tapped = true;
236 PlayerGUID = caster->GetGUID();
237
238 me->setFaction(FACTION_FRIENDLY);
239 DoCast(caster, SPELL_FORCE_OF_NELTHARAKU, true);
240
241 Unit* Dragonmaw = me->FindNearestCreature(NPC_DRAGONMAW_SUBJUGATOR, 50);
242 if (Dragonmaw)
243 {
244 me->AddThreat(Dragonmaw, 100000.0f);
245 AttackStart(Dragonmaw);
246 }
247
248 HostileReference* ref = me->getThreatManager().getOnlineContainer().getReferenceByTarget(caster);
249 if (ref)
250 ref->removeReference();
251 }
252 }
253
255 {
256 if (type != POINT_MOTION_TYPE)
257 return;
258
259 if (id == 1)
260 {
261 if (PlayerGUID)
262 {
263 Unit* player = Unit::GetUnit(*me, PlayerGUID);
264 if (player)
265 DoCast(player, SPELL_FORCE_OF_NELTHARAKU, true);
266
267 PlayerGUID = 0;
268 }
269 me->SetVisible(false);
270 me->SetDisableGravity(false);
271 me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
272 me->RemoveCorpse();
273 }
274 }
275
277 {
278 if (!UpdateVictim())
279 {
280 if (Tapped)
281 {
282 if (FlyTimer <= diff)
283 {
284 Tapped = false;
285 if (PlayerGUID)
286 {
288 if (player && player->GetQuestStatus(10854) == QUEST_STATUS_INCOMPLETE)
289 {
290 DoCast(player, SPELL_FORCE_OF_NELTHARAKU, true);
291 /*
292 float x, y, z;
293 me->GetPosition(x, y, z);
294
295 float dx, dy, dz;
296 me->GetRandomPoint(x, y, z, 20, dx, dy, dz);
297 dz += 20; // so it's in the air, not ground*/
298
299 Position pos;
300 if (Unit* EscapeDummy = me->FindNearestCreature(NPC_ESCAPE_DUMMY, 30))
301 EscapeDummy->GetPosition(&pos);
302 else
303 {
304 me->GetRandomNearPosition(pos, 20);
305 pos.m_positionZ += 25;
306 }
307
308 me->SetDisableGravity(true);
309 me->GetMotionMaster()->MovePoint(1, pos);
310 }
311 }
312 } else FlyTimer -= diff;
313 }
314 return;
315 }
316
318 }
319 };
320};
321
322/*#####
323# npc_dragonmaw_peon
324#####*/
325
327{
328public:
329 npc_dragonmaw_peon() : CreatureScript("npc_dragonmaw_peon") { }
330
332 {
333 return new npc_dragonmaw_peonAI(creature);
334 }
335
337 {
338 npc_dragonmaw_peonAI(Creature* creature) : ScriptedAI(creature) { }
339
341 bool Tapped;
343
345 {
346 PlayerGUID = 0;
347 Tapped = false;
348 PoisonTimer = 0;
349 }
350
351 void SpellHit(Unit* caster, const SpellInfo* spell) OVERRIDE
352 {
353 if (!caster)
354 return;
355
356 if (caster->GetTypeId() == TypeID::TYPEID_PLAYER && spell->Id == 40468 && !Tapped)
357 {
358 PlayerGUID = caster->GetGUID();
359
360 Tapped = true;
361 float x, y, z;
362 caster->GetClosePoint(x, y, z, me->GetObjectSize());
363
364 me->SetWalk(false);
365 me->GetMotionMaster()->MovePoint(1, x, y, z);
366 }
367 }
368
370 {
371 if (type != POINT_MOTION_TYPE)
372 return;
373
374 if (id)
375 {
377 PoisonTimer = 15000;
378 }
379 }
380
382 {
383 if (PoisonTimer)
384 {
385 if (PoisonTimer <= diff)
386 {
387 if (PlayerGUID)
388 {
390 if (player && player->GetQuestStatus(11020) == QUEST_STATUS_INCOMPLETE)
391 player->KilledMonsterCredit(23209, 0);
392 }
393 PoisonTimer = 0;
394 me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
395 } else PoisonTimer -= diff;
396 }
397 }
398 };
399};
400
401/*######
402## npc_drake_dealer_hurlunk
403######*/
404
406{
407public:
408 npc_drake_dealer_hurlunk() : CreatureScript("npc_drake_dealer_hurlunk") { }
409
410 bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
411 {
412 player->PlayerTalkClass->ClearMenus();
413 if (action == GOSSIP_ACTION_TRADE)
414 player->GetSession()->SendListInventory(creature->GetGUID());
415
416 return true;
417 }
418
419 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
420 {
421 if (creature->IsVendor() && player->GetReputationRank(1015) == REP_EXALTED)
423
424 player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
425
426 return true;
427 }
428};
429
430/*######
431## npc_flanis_swiftwing_and_kagrosh
432######*/
433
434#define GOSSIP_HSK1 "Take Flanis's Pack"
435#define GOSSIP_HSK2 "Take Kagrosh's Pack"
436
438{
439public:
440 npcs_flanis_swiftwing_and_kagrosh() : CreatureScript("npcs_flanis_swiftwing_and_kagrosh") { }
441
442 bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) OVERRIDE
443 {
444 player->PlayerTalkClass->ClearMenus();
445 if (action == GOSSIP_ACTION_INFO_DEF+1)
446 {
447 ItemPosCountVec dest;
448 uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30658, 1, NULL);
449 if (msg == EQUIP_ERR_OK)
450 {
451 player->StoreNewItem(dest, 30658, 1, true);
452 player->PlayerTalkClass->ClearMenus();
453 }
454 }
455 if (action == GOSSIP_ACTION_INFO_DEF+2)
456 {
457 ItemPosCountVec dest;
458 uint8 msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, 30659, 1, NULL);
459 if (msg == EQUIP_ERR_OK)
460 {
461 player->StoreNewItem(dest, 30659, 1, true);
462 player->PlayerTalkClass->ClearMenus();
463 }
464 }
465 return true;
466 }
467
468 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
469 {
470 if (player->GetQuestStatus(10583) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(30658, 1, true))
471 player->ADD_GOSSIP_ITEM(0, GOSSIP_HSK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
472 if (player->GetQuestStatus(10601) == QUEST_STATUS_INCOMPLETE && !player->HasItemCount(30659, 1, true))
473 player->ADD_GOSSIP_ITEM(0, GOSSIP_HSK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
474
475 player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
476
477 return true;
478 }
479};
480
481/*######
482## npc_murkblood_overseer
483######*/
484
485#define QUEST_11082 11082
486
487#define GOSSIP_HMO "I am here for you, overseer."
488#define GOSSIP_SMO1 "How dare you question an overseer of the Dragonmaw!"
489#define GOSSIP_SMO2 "Who speaks of me? What are you talking about, broken?"
490#define GOSSIP_SMO3 "Continue please."
491#define GOSSIP_SMO4 "Who are these bidders?"
492#define GOSSIP_SMO5 "Well... yes."
493
495{
496public:
497 npc_murkblood_overseer() : CreatureScript("npc_murkblood_overseer") { }
498
499 bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
500 {
501 player->PlayerTalkClass->ClearMenus();
502 switch (action)
503 {
506 //correct id not known
507 player->SEND_GOSSIP_MENU(10940, creature->GetGUID());
508 break;
511 //correct id not known
512 player->SEND_GOSSIP_MENU(10940, creature->GetGUID());
513 break;
516 //correct id not known
517 player->SEND_GOSSIP_MENU(10940, creature->GetGUID());
518 break;
521 //correct id not known
522 player->SEND_GOSSIP_MENU(10940, creature->GetGUID());
523 break;
526 //correct id not known
527 player->SEND_GOSSIP_MENU(10940, creature->GetGUID());
528 break;
530 //correct id not known
531 player->SEND_GOSSIP_MENU(10940, creature->GetGUID());
532 creature->CastSpell(player, 41121, false);
533 player->AreaExploredOrEventHappens(QUEST_11082);
534 break;
535 }
536 return true;
537 }
538
539 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
540 {
541 if (player->GetQuestStatus(QUEST_11082) == QUEST_STATUS_INCOMPLETE)
542 player->ADD_GOSSIP_ITEM(0, GOSSIP_HMO, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
543
544 player->SEND_GOSSIP_MENU(10940, creature->GetGUID());
545 return true;
546 }
547};
548
549/*######
550## npc_oronok
551######*/
552
553#define GOSSIP_ORONOK1 "I am ready to hear your story, Oronok."
554#define GOSSIP_ORONOK2 "How do I find the cipher?"
555#define GOSSIP_ORONOK3 "How do you know all of this?"
556#define GOSSIP_ORONOK4 "Yet what? What is it, Oronok?"
557#define GOSSIP_ORONOK5 "Continue, please."
558#define GOSSIP_ORONOK6 "So what of the cipher now? And your boys?"
559#define GOSSIP_ORONOK7 "I will find your boys and the cipher, Oronok."
560
562{
563public:
564 npc_oronok_tornheart() : CreatureScript("npc_oronok_tornheart") { }
565
566 bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
567 {
568 player->PlayerTalkClass->ClearMenus();
569 switch (action)
570 {
572 player->GetSession()->SendListInventory(creature->GetGUID());
573 break;
575 player->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
576 player->SEND_GOSSIP_MENU(10313, creature->GetGUID());
577 break;
579 player->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
580 player->SEND_GOSSIP_MENU(10314, creature->GetGUID());
581 break;
583 player->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
584 player->SEND_GOSSIP_MENU(10315, creature->GetGUID());
585 break;
587 player->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
588 player->SEND_GOSSIP_MENU(10316, creature->GetGUID());
589 break;
591 player->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
592 player->SEND_GOSSIP_MENU(10317, creature->GetGUID());
593 break;
595 player->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6);
596 player->SEND_GOSSIP_MENU(10318, creature->GetGUID());
597 break;
599 player->CLOSE_GOSSIP_MENU();
600 player->AreaExploredOrEventHappens(10519);
601 break;
602 }
603 return true;
604 }
605
606 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
607 {
608 if (creature->IsQuestGiver())
609 player->PrepareQuestMenu(creature->GetGUID());
610 if (creature->IsVendor())
612
613 if (player->GetQuestStatus(10519) == QUEST_STATUS_INCOMPLETE)
614 {
615 player->ADD_GOSSIP_ITEM(0, GOSSIP_ORONOK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
616 player->SEND_GOSSIP_MENU(10312, creature->GetGUID());
617 }else
618 player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
619
620 return true;
621 }
622};
623
624/*####
625# npc_karynaku
626####*/
627
637
639{
640 public:
641 npc_karynaku() : CreatureScript("npc_karynaku") { }
642
643 bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) OVERRIDE
644 {
645 if (quest->GetQuestId() == QUEST_ALLY_OF_NETHER)
646 player->ActivateTaxiPathTo(TAXI_PATH_ID);
647
648 if (quest->GetQuestId() == QUEST_ZUHULED_THE_WACK)
649 creature->SummonCreature(NPC_ZUHULED_THE_WACKED, -4204.94f, 316.397f, 122.508f, 1.309f, TempSummonType::TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000);
650
651 return true;
652 }
653};
654
655/*####
656# npc_overlord_morghor
657# this whole script is wrong and needs a rewrite.even the illidan npc used is the wrong one.npc id 23467 may be the correct one
658####*/
660{
662
663 C_ILLIDAN = 22083,
664 C_YARZILL = 23141,
665
666 SPELL_ONE = 39990, // Red Lightning Bolt
667 SPELL_TWO = 41528, // Mark of Stormrage
668 SPELL_THREE = 40216, // Dragonaw Faction
669 SPELL_FOUR = 42016, // Dragonaw Trasform
670
673 //OVERLORD_SAY_3 = 2,
677
680
688
690};
691
693{
694public:
695 npc_overlord_morghor() : CreatureScript("npc_overlord_morghor") { }
696
697 bool OnQuestAccept(Player* player, Creature* creature, const Quest *_Quest) OVERRIDE
698 {
699 if (_Quest->GetQuestId() == QUEST_LORD_ILLIDAN_STORMRAGE)
700 {
701 CAST_AI(npc_overlord_morghor::npc_overlord_morghorAI, creature->AI())->PlayerGUID = player->GetGUID();
702 CAST_AI(npc_overlord_morghor::npc_overlord_morghorAI, creature->AI())->StartEvent();
703 return true;
704 }
705 return false;
706 }
707
709 {
710 return new npc_overlord_morghorAI(creature);
711 }
712
714 {
715 npc_overlord_morghorAI(Creature* creature) : ScriptedAI(creature) { }
716
719
722
723 bool Event;
724
726 {
727 PlayerGUID = 0;
728 IllidanGUID = 0;
729
731 Step = 0;
732
733 Event = false;
734 me->SetUInt32Value(UNIT_FIELD_NPC_FLAGS, 2);
735 }
736
738 {
739 me->SetUInt32Value(UNIT_FIELD_NPC_FLAGS, 0);
740 me->SetUInt32Value(UNIT_FIELD_ANIM_TIER, 0);
741 Unit* Illidan = me->SummonCreature(C_ILLIDAN, -5107.83f, 602.584f, 85.2393f, 4.92598f, TempSummonType::TEMPSUMMON_CORPSE_DESPAWN, 0);
742 if (Illidan)
743 {
744 IllidanGUID = Illidan->GetGUID();
745 Illidan->SetVisible(false);
746 }
747 if (PlayerGUID)
748 {
750 if (player)
751 Talk(OVERLORD_SAY_1, player);
752 }
753 ConversationTimer = 4200;
754 Step = 0;
755 Event = true;
756 }
757
759 {
762
763 if (!player)
764 {
766 return 0;
767 }
768
769 switch (Step)
770 {
771 case 0:
772 return 0;
773 break;
774 case 1:
775 me->GetMotionMaster()->MovePoint(0, -5104.41f, 595.297f, 85.6838f);
776 return 9000;
777 break;
778 case 2:
779 Talk(OVERLORD_YELL_1, player);
780 return 4500;
781 break;
782 case 3:
783 me->SetInFront(player);
784 return 3200;
785 break;
786 case 4:
787 Talk(OVERLORD_SAY_2, player);
788 return 2000;
789 break;
790 case 5:
791 if (Illi)
792 {
793 Illi->SetVisible(true);
795 Illi->SetDisplayId(21526);
796 }
797 return 350;
798 break;
799 case 6:
800 if (Illi)
801 {
802 Illi->CastSpell(Illi, SPELL_ONE, true);
803 Illi->SetTarget(me->GetGUID());
804 me->SetTarget(IllidanGUID);
805 }
806 return 2000;
807 break;
808 case 7:
810 return 4500;
811 break;
812 case 8:
813 me->SetUInt32Value(UNIT_FIELD_ANIM_TIER, 8);
814 return 2500;
815 break;
816 case 9:
817 // missing text "Lord Illidan, this is the Dragonmaw that I, and others, have told you about. He will lead us to victory!"
818 return 5000;
819 break;
820 case 10:
821 if (Illi)
822 Illi->AI()->Talk(LORD_ILLIDAN_SAY_1);
823 return 5000;
824 break;
825 case 11:
826 Talk(OVERLORD_SAY_4, player);
827 return 6000;
828 break;
829 case 12:
830 if (Illi)
831 Illi->AI()->Talk(LORD_ILLIDAN_SAY_2);
832 return 5500;
833 break;
834 case 13:
835 if (Illi)
836 Illi->AI()->Talk(LORD_ILLIDAN_SAY_3);
837 return 4000;
838 break;
839 case 14:
840 if (Illi)
841 Illi->SetTarget(PlayerGUID);
842 return 1500;
843 break;
844 case 15:
845 if (Illi)
846 Illi->AI()->Talk(LORD_ILLIDAN_SAY_4);
847 return 1500;
848 break;
849 case 16:
850 if (Illi)
851 Illi->CastSpell(player, SPELL_TWO, true);
854 return 5000;
855 break;
856 case 17:
857 if (Illi)
858 Illi->AI()->Talk(LORD_ILLIDAN_SAY_5);
859 return 5000;
860 break;
861 case 18:
862 if (Illi)
863 Illi->AI()->Talk(LORD_ILLIDAN_SAY_6);
864 return 5000;
865 break;
866 case 19:
867 if (Illi)
868 Illi->AI()->Talk(LORD_ILLIDAN_SAY_7);
869 return 5000;
870 break;
871 case 20:
872 if (Illi)
873 {
875 Illi->SetDisableGravity(true);
876 }
877 return 500;
878 break;
879 case 21:
881 return 500;
882 break;
883 case 22:
884 if (Illi)
885 {
886 Illi->SetVisible(false);
888 }
889 return 1000;
890 break;
891 case 23:
892 me->SetUInt32Value(UNIT_FIELD_ANIM_TIER, 0);
893 return 2000;
894 break;
895 case 24:
896 me->SetTarget(PlayerGUID);
897 return 5000;
898 break;
899 case 25:
901 return 2000;
902 break;
903 case 26:
905 return 6000;
906 break;
907 case 27:
908 {
909 Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50.0f);
910 if (Yarzill)
911 Yarzill->SetTarget(PlayerGUID);
912 return 500;
913 }
914 break;
915 case 28:
917 player->RemoveAurasDueToSpell(41519);
918 player->CastSpell(player, SPELL_THREE, true);
919 player->CastSpell(player, SPELL_FOUR, true);
920 return 1000;
921 break;
922 case 29:
923 {
924 if (Creature* Yarzill = me->FindNearestCreature(C_YARZILL, 50.0f))
925 Yarzill->AI()->Talk(YARZILL_THE_MERC_SAY, player);
926 return 5000;
927 }
928 break;
929 case 30:
930 {
931 if (Creature* Yarzill = me->FindNearestCreature(C_YARZILL, 50.0f))
932 Yarzill->SetTarget(0);
933 return 5000;
934 }
935 break;
936 case 31:
937 {
938 if (Creature* Yarzill = me->FindNearestCreature(C_YARZILL, 50.0f))
939 Yarzill->CastSpell(player, 41540, true);
940 return 1000;
941 }
942 break;
943 case 32:
944 me->GetMotionMaster()->MovePoint(0, -5085.77f, 577.231f, 86.6719f);
945 return 5000;
946 break;
947 case 33:
948 me->SetTarget(0);
949 Reset();
950 return 100;
951 break;
952 default :
953 return 0;
954 break;
955 }
956 }
957
959 {
961 return;
962
963 if (ConversationTimer <= diff)
964 {
965 if (Event && PlayerGUID)
967 } else ConversationTimer -= diff;
968 }
969 };
970};
971
972/*####
973# npc_earthmender_wilda
974####*/
975
995
997{
998public:
999 npc_earthmender_wilda() : CreatureScript("npc_earthmender_wilda") { }
1000
1001 bool OnQuestAccept(Player* player, Creature* creature, const Quest* quest) OVERRIDE
1002 {
1003 if (quest->GetQuestId() == QUEST_ESCAPE_COILSCAR)
1004 {
1005 creature->AI()->Talk(SAY_WIL_START, player);
1006 creature->setFaction(FACTION_EARTHEN);
1007
1009 pEscortAI->Start(false, false, player->GetGUID(), quest);
1010 }
1011 return true;
1012 }
1013
1015 {
1016 return new npc_earthmender_wildaAI(creature);
1017 }
1018
1020 {
1022
1024
1026 {
1027 m_uiHealingTimer = 0;
1028 }
1029
1031 {
1032 Player* player = GetPlayerForEscort();
1033 if (!player)
1034 return;
1035
1036 switch (waypointId)
1037 {
1038 case 13:
1039 Talk(SAY_WIL_PROGRESS1, player);
1041 break;
1042 case 14:
1044 break;
1045 case 15:
1046 Talk(SAY_WIL_FIND_EXIT, player);
1047 break;
1048 case 19:
1049 DoRandomSay();
1050 break;
1051 case 20:
1053 break;
1054 case 26:
1055 DoRandomSay();
1056 break;
1057 case 27:
1059 break;
1060 case 33:
1061 DoRandomSay();
1062 break;
1063 case 34:
1065 break;
1066 case 37:
1067 DoRandomSay();
1068 break;
1069 case 38:
1071 break;
1072 case 39:
1073 Talk(SAY_WIL_JUST_AHEAD, player);
1074 break;
1075 case 43:
1076 DoRandomSay();
1077 break;
1078 case 44:
1080 break;
1081 case 50:
1082 Talk(SAY_WIL_END, player);
1084 break;
1085 }
1086 }
1087
1089 {
1090 if (summoned->GetEntry() == NPC_COILSKAR_ASSASSIN)
1091 summoned->AI()->AttackStart(me);
1092 }
1093
1094 //this is very unclear, random say without no real relevance to script/event
1096 {
1098 }
1099
1101 {
1102 //unknown where they actually appear
1104 }
1105
1107 {
1108 //don't always use
1109 if (rand()%5)
1110 return;
1111
1112 //only aggro text if not player
1113 if (who->GetTypeId() != TypeID::TYPEID_PLAYER)
1114 {
1115 //appears to be random
1116 if (std::rand() % 1)
1118 }
1119 }
1120
1122 {
1123 npc_escortAI::UpdateAI(uiDiff);
1124
1125 if (!UpdateVictim())
1126 return;
1127
1129 if (!HealthAbovePct(30))
1130 {
1131 if (m_uiHealingTimer <= uiDiff)
1132 {
1134 m_uiHealingTimer = 15000;
1135 }
1136 else
1137 m_uiHealingTimer -= uiDiff;
1138 }
1139 }
1140 };
1141};
1142
1143/*#####
1144# Quest: Battle of the crimson watch
1145#####*/
1146
1147/* ContentData
1148Battle of the crimson watch - creatures, gameobjects and defines
1149npc_illidari_spawn : Adds that are summoned in the Crimson Watch battle.
1150npc_torloth_the_magnificent : Final Creature that players have to face before quest is completed
1151npc_lord_illidan_stormrage : Creature that controls the event.
1152go_crystal_prison : GameObject that begins the event and hands out quest
1153EndContentData */
1154
1155#define QUEST_BATTLE_OF_THE_CRIMSON_WATCH 10781
1156#define EVENT_AREA_RADIUS 65 //65yds
1157#define EVENT_COOLDOWN 30000 //in ms. appear after event completed or failed (should be = Adds despawn time)
1158
1163
1164// Creature 0 - Torloth, 1 - Illidan
1166{
1167 {0, 2000},
1168 {1, 7000},
1169 {0, 3000},
1170 {0, 2000}, // Torloth stand
1171 {0, 1000},
1172 {0, 3000},
1173 {0, 0}
1174};
1175
1176struct Location
1177{
1178 float x, y, z, o;
1179};
1180
1181//Cordinates for Spawns
1183{
1184 //Cords used for:
1185 {-4615.8556f, 1342.2532f, 139.9f, 1.612f}, //Illidari Soldier
1186 {-4598.9365f, 1377.3182f, 139.9f, 3.917f}, //Illidari Soldier
1187 {-4598.4697f, 1360.8999f, 139.9f, 2.427f}, //Illidari Soldier
1188 {-4589.3599f, 1369.1061f, 139.9f, 3.165f}, //Illidari Soldier
1189 {-4608.3477f, 1386.0076f, 139.9f, 4.108f}, //Illidari Soldier
1190 {-4633.1889f, 1359.8033f, 139.9f, 0.949f}, //Illidari Soldier
1191 {-4623.5791f, 1351.4574f, 139.9f, 0.971f}, //Illidari Soldier
1192 {-4607.2988f, 1351.6099f, 139.9f, 2.416f}, //Illidari Soldier
1193 {-4633.7764f, 1376.0417f, 139.9f, 5.608f}, //Illidari Soldier
1194 {-4600.2461f, 1369.1240f, 139.9f, 3.056f}, //Illidari Mind Breaker
1195 {-4631.7808f, 1367.9459f, 139.9f, 0.020f}, //Illidari Mind Breaker
1196 {-4600.2461f, 1369.1240f, 139.9f, 3.056f}, //Illidari Highlord
1197 {-4631.7808f, 1367.9459f, 139.9f, 0.020f}, //Illidari Highlord
1198 {-4615.5586f, 1353.0031f, 139.9f, 1.540f}, //Illidari Highlord
1199 {-4616.4736f, 1384.2170f, 139.9f, 4.971f}, //Illidari Highlord
1200 {-4627.1240f, 1378.8752f, 139.9f, 2.544f} //Torloth The Magnificent
1201};
1202
1203struct WaveData
1204{
1207};
1208
1210{
1211 {9, 0, 22075, 10000, 7000}, //Illidari Soldier
1212 {2, 9, 22074, 10000, 7000}, //Illidari Mind Breaker
1213 {4, 11, 19797, 10000, 7000}, //Illidari Highlord
1214 {1, 15, 22076, 10000, 7000} //Torloth The Magnificent
1215};
1216
1217struct SpawnSpells
1218{
1220};
1221
1223{
1224 {10000, 15000, 35871}, // Illidari Soldier Cast - Spellbreaker
1225 {10000, 10000, 38985}, // Illidari Mind Breake Cast - Focused Bursts
1226 {35000, 35000, 22884}, // Illidari Mind Breake Cast - Psychic Scream
1227 {20000, 20000, 17194}, // Illidari Mind Breake Cast - Mind Blast
1228 {8000, 15000, 38010}, // Illidari Highlord Cast - Curse of Flames
1229 {12000, 20000, 16102}, // Illidari Highlord Cast - Flamestrike
1230 {10000, 15000, 15284}, // Torloth the Magnificent Cast - Cleave
1231 {18000, 20000, 39082}, // Torloth the Magnificent Cast - Shadowfury
1232 {25000, 28000, 33961} // Torloth the Magnificent Cast - Spell Reflection
1233};
1234
1235/*######
1236# npc_torloth_the_magnificent
1237#####*/
1238
1240{
1241public:
1242 npc_torloth_the_magnificent() : CreatureScript("npc_torloth_the_magnificent") { }
1243
1245 {
1246 return new npc_torloth_the_magnificentAI(c);
1247 }
1248
1250 {
1252
1254
1256
1259
1261
1263 {
1264 AnimationTimer = 4000;
1265 AnimationCount = 0;
1266 LordIllidanGUID = 0;
1267 AggroTargetGUID = 0;
1268 Timers = false;
1269
1270 me->AddUnitState(UNIT_STATE_ROOT);
1272 me->SetTarget(0);
1273 }
1274
1275 void EnterCombat(Unit* /*who*/)OVERRIDE { }
1276
1278 {
1279 Creature* creature = me;
1280
1281 if (TorlothAnim[AnimationCount].creature == 1)
1282 {
1283 creature = (Unit::GetCreature(*me, LordIllidanGUID));
1284
1285 if (!creature)
1286 return;
1287 }
1288
1290
1291 switch (AnimationCount)
1292 {
1293 case 0:
1294 me->SetUInt32Value(UNIT_FIELD_ANIM_TIER, 8);
1295 break;
1296 case 3:
1297 me->RemoveFlag(UNIT_FIELD_ANIM_TIER, 8);
1298 break;
1299 case 5:
1300 if (Player* AggroTarget = ObjectAccessor::GetPlayer(*me, AggroTargetGUID))
1301 {
1302 me->SetTarget(AggroTarget->GetGUID());
1303 me->AddThreat(AggroTarget, 1);
1304 me->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
1305 }
1306 break;
1307 case 6:
1308 if (Player* AggroTarget = ObjectAccessor::GetPlayer(*me, AggroTargetGUID))
1309 {
1311 me->ClearUnitState(UNIT_STATE_ROOT);
1312
1313 float x, y, z;
1314 AggroTarget->GetPosition(x, y, z);
1315 me->GetMotionMaster()->MovePoint(0, x, y, z);
1316 }
1317 break;
1318 }
1320 }
1321
1323 {
1324 if (AnimationTimer)
1325 {
1326 if (AnimationTimer <= diff)
1327 {
1329 } else AnimationTimer -= diff;
1330 }
1331
1332 if (AnimationCount < 6)
1333 {
1334 me->CombatStop();
1335 } else if (!Timers)
1336 {
1337 SpellTimer1 = SpawnCast[6].Timer1;
1338 SpellTimer2 = SpawnCast[7].Timer1;
1339 SpellTimer3 = SpawnCast[8].Timer1;
1340 Timers = true;
1341 }
1342
1343 if (Timers)
1344 {
1345 if (SpellTimer1 <= diff)
1346 {
1347 DoCastVictim(SpawnCast[6].SpellId);//Cleave
1348 SpellTimer1 = SpawnCast[6].Timer2 + (rand()%10 * 1000);
1349 } else SpellTimer1 -= diff;
1350
1351 if (SpellTimer2 <= diff)
1352 {
1353 DoCastVictim(SpawnCast[7].SpellId);//Shadowfury
1354 SpellTimer2 = SpawnCast[7].Timer2 + (rand()%5 * 1000);
1355 } else SpellTimer2 -= diff;
1356
1357 if (SpellTimer3 <= diff)
1358 {
1359 DoCast(me, SpawnCast[8].SpellId);
1360 SpellTimer3 = SpawnCast[8].Timer2 + (rand()%7 * 1000);//Spell Reflection
1361 } else SpellTimer3 -= diff;
1362 }
1363
1365 }
1366
1367 void JustDied(Unit* killer) OVERRIDE
1368 {
1369 switch (killer->GetTypeId())
1370 {
1372 if (Unit* owner = killer->GetOwner())
1373 if (Player* player = owner->ToPlayer())
1374 player->GroupEventHappens(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, me);
1375 break;
1377 if (Player* player = killer->ToPlayer())
1378 player->GroupEventHappens(QUEST_BATTLE_OF_THE_CRIMSON_WATCH, me);
1379 break;
1380 default:
1381 break;
1382 }
1383
1384 if (Creature* LordIllidan = (Unit::GetCreature(*me, LordIllidanGUID)))
1385 LordIllidan->AI()->EnterEvadeMode();
1386 }
1387 };
1388};
1389
1390/*#####
1391# npc_lord_illidan_stormrage
1392#####*/
1393
1395{
1396public:
1397 npc_lord_illidan_stormrage() : CreatureScript("npc_lord_illidan_stormrage") { }
1398
1400 {
1402 {
1403 PlayerGUID = 0;
1404 WaveTimer = 10000;
1405 AnnounceTimer = 7000;
1406 LiveCount = 0;
1407 WaveCount = 0;
1408 EventStarted = false;
1409 Announced = false;
1410 Failed = false;
1411 }
1412
1414 {
1415 PlayerGUID = 0;
1416 WaveTimer = 10000;
1417 AnnounceTimer = 7000;
1418 LiveCount = 0;
1419 WaveCount = 0;
1420 EventStarted = false;
1421 Announced = false;
1422 Failed = false;
1423
1424 me->SetVisible(false);
1425 }
1426
1427 void EnterCombat(Unit* /*who*/) OVERRIDE { }
1428
1430
1431 void AttackStart(Unit* /*who*/) OVERRIDE { }
1432
1433 void SummonNextWave();
1434
1436 {
1438
1439 if (!player)
1440 return;
1441
1442 if (Group* EventGroup = player->GetGroup())
1443 {
1444 uint8 GroupMemberCount = 0;
1445 uint8 DeadMemberCount = 0;
1446 uint8 FailedMemberCount = 0;
1447
1448 Group::MemberSlotList const& members = EventGroup->GetMemberSlots();
1449
1450 for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr)
1451 {
1452 Player* GroupMember = ObjectAccessor::GetPlayer(*me, itr->guid);
1453 if (!GroupMember)
1454 continue;
1456 {
1458 ++FailedMemberCount;
1459 }
1460 ++GroupMemberCount;
1461
1462 if (GroupMember->isDead())
1463 ++DeadMemberCount;
1464 }
1465
1466 if (GroupMemberCount == FailedMemberCount)
1467 {
1468 Failed = true;
1469 }
1470
1471 if (GroupMemberCount == DeadMemberCount)
1472 {
1473 for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr)
1474 {
1475 if (Player* groupMember = ObjectAccessor::GetPlayer(*me, itr->guid))
1476 if (groupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE)
1477 groupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH);
1478 }
1479 Failed = true;
1480 }
1481 } else if (player->isDead() || !player->IsWithinDistInMap(me, EVENT_AREA_RADIUS))
1482 {
1484 Failed = true;
1485 }
1486 }
1487
1489 {
1490 --LiveCount;
1491 if (!LiveCount)
1492 Announced = false;
1493 }
1494
1496 {
1497 if (!PlayerGUID || !EventStarted)
1498 return;
1499
1500 if (!LiveCount && WaveCount < 4)
1501 {
1502 if (!Announced && AnnounceTimer <= diff)
1503 {
1504 Announced = true;
1505 }
1506 else
1507 AnnounceTimer -= diff;
1508
1509 if (WaveTimer <= diff)
1510 {
1512 }
1513 else
1514 WaveTimer -= diff;
1515 }
1517
1518 if (Failed)
1520 }
1521
1530 };
1531
1533 {
1534 return new npc_lord_illidan_stormrageAI(creature);
1535 }
1536};
1537
1538/*######
1539# npc_illidari_spawn
1540######*/
1541
1543{
1544public:
1545 npc_illidari_spawn() : CreatureScript("npc_illidari_spawn") { }
1546
1548 {
1549 return new npc_illidari_spawnAI(c);
1550 }
1551
1553 {
1554 npc_illidari_spawnAI(Creature* creature) : ScriptedAI(creature) { }
1555
1559
1561 {
1562 LordIllidanGUID = 0;
1563 Timers = false;
1564 }
1565
1566 void EnterCombat(Unit* /*who*/) OVERRIDE { }
1567
1568 void JustDied(Unit* /*killer*/) OVERRIDE
1569 {
1570 me->RemoveCorpse();
1571 if (Creature* LordIllidan = (Unit::GetCreature(*me, LordIllidanGUID)))
1572 if (LordIllidan)
1573 CAST_AI(npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI, LordIllidan->AI())->LiveCounter();
1574 }
1575
1577 {
1578 if (!UpdateVictim())
1579 return;
1580
1581 if (!Timers)
1582 {
1583 if (me->GetEntry() == 22075)//Illidari Soldier
1584 {
1585 SpellTimer1 = SpawnCast[0].Timer1 + (rand()%4 * 1000);
1586 }
1587 if (me->GetEntry() == 22074)//Illidari Mind Breaker
1588 {
1589 SpellTimer1 = SpawnCast[1].Timer1 + (rand()%10 * 1000);
1590 SpellTimer2 = SpawnCast[2].Timer1 + (rand()%4 * 1000);
1591 SpellTimer3 = SpawnCast[3].Timer1 + (rand()%4 * 1000);
1592 }
1593 if (me->GetEntry() == 19797)// Illidari Highlord
1594 {
1595 SpellTimer1 = SpawnCast[4].Timer1 + (rand()%4 * 1000);
1596 SpellTimer2 = SpawnCast[5].Timer1 + (rand()%4 * 1000);
1597 }
1598 Timers = true;
1599 }
1600 //Illidari Soldier
1601 if (me->GetEntry() == 22075)
1602 {
1603 if (SpellTimer1 <= diff)
1604 {
1605 DoCastVictim(SpawnCast[0].SpellId);//Spellbreaker
1606 SpellTimer1 = SpawnCast[0].Timer2 + (rand()%5 * 1000);
1607 } else SpellTimer1 -= diff;
1608 }
1609 //Illidari Mind Breaker
1610 if (me->GetEntry() == 22074)
1611 {
1612 if (SpellTimer1 <= diff)
1613 {
1614 if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
1615 {
1616 if (target->GetTypeId() == TypeID::TYPEID_PLAYER)
1617 {
1618 DoCast(target, SpawnCast[1].SpellId); //Focused Bursts
1619 SpellTimer1 = SpawnCast[1].Timer2 + (rand()%5 * 1000);
1620 } else SpellTimer1 = 2000;
1621 }
1622 } else SpellTimer1 -= diff;
1623
1624 if (SpellTimer2 <= diff)
1625 {
1626 DoCastVictim(SpawnCast[2].SpellId);//Psychic Scream
1627 SpellTimer2 = SpawnCast[2].Timer2 + (rand()%13 * 1000);
1628 } else SpellTimer2 -= diff;
1629
1630 if (SpellTimer3 <= diff)
1631 {
1632 DoCastVictim(SpawnCast[3].SpellId);//Mind Blast
1633 SpellTimer3 = SpawnCast[3].Timer2 + (rand()%8 * 1000);
1634 } else SpellTimer3 -= diff;
1635 }
1636 //Illidari Highlord
1637 if (me->GetEntry() == 19797)
1638 {
1639 if (SpellTimer1 <= diff)
1640 {
1641 DoCastVictim(SpawnCast[4].SpellId);//Curse Of Flames
1642 SpellTimer1 = SpawnCast[4].Timer2 + (rand()%10 * 1000);
1643 } else SpellTimer1 -= diff;
1644
1645 if (SpellTimer2 <= diff)
1646 {
1647 DoCastVictim(SpawnCast[5].SpellId);//Flamestrike
1648 SpellTimer2 = SpawnCast[5].Timer2 + (rand()%7 * 13000);
1649 } else SpellTimer2 -= diff;
1650 }
1651
1653 }
1654 };
1655};
1656
1658{
1659 uint8 count = WavesInfo[WaveCount].SpawnCount;
1660 uint8 locIndex = WavesInfo[WaveCount].UsedSpawnPoint;
1661 uint8 FelguardCount = 0;
1662 uint8 DreadlordCount = 0;
1663
1664 for (uint8 i = 0; i < count; ++i)
1665 {
1666 Creature* Spawn = NULL;
1667 float X = SpawnLocation[locIndex + i].x;
1668 float Y = SpawnLocation[locIndex + i].y;
1669 float Z = SpawnLocation[locIndex + i].z;
1670 float O = SpawnLocation[locIndex + i].o;
1672 ++LiveCount;
1673
1674 if (Spawn)
1675 {
1676 Spawn->LoadCreaturesAddon();
1677
1678 if (WaveCount == 0)//1 Wave
1679 {
1680 if (rand()%3 == 1 && FelguardCount<2)
1681 {
1682 Spawn->SetDisplayId(18654);
1683 ++FelguardCount;
1684 }
1685 else if (DreadlordCount < 3)
1686 {
1687 Spawn->SetDisplayId(19991);
1688 ++DreadlordCount;
1689 }
1690 else if (FelguardCount<2)
1691 {
1692 Spawn->SetDisplayId(18654);
1693 ++FelguardCount;
1694 }
1695 }
1696
1697 if (WaveCount < 3)//1-3 Wave
1698 {
1699 if (PlayerGUID)
1700 {
1702 {
1703 float x, y, z;
1704 target->GetPosition(x, y, z);
1705 Spawn->GetMotionMaster()->MovePoint(0, x, y, z);
1706 }
1707 }
1708 CAST_AI(npc_illidari_spawn::npc_illidari_spawnAI, Spawn->AI())->LordIllidanGUID = me->GetGUID();
1709 }
1710
1711 if (WavesInfo[WaveCount].CreatureId == 22076) // Torloth
1712 {
1713 CAST_AI(npc_torloth_the_magnificent::npc_torloth_the_magnificentAI, Spawn->AI())->LordIllidanGUID = me->GetGUID();
1714 if (PlayerGUID)
1716 }
1717 }
1718 }
1719 ++WaveCount;
1720 WaveTimer = WavesInfo[WaveCount].SpawnTimer;
1721 AnnounceTimer = WavesInfo[WaveCount].YellTimer;
1722}
1723
1724/*#####
1725# go_crystal_prison
1726######*/
1727
1729{
1730public:
1731 go_crystal_prison() : GameObjectScript("go_crystal_prison") { }
1732
1733 bool OnQuestAccept(Player* player, GameObject* /*go*/, Quest const* quest) OVERRIDE
1734 {
1735 if (quest->GetQuestId() == QUEST_BATTLE_OF_THE_CRIMSON_WATCH)
1736 {
1737 Creature* Illidan = player->FindNearestCreature(22083, 50);
1738
1739 if (Illidan && !CAST_AI(npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI, Illidan->AI())->EventStarted)
1740 {
1741 CAST_AI(npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI, Illidan->AI())->PlayerGUID = player->GetGUID();
1744 }
1745 }
1746 return true;
1747 }
1748};
1749
1750/*####
1751# npc_enraged_spirits
1752####*/
1753
1755{
1756// QUESTS
1760
1761 // Totem
1764
1765 // SPIRITS
1770
1771 // SOULS
1775 NPC_ENRAGED_WATERY_SOUL = 21109, // wrong model
1776
1777 // SPELL KILLCREDIT - not working!?! - using KilledMonsterCredit
1782
1783 // KilledMonsterCredit Workaround
1788
1789 // Captured Spell / Buff
1791
1792 // Factions
1795};
1796
1798{
1799public:
1800 npc_enraged_spirit() : CreatureScript("npc_enraged_spirit") { }
1801
1803 {
1804 return new npc_enraged_spiritAI(creature);
1805 }
1806
1808 {
1809 npc_enraged_spiritAI(Creature* creature) : ScriptedAI(creature) { }
1810
1811 void Reset() OVERRIDE { }
1812
1813 void EnterCombat(Unit* /*who*/)OVERRIDE { }
1814
1815 void JustDied(Unit* /*killer*/) OVERRIDE
1816 {
1817 // always spawn spirit on death
1818 // if totem around
1819 // move spirit to totem and cast kill count
1820 uint32 entry = 0;
1821 uint32 credit = 0;
1822
1823 switch (me->GetEntry())
1824 {
1826 entry = NPC_FIERY_SOUL;
1827 //credit = SPELL_FIERY_SOUL_CAPTURED_CREDIT;
1828 credit = NPC_CREDIT_FIRE;
1829 break;
1831 entry = NPC_EARTHEN_SOUL;
1832 //credit = SPELL_EARTHEN_SOUL_CAPTURED_CREDIT;
1833 credit = NPC_CREDIT_EARTH;
1834 break;
1836 entry = NPC_ENRAGED_AIRY_SOUL;
1837 //credit = SPELL_AIRY_SOUL_CAPTURED_CREDIT;
1838 credit = NPC_CREDIT_AIR;
1839 break;
1842 //credit = SPELL_WATERY_SOUL_CAPTURED_CREDIT;
1843 credit = NPC_CREDIT_WATER;
1844 break;
1845 default:
1846 break;
1847 }
1848
1849 // Spawn Soul on Kill ALWAYS!
1850 Creature* Summoned = NULL;
1851 Unit* totemOspirits = NULL;
1852
1853 if (entry != 0)
1854 Summoned = DoSpawnCreature(entry, 0, 0, 1, 0, TempSummonType::TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 5000);
1855
1856 // FIND TOTEM, PROCESS QUEST
1857 if (Summoned)
1858 {
1859 totemOspirits = me->FindNearestCreature(ENTRY_TOTEM_OF_SPIRITS, RADIUS_TOTEM_OF_SPIRITS);
1860 if (totemOspirits)
1861 {
1863 Summoned->GetMotionMaster()->MovePoint(0, totemOspirits->GetPositionX(), totemOspirits->GetPositionY(), Summoned->GetPositionZ());
1864
1865 if (Unit* owner = totemOspirits->GetOwner())
1866 if (Player* player = owner->ToPlayer())
1867 player->KilledMonsterCredit(credit, 0);
1868 DoCast(totemOspirits, SPELL_SOUL_CAPTURED);
1869 }
1870 }
1871 }
1872 };
1873};
1874
1876{
1879};
1880
1882{
1883 public:
1884 spell_unlocking_zuluheds_chains() : SpellScriptLoader("spell_unlocking_zuluheds_chains") { }
1885
1887 {
1889
1891 {
1892 if (GetCaster()->GetTypeId() == TypeID::TYPEID_PLAYER)
1893 if (Creature* karynaku = GetCaster()->FindNearestCreature(NPC_KARYNAKU, 15.0f))
1894 GetCaster()->ToPlayer()->KilledMonsterCredit(NPC_KARYNAKU, karynaku->GetGUID());
1895 }
1896
1901 };
1902
1907};
1908
1921
1923{
1924public:
1925 npc_shadowmoon_tuber_node() : CreatureScript("npc_shadowmoon_tuber_node") { }
1926
1928 {
1930
1932 {
1933 tapped = false;
1934 tuberGUID = 0;
1935 resetTimer = 60000;
1936 }
1937
1939 {
1940 if (id == TYPE_BOAR && data == DATA_BOAR)
1941 {
1942 // Spawn chest GO
1944
1945 // Despawn the tuber
1946 if (GameObject* tuber = me->FindNearestGameObject(GO_SHADOWMOON_TUBER_MOUND, 5.0f))
1947 {
1948 tuberGUID = tuber->GetGUID();
1949 // @Workaround: find how to properly despawn the GO
1950 tuber->SetPhaseMask(2, true);
1951 }
1952 }
1953 }
1954
1955 void SpellHit(Unit* /*caster*/, const SpellInfo* spell) OVERRIDE
1956 {
1957 if (!tapped && spell->Id == SPELL_WHISTLE)
1958 {
1959 if (Creature* boar = me->FindNearestCreature(NPC_BOAR_ENTRY, 30.0f))
1960 {
1961 // Disable trigger and force nearest boar to walk to him
1962 tapped = true;
1963 boar->SetWalk(false);
1964 boar->GetMotionMaster()->MovePoint(POINT_TUBER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ());
1965 }
1966 }
1967 }
1968
1970 {
1971 if (tapped)
1972 {
1973 if (resetTimer <= diff)
1974 {
1975 // Respawn the tuber
1976 if (tuberGUID)
1978 // @Workaround: find how to properly respawn the GO
1979 tuber->SetPhaseMask(1, true);
1980
1981 Reset();
1982 }
1983 else
1984 resetTimer -= diff;
1985 }
1986 }
1987 private:
1991 };
1992
1994 {
1995 return new npc_shadowmoon_tuber_nodeAI(creature);
1996 }
1997};
1998
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::int8_t int8
Definition Define.h:75
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
@ GOSSIP_ICON_CHAT
Definition GossipDef.h:46
@ GOSSIP_ICON_VENDOR
Definition GossipDef.h:47
@ EQUIP_ERR_OK
Definition Item.h:28
@ WAYPOINT_MOTION_TYPE
@ POINT_MOTION_TYPE
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
@ TEMPSUMMON_CORPSE_DESPAWN
Definition Object.h:72
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
Definition Object.h:71
@ TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
Definition Object.h:68
std::vector< ItemPosCount > ItemPosCountVec
Definition Player.h:777
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:89
#define CAST_AI(a, b)
#define GOSSIP_TEXT_BROWSE_GOODS
@ GOSSIP_SENDER_MAIN
@ GOSSIP_ACTION_TRADE
@ GOSSIP_ACTION_INFO_DEF
@ EMOTE_ONESHOT_POINT
@ EMOTE_ONESHOT_EAT
@ EMOTE_ONESHOT_ATTACK_UNARMED
@ EMOTE_ONESHOT_LIFTOFF
@ REP_EXALTED
@ SPELL_SCHOOL_MASK_NORMAL
#define SpellHitFn(F)
@ JUST_DIED
Definition Unit.h:504
@ NULL_BAG
Definition Unit.h:336
@ NULL_SLOT
Definition Unit.h:337
@ UNIT_STATE_ROOT
Definition Unit.h:522
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ DIRECT_DAMAGE
Definition Unit.h:614
@ SELECT_TARGET_RANDOM
Definition UnitAI.h:23
@ UNIT_FIELD_NPC_FLAGS
@ UNIT_FIELD_ANIM_TIER
@ UNIT_FIELD_FLAGS
@ UNIT_FIELD_NPC_EMOTESTATE
static Locations Spawn[]
@ SPELL_HEALING_WAVE
@ SPELL_CHAIN_LIGHTNING
Creature * DoSummon(uint32 entry, Position const &pos, uint32 despawnTime=30000, TempSummonType summonType=TempSummonType::TEMPSUMMON_CORPSE_TIMED_DESPAWN)
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
virtual void EnterEvadeMode()
void SetDisplayId(uint32 modelId) OVERRIDE
void SetTarget(uint64 guid) OVERRIDE
void setDeathState(DeathState s) OVERRIDE
CreatureAI * AI() const
Definition Creature.h:483
CreatureScript(const char *name)
static GameObject * GetGameObject(WorldObject &object, uint64 guid)
GameObjectScript(const char *name)
Definition Group.h:147
std::list< MemberSlot > MemberSlotList
Definition Group.h:159
MemberSlotList::const_iterator member_citerator
Definition Group.h:160
void MovePoint(uint32 id, Position const &pos, bool generatePath=true)
static Creature * GetCreature(WorldObject const &u, uint64 guid)
static Player * GetPlayer(WorldObject const &, uint64 guid)
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:1280
void KilledMonsterCredit(uint32 entry, uint64 guid=0)
void GroupEventHappens(uint32 questId, WorldObject const *pEventObject)
Group * GetGroup()
Definition Player.h:2972
QuestStatus GetQuestStatus(uint32 quest_id) const
void FailQuest(uint32 quest_id)
HookList< HitHandler > AfterHit
Unit * GetCaster()
SpellScriptLoader(const char *name)
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
Unit * SelectTarget(SelectAggroTarget targetType, uint32 position=0, float dist=0.0f, bool playerOnly=false, int32 aura=0)
Definition UnitAI.cpp:66
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
Definition Unit.h:1367
void SetVisible(bool x)
Definition Unit.cpp:4163
void setFaction(uint32 faction)
Definition Unit.h:1699
Unit * GetOwner() const
Definition Unit.cpp:2339
virtual void SetTarget(uint64)=0
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
void RemoveAurasDueToSpell(uint32 spellId, uint64 casterGUID=0, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
MotionMaster * GetMotionMaster()
Definition Unit.h:2605
static Creature * GetCreature(WorldObject &object, uint64 guid)
Definition Unit.cpp:4905
static Unit * GetUnit(WorldObject &object, uint64 guid)
Definition Unit.cpp:4895
void HandleEmoteCommand(uint32 anim_id)
bool SetDisableGravity(bool disable, bool packetOnly=false)
Definition Unit.cpp:9156
bool isDead() const
Definition Unit.h:2040
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true) const
Definition Object.cpp:1735
GameObject * FindNearestGameObject(uint32 entry, float range) const
Definition Object.cpp:2810
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:2801
bool OnQuestAccept(Player *player, GameObject *, Quest const *quest) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnGossipHello(Player *player, Creature *creature) OVERRIDE
bool OnGossipSelect(Player *player, Creature *creature, uint32, uint32 action) OVERRIDE
bool OnQuestAccept(Player *player, Creature *creature, const Quest *quest) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *c) const OVERRIDE
bool OnQuestAccept(Player *player, Creature *creature, Quest const *quest) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnGossipHello(Player *player, Creature *creature) OVERRIDE
bool OnGossipSelect(Player *player, Creature *creature, uint32, uint32 action) OVERRIDE
bool OnGossipHello(Player *player, Creature *creature) OVERRIDE
bool OnGossipSelect(Player *player, Creature *creature, uint32, uint32 action) OVERRIDE
bool OnQuestAccept(Player *player, Creature *creature, const Quest *_Quest) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *c) const OVERRIDE
bool OnGossipHello(Player *player, Creature *creature) OVERRIDE
bool OnGossipSelect(Player *player, Creature *, uint32, uint32 action) OVERRIDE
SpellScript * GetSpellScript() const OVERRIDE
@ SPELL_ONE
@ SPELL_THREE
@ SPELL_TWO
const Position SpawnLocation[]
float y
Definition chapter5.cpp:210
float o
Definition chapter5.cpp:210
float z
Definition chapter5.cpp:210
float x
Definition chapter5.cpp:210
float m_positionZ
Definition Object.h:289
float GetPositionZ() const
Definition Object.h:330
float GetPositionX() const
Definition Object.h:328
void GetPosition(float &x, float &y) const
Definition Object.h:333
float GetPositionY() const
Definition Object.h:329
Creature * me
bool HealthAbovePct(uint32 pct) const
Creature * DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, TempSummonType type, uint32 despawntime)
ScriptedAI(Creature *creature)
void AttackStart(Unit *) OVERRIDE
uint32 CreatureId
uint8 UsedSpawnPoint
uint32 SpawnTimer
uint32 YellTimer
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void MovementInform(uint32 type, uint32 id) OVERRIDE
void SpellHit(Unit *caster, const SpellInfo *spell) OVERRIDE
void UpdateAI(uint32 uiDiff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void SpellHit(Unit *caster, const SpellInfo *spell) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
Player * GetPlayerForEscort()
npc_escortAI(Creature *creature)
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void SpellHit(Unit *pCaster, SpellInfo const *spell) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void SpellHit(Unit *, const SpellInfo *spell) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
#define GOSSIP_HSK2
static WaveData WavesInfo[]
@ QUEST_ZUHULED_THE_WACK
@ NPC_ZUHULED_THE_WACKED
#define GOSSIP_ORONOK1
static SpawnSpells SpawnCast[]
@ GO_SHADOWMOON_TUBER_MOUND
#define QUEST_BATTLE_OF_THE_CRIMSON_WATCH
#define GOSSIP_SMO4
static Location SpawnLocation[]
#define GOSSIP_SMO3
#define GOSSIP_ORONOK4
#define GOSSIP_ORONOK3
#define GOSSIP_SMO5
void AddSC_shadowmoon_valley()
static TorlothCinematic TorlothAnim[]
#define GOSSIP_HSK1
@ QUEST_ENRAGED_SPIRITS_FIRE_EARTH
@ SPELL_EARTHEN_SOUL_CAPTURED_CREDIT
@ NPC_ENRAGED_WATER_SPIRIT
@ NPC_ENRAGED_EARTH_SPIRIT
@ RADIUS_TOTEM_OF_SPIRITS
@ NPC_ENRAGED_WATERY_SOUL
@ SPELL_WATERY_SOUL_CAPTURED_CREDIT
@ FACTION_ENRAGED_SOUL_FRIENDLY
@ SPELL_AIRY_SOUL_CAPTURED_CREDIT
@ QUEST_ENRAGED_SPIRITS_AIR
@ FACTION_ENRAGED_SOUL_HOSTILE
@ SPELL_FIERY_SOUL_CAPTURED_CREDIT
@ QUEST_ENRAGED_SPIRITS_WATER
@ NPC_ENRAGED_FIRE_SPIRIT
#define GOSSIP_ORONOK7
#define GOSSIP_ORONOK2
#define GOSSIP_HMO
#define EVENT_AREA_RADIUS
@ NPC_COILSKAR_ASSASSIN
@ QUEST_ESCAPE_COILSCAR
@ SPELL_EARTHBING_TOTEM
#define GOSSIP_ORONOK6
#define GOSSIP_ORONOK5
#define GOSSIP_SMO2
@ SPELL_NETHER_BREATH
@ SPELL_PLACE_CARCASS
@ NPC_DRAGONMAW_SUBJUGATOR
@ SPELL_HIT_FORCE_OF_NELTHARAKU
@ SPELL_FORCE_OF_NELTHARAKU
#define QUEST_11082
@ QUEST_LORD_ILLIDAN_STORMRAGE
#define GOSSIP_SMO1
static WaveData WavesInfo[5]
@ FACTION_FRIENDLY
static SpawnSpells SpawnCast[4]