Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
npcs_special.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: Npcs_Special
8SD%Complete: 100
9SDComment: To be used for special NPCs that are located globally.
10SDCategory: NPCs
11EndScriptData
12*/
13
14/* ContentData
15npc_air_force_bots 80% support for misc (invisible) guard bots in areas where player allowed to fly. Summon guards after a preset time if tagged by spell
16npc_lunaclaw_spirit 80% support for quests 6001/6002 (Body and Heart)
17npc_chicken_cluck 100% support for quest 3861 (Cluck!)
18npc_dancing_flames 100% midsummer event NPC
19npc_guardian 100% guardianAI used to prevent players from accessing off-limits areas. Not in use by SD2
20npc_garments_of_quests 80% NPC's related to all Garments of-quests 5621, 5624, 5625, 5648, 565
21npc_injured_patient 100% patients for triage-quests (6622 and 6624)
22npc_doctor 100% Gustaf Vanhowzen and Gregory Victor, quest 6622 and 6624 (Triage)
23npc_mount_vendor 100% Regular mount vendors all over the world. Display gossip if player doesn't meet the requirements to buy
24npc_rogue_trainer 80% Scripted trainers, so they are able to offer item 17126 for class quest 6681
25npc_sayge 100% Darkmoon event fortune teller, buff player based on answers given
26npc_snake_trap_serpents 80% AI for snakes that summoned by Snake Trap
27npc_shadowfiend 100% restore 5% of owner's mana when shadowfiend die from damage
28npc_locksmith 75% list of keys needs to be confirmed
29npc_firework 100% NPC's summoned by rockets and rocket clusters, for making them cast visual
30EndContentData */
31
32#include "ScriptMgr.h"
33#include "ScriptedCreature.h"
34#include "ScriptedGossip.h"
35#include "ScriptedEscortAI.h"
36#include "ObjectMgr.h"
37#include "ScriptMgr.h"
38#include "World.h"
39#include "PassiveAI.h"
40#include "GameEventMgr.h"
41#include "GridNotifiers.h"
42#include "GridNotifiersImpl.h"
43#include "Cell.h"
44#include "CellImpl.h"
45#include "SpellAuras.h"
46#include "Pet.h"
47#include "BlackMarketMgr.h"
48
49/*########
50# npc_air_force_bots
51#########*/
52
54{
55 SPAWNTYPE_TRIPWIRE_ROOFTOP, // no warning, summon Creature at smaller range
56 SPAWNTYPE_ALARMBOT, // cast guards mark and summon npc - if player shows up with that buff duration < 5 seconds attack
57};
58
65
71
72float const RANGE_TRIPWIRE = 15.0f;
73float const RANGE_GUARDS_MARK = 50.0f;
74
76{
77 {2614, 15241, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Alliance)
78 {2615, 15242, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Horde)
79 {21974, 21976, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Area 52)
80 {21993, 15242, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Horde - Bat Rider)
81 {21996, 15241, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Alliance - Gryphon)
82 {21997, 21976, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Goblin - Area 52 - Zeppelin)
83 {21999, 15241, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Alliance)
84 {22001, 15242, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Horde)
85 {22002, 15242, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Ground (Horde)
86 {22003, 15241, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Ground (Alliance)
87 {22063, 21976, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Goblin - Area 52)
88 {22065, 22064, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Ethereal - Stormspire)
89 {22066, 22067, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Scryer - Dragonhawk)
90 {22068, 22064, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Ethereal - Stormspire)
91 {22069, 22064, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Stormspire)
92 {22070, 22067, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Scryer)
93 {22071, 22067, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Scryer)
94 {22078, 22077, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Aldor)
95 {22079, 22077, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Aldor - Gryphon)
96 {22080, 22077, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Aldor)
97 {22086, 22085, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Sporeggar)
98 {22087, 22085, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Sporeggar - Spore Bat)
99 {22088, 22085, SPAWNTYPE_TRIPWIRE_ROOFTOP}, //Air Force Trip Wire - Rooftop (Sporeggar)
100 {22090, 22089, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Toshley's Station - Flying Machine)
101 {22124, 22122, SPAWNTYPE_ALARMBOT}, //Air Force Alarm Bot (Cenarion)
102 {22125, 22122, SPAWNTYPE_ALARMBOT}, //Air Force Guard Post (Cenarion - Stormcrow)
103 {22126, 22122, SPAWNTYPE_ALARMBOT} //Air Force Trip Wire - Rooftop (Cenarion Expedition)
104};
105
107{
108public:
109 npc_air_force_bots() : CreatureScript("npc_air_force_bots") { }
110
112 {
114 {
115 SpawnAssoc = NULL;
116 SpawnedGUID = 0;
117
118 // find the correct spawnhandling
119 static uint32 entryCount = sizeof(spawnAssociations) / sizeof(SpawnAssociation);
120
121 for (uint8 i = 0; i < entryCount; ++i)
122 {
123 if (spawnAssociations[i].thisCreatureEntry == creature->GetEntry())
124 {
126 break;
127 }
128 }
129
130 if (!SpawnAssoc)
131 SF_LOG_ERROR("sql.sql", "TCSR: Creature template entry %u has ScriptName npc_air_force_bots, but it's not handled by that script", creature->GetEntry());
132 else
133 {
134 CreatureTemplate const* spawnedTemplate = sObjectMgr->GetCreatureTemplate(SpawnAssoc->spawnedCreatureEntry);
135
136 if (!spawnedTemplate)
137 {
138 SF_LOG_ERROR("sql.sql", "TCSR: Creature template entry %u does not exist in DB, which is required by npc_air_force_bots", SpawnAssoc->spawnedCreatureEntry);
139 SpawnAssoc = NULL;
140 return;
141 }
142 }
143 }
144
147
148 void Reset() OVERRIDE { }
149
151 {
152 Creature* summoned = me->SummonCreature(SpawnAssoc->spawnedCreatureEntry, 0.0f, 0.0f, 0.0f, 0.0f, TempSummonType::TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 300000);
153
154 if (summoned)
155 SpawnedGUID = summoned->GetGUID();
156 else
157 {
158 SF_LOG_ERROR("sql.sql", "TCSR: npc_air_force_bots: wasn't able to spawn Creature %u", SpawnAssoc->spawnedCreatureEntry);
159 SpawnAssoc = NULL;
160 }
161
162 return summoned;
163 }
164
166 {
168
169 if (creature && creature->IsAlive())
170 return creature;
171
172 return NULL;
173 }
174
176
177 {
178 if (!SpawnAssoc)
179 return;
180
181 if (me->IsValidAttackTarget(who))
182 {
183 Player* playerTarget = who->ToPlayer();
184
185 // airforce guards only spawn for players
186 if (!playerTarget)
187 return;
188
189 Creature* lastSpawnedGuard = SpawnedGUID == 0 ? NULL : GetSummonedGuard();
190
191 // prevent calling Unit::GetUnit at next MoveInLineOfSight call - speedup
192 if (!lastSpawnedGuard)
193 SpawnedGUID = 0;
194
195 switch (SpawnAssoc->spawnType)
196 {
198 {
199 if (!who->IsWithinDistInMap(me, RANGE_GUARDS_MARK))
200 return;
201
202 Aura* markAura = who->GetAura(SPELL_GUARDS_MARK);
203 if (markAura)
204 {
205 // the target wasn't able to move out of our range within 25 seconds
206 if (!lastSpawnedGuard)
207 {
208 lastSpawnedGuard = SummonGuard();
209
210 if (!lastSpawnedGuard)
211 return;
212 }
213
214 if (markAura->GetDuration() < AURA_DURATION_TIME_LEFT)
215 if (!lastSpawnedGuard->GetVictim())
216 lastSpawnedGuard->AI()->AttackStart(who);
217 }
218 else
219 {
220 if (!lastSpawnedGuard)
221 lastSpawnedGuard = SummonGuard();
222
223 if (!lastSpawnedGuard)
224 return;
225
226 lastSpawnedGuard->CastSpell(who, SPELL_GUARDS_MARK, true);
227 }
228 break;
229 }
231 {
232 if (!who->IsWithinDistInMap(me, RANGE_TRIPWIRE))
233 return;
234
235 if (!lastSpawnedGuard)
236 lastSpawnedGuard = SummonGuard();
237
238 if (!lastSpawnedGuard)
239 return;
240
241 // ROOFTOP only triggers if the player is on the ground
242 if (!playerTarget->IsFlying() && !lastSpawnedGuard->GetVictim())
243 lastSpawnedGuard->AI()->AttackStart(who);
244
245 break;
246 }
247 }
248 }
249 }
250 };
251
253 {
254 return new npc_air_force_botsAI(creature);
255 }
256};
257
258/*######
259## npc_lunaclaw_spirit
260######*/
261
270
271#define GOSSIP_ITEM_GRANT "You have thought well, spirit. I ask you to grant me the strength of your body and the strength of your heart."
272
274{
275public:
276 npc_lunaclaw_spirit() : CreatureScript("npc_lunaclaw_spirit") { }
277
278 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
279 {
280 if (player->GetQuestStatus(QUEST_BODY_HEART_A) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_BODY_HEART_H) == QUEST_STATUS_INCOMPLETE)
282
283 player->SEND_GOSSIP_MENU(TEXT_ID_DEFAULT, creature->GetGUID());
284 return true;
285 }
286
287 bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
288 {
289 player->PlayerTalkClass->ClearMenus();
290 if (action == GOSSIP_ACTION_INFO_DEF + 1)
291 {
292 player->SEND_GOSSIP_MENU(TEXT_ID_PROGRESS, creature->GetGUID());
293 player->AreaExploredOrEventHappens(player->GetTeam() == ALLIANCE ? QUEST_BODY_HEART_A : QUEST_BODY_HEART_H);
294 }
295 return true;
296 }
297};
298
299/*########
300# npc_chicken_cluck
301#########*/
302
313
315{
316public:
317 npc_chicken_cluck() : CreatureScript("npc_chicken_cluck") { }
318
320 {
321 npc_chicken_cluckAI(Creature* creature) : ScriptedAI(creature) { }
322
324
326 {
327 ResetFlagTimer = 120000;
328 me->setFaction(FACTION_CHICKEN);
330 }
331
332 void EnterCombat(Unit* /*who*/) OVERRIDE { }
333
335 {
336 // Reset flags after a certain time has passed so that the next player has to start the 'event' again
338 {
339 if (ResetFlagTimer <= diff)
340 {
342 return;
343 }
344 else
345 ResetFlagTimer -= diff;
346 }
347
348 if (UpdateVictim())
350 }
351
352 void ReceiveEmote(Player* player, uint32 emote) OVERRIDE
353 {
354 switch (emote)
355 {
357 if (player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_NONE && rand() % 30 == 1)
358 {
360 me->setFaction(FACTION_FRIENDLY);
361 Talk(player->GetTeam() == HORDE ? EMOTE_HELLO_H : EMOTE_HELLO_A);
362 }
363 break;
364 case TEXT_EMOTE_CHEER:
365 if (player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_COMPLETE)
366 {
368 me->setFaction(FACTION_FRIENDLY);
370 }
371 break;
372 }
373 }
374 };
375
377 {
378 return new npc_chicken_cluckAI(creature);
379 }
380
381 bool OnQuestAccept(Player* /*player*/, Creature* creature, Quest const* quest) OVERRIDE
382 {
383 if (quest->GetQuestId() == QUEST_CLUCK)
384 CAST_AI(npc_chicken_cluck::npc_chicken_cluckAI, creature->AI())->Reset();
385
386 return true;
387 }
388
389 bool OnQuestComplete(Player* /*player*/, Creature* creature, Quest const* quest) OVERRIDE
390 {
391 if (quest->GetQuestId() == QUEST_CLUCK)
392 CAST_AI(npc_chicken_cluck::npc_chicken_cluckAI, creature->AI())->Reset();
393
394 return true;
395 }
396};
397
398/*######
399## npc_dancing_flames
400######*/
401
408
410{
411public:
412 npc_dancing_flames() : CreatureScript("npc_dancing_flames") { }
413
415 {
416 npc_dancing_flamesAI(Creature* creature) : ScriptedAI(creature) { }
417
418 bool Active;
420
422 {
423 Active = true;
424 CanIteract = 3500;
425 DoCast(me, SPELL_BRAZIER, true);
426 DoCast(me, SPELL_FIERY_AURA, false);
427 float x, y, z;
428 me->GetPosition(x, y, z);
429 me->Relocate(x, y, z + 0.94f);
430 me->SetDisableGravity(true);
431 me->HandleEmoteCommand(EMOTE_ONESHOT_DANCE);
432 }
433
435 {
436 if (!Active)
437 {
438 if (CanIteract <= diff)
439 {
440 Active = true;
441 CanIteract = 3500;
442 me->HandleEmoteCommand(EMOTE_ONESHOT_DANCE);
443 }
444 else
445 CanIteract -= diff;
446 }
447 }
448
449 void EnterCombat(Unit* /*who*/)OVERRIDE { }
450
451 void ReceiveEmote(Player* player, uint32 emote) OVERRIDE
452 {
453 if (me->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()) && me->IsWithinDistInMap(player, 30.0f))
454 {
455 me->SetInFront(player);
456 Active = false;
457
458 switch (emote)
459 {
460 case TEXT_EMOTE_KISS:
461 me->HandleEmoteCommand(EMOTE_ONESHOT_SHY);
462 break;
463 case TEXT_EMOTE_WAVE:
464 me->HandleEmoteCommand(EMOTE_ONESHOT_WAVE);
465 break;
466 case TEXT_EMOTE_BOW:
467 me->HandleEmoteCommand(EMOTE_ONESHOT_BOW);
468 break;
469 case TEXT_EMOTE_JOKE:
470 me->HandleEmoteCommand(EMOTE_ONESHOT_LAUGH);
471 break;
472 case TEXT_EMOTE_DANCE:
473 if (!player->HasAura(SPELL_SEDUCTION))
474 DoCast(player, SPELL_SEDUCTION, true);
475 break;
476 }
477 }
478 }
479 };
480
482 {
483 return new npc_dancing_flamesAI(creature);
484 }
485};
486
487/*######
488## Triage quest
489######*/
490
500
501struct Location
502{
503 float x, y, z, o;
504};
505
507{
508 {-3757.38f, -4533.05f, 14.16f, 3.62f}, // Top-far-right bunk as seen from entrance
509 {-3754.36f, -4539.13f, 14.16f, 5.13f}, // Top-far-left bunk
510 {-3749.54f, -4540.25f, 14.28f, 3.34f}, // Far-right bunk
511 {-3742.10f, -4536.85f, 14.28f, 3.64f}, // Right bunk near entrance
512 {-3755.89f, -4529.07f, 14.05f, 0.57f}, // Far-left bunk
513 {-3749.51f, -4527.08f, 14.07f, 5.26f}, // Mid-left bunk
514 {-3746.37f, -4525.35f, 14.16f, 5.22f}, // Left bunk near entrance
515};
516
517//alliance run to where
518#define A_RUNTOX -3742.96f
519#define A_RUNTOY -4531.52f
520#define A_RUNTOZ 11.91f
521
523{
524 {-1013.75f, -3492.59f, 62.62f, 4.34f}, // Left, Behind
525 {-1017.72f, -3490.92f, 62.62f, 4.34f}, // Right, Behind
526 {-1015.77f, -3497.15f, 62.82f, 4.34f}, // Left, Mid
527 {-1019.51f, -3495.49f, 62.82f, 4.34f}, // Right, Mid
528 {-1017.25f, -3500.85f, 62.98f, 4.34f}, // Left, front
529 {-1020.95f, -3499.21f, 62.98f, 4.34f} // Right, Front
530};
531
532//horde run to where
533#define H_RUNTOX -1016.44f
534#define H_RUNTOY -3508.48f
535#define H_RUNTOZ 62.96f
536
538{
539 12938, // 12938 Injured Alliance Soldier
540 12936, // 12936 Badly injured Alliance Soldier
541 12937 // 12937 Critically injured Alliance Soldier
542};
543
545{
546 12923, //12923 Injured Soldier
547 12924, //12924 Badly injured Soldier
548 12925 //12925 Critically injured Soldier
549};
550
551/*######
552## npc_doctor (handles both Gustaf Vanhowzen and Gregory Victor)
553######*/
555{
556public:
557 npc_doctor() : CreatureScript("npc_doctor") { }
558
559 struct npc_doctorAI : public ScriptedAI
560 {
561 npc_doctorAI(Creature* creature) : ScriptedAI(creature) { }
562
564
569
570 bool Event;
571
572 std::list<uint64> Patients;
573 std::vector<Location*> Coordinates;
574
576 {
577 PlayerGUID = 0;
578
579 SummonPatientTimer = 10000;
583
584 Patients.clear();
585 Coordinates.clear();
586
587 Event = false;
588
590 }
591
592 void BeginEvent(Player* player)
593 {
594 PlayerGUID = player->GetGUID();
595
596 SummonPatientTimer = 10000;
600
601 switch (me->GetEntry())
602 {
603 case DOCTOR_ALLIANCE:
604 for (uint8 i = 0; i < ALLIANCE_COORDS; ++i)
605 Coordinates.push_back(&AllianceCoords[i]);
606 break;
607 case DOCTOR_HORDE:
608 for (uint8 i = 0; i < HORDE_COORDS; ++i)
609 Coordinates.push_back(&HordeCoords[i]);
610 break;
611 }
612
613 Event = true;
615 }
616
618 {
620 if (player && ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)))
621 {
623
624 if (PatientDiedCount > 5 && Event)
625 {
626 if (player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
627 player->FailQuest(6624);
628 else if (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
629 player->FailQuest(6622);
630
631 Reset();
632 return;
633 }
634
635 Coordinates.push_back(point);
636 }
637 else
638 // If no player or player abandon quest in progress
639 Reset();
640 }
641
642 void PatientSaved(Creature* /*soldier*/, Player* player, Location* point)
643 {
644 if (player && PlayerGUID == player->GetGUID())
645 {
646 if ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))
647 {
649
650 if (PatientSavedCount == 15)
651 {
652 if (!Patients.empty())
653 {
654 std::list<uint64>::const_iterator itr;
655 for (itr = Patients.begin(); itr != Patients.end(); ++itr)
656 {
657 if (Creature* patient = Unit::GetCreature((*me), *itr))
658 patient->setDeathState(DeathState::JUST_DIED);
659 }
660 }
661
662 if (player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
663 player->AreaExploredOrEventHappens(6624);
664 else if (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
665 player->AreaExploredOrEventHappens(6622);
666
667 Reset();
668 return;
669 }
670
671 Coordinates.push_back(point);
672 }
673 }
674 }
675
676 void UpdateAI(uint32 diff) OVERRIDE;
677
678 void EnterCombat(Unit* /*who*/) OVERRIDE { }
679 };
680
681 bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) OVERRIDE
682 {
683 if ((quest->GetQuestId() == 6624) || (quest->GetQuestId() == 6622))
684 CAST_AI(npc_doctor::npc_doctorAI, creature->AI())->BeginEvent(player);
685
686 return true;
687 }
688
690 {
691 return new npc_doctorAI(creature);
692 }
693};
694
695/*#####
696## npc_injured_patient (handles all the patients, no matter Horde or Alliance)
697#####*/
698
700{
701public:
702 npc_injured_patient() : CreatureScript("npc_injured_patient") { }
703
705 {
706 npc_injured_patientAI(Creature* creature) : ScriptedAI(creature) { }
707
710
712 {
713 DoctorGUID = 0;
714 Coord = NULL;
715
716 //no select
718
719 //no regen health
721
722 //to make them lay with face down
724
725 uint32 mobId = me->GetEntry();
726
727 switch (mobId)
728 { //lower max health
729 case 12923:
730 case 12938: //Injured Soldier
731 me->SetHealth(me->CountPctFromMaxHealth(75));
732 break;
733 case 12924:
734 case 12936: //Badly injured Soldier
735 me->SetHealth(me->CountPctFromMaxHealth(50));
736 break;
737 case 12925:
738 case 12937: //Critically injured Soldier
739 me->SetHealth(me->CountPctFromMaxHealth(25));
740 break;
741 }
742 }
743
744 void EnterCombat(Unit* /*who*/)OVERRIDE { }
745
746 void SpellHit(Unit* caster, SpellInfo const* spell) OVERRIDE
747 {
748 Player* player = caster->ToPlayer();
749 if (!player || !me->IsAlive() || spell->Id != 20804)
750 return;
751
752 if (player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
753 if (DoctorGUID)
754 if (Creature* doctor = Unit::GetCreature(*me, DoctorGUID))
755 CAST_AI(npc_doctor::npc_doctorAI, doctor->AI())->PatientSaved(me, player, Coord);
756
757 //make not selectable
759
760 //regen health
762
763 //stand up
765
766 Talk(SAY_DOC);
767
768 uint32 mobId = me->GetEntry();
769 me->SetWalk(false);
770
771 switch (mobId)
772 {
773 case 12923:
774 case 12924:
775 case 12925:
776 me->GetMotionMaster()->MovePoint(0, H_RUNTOX, H_RUNTOY, H_RUNTOZ);
777 break;
778 case 12936:
779 case 12937:
780 case 12938:
781 me->GetMotionMaster()->MovePoint(0, A_RUNTOX, A_RUNTOY, A_RUNTOZ);
782 break;
783 }
784 }
785
786 void UpdateAI(uint32 /*diff*/) OVERRIDE
787 {
788 //lower HP on every world tick makes it a useful counter, not officlone though
789 if (me->IsAlive() && me->GetHealth() > 6)
790 me->ModifyHealth(-5);
791
792 if (me->IsAlive() && me->GetHealth() <= 6)
793 {
796 me->setDeathState(DeathState::JUST_DIED);
797 me->SetFlag(OBJECT_FIELD_DYNAMIC_FLAGS, 32);
798
799 if (DoctorGUID)
800 if (Creature* doctor = Unit::GetCreature((*me), DoctorGUID))
801 CAST_AI(npc_doctor::npc_doctorAI, doctor->AI())->PatientDied(Coord);
802 }
803 }
804 };
805
807 {
808 return new npc_injured_patientAI(creature);
809 }
810};
811
813{
814 if (Event && SummonPatientCount >= 20)
815 {
816 Reset();
817 return;
818 }
819
820 if (Event)
821 {
822 if (SummonPatientTimer <= diff)
823 {
824 if (Coordinates.empty())
825 return;
826
827 std::vector<Location*>::iterator itr = Coordinates.begin() + rand() % Coordinates.size();
828 uint32 patientEntry = 0;
829
830 switch (me->GetEntry())
831 {
832 case DOCTOR_ALLIANCE:
833 patientEntry = AllianceSoldierId[rand() % 3];
834 break;
835 case DOCTOR_HORDE:
836 patientEntry = HordeSoldierId[rand() % 3];
837 break;
838 default:
839 SF_LOG_ERROR("scripts", "Invalid entry for Triage doctor. Please check your database");
840 return;
841 }
842
843 if (Location* point = *itr)
844 {
845 if (Creature* Patient = me->SummonCreature(patientEntry, point->x, point->y, point->z, point->o, TempSummonType::TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000))
846 {
847 //303, this flag appear to be required for client side item->spell to work (TARGET_SINGLE_FRIEND)
849
850 Patients.push_back(Patient->GetGUID());
851 CAST_AI(npc_injured_patient::npc_injured_patientAI, Patient->AI())->DoctorGUID = me->GetGUID();
852 CAST_AI(npc_injured_patient::npc_injured_patientAI, Patient->AI())->Coord = point;
853
854 Coordinates.erase(itr);
855 }
856 }
857 SummonPatientTimer = 10000;
859 }
860 else
861 SummonPatientTimer -= diff;
862 }
863}
864
865/*######
866## npc_garments_of_quests
867######*/
868
870
872{
875
881
882 ENTRY_SHAYA = 12429,
884 ENTRY_DOLF = 12427,
885 ENTRY_KORJA = 12430,
887
888 // used by 12429, 12423, 12427, 12430, 12428, but signed for 12429
892};
893
895{
896public:
897 npc_garments_of_quests() : CreatureScript("npc_garments_of_quests") { }
898
900 {
902 {
903 Reset();
904 }
905
907
909 bool CanRun;
910
912
914 {
915 CasterGUID = 0;
916
917 IsHealed = false;
918 CanRun = false;
919
920 RunAwayTimer = 5000;
921
922 me->SetStandState(UNIT_STAND_STATE_KNEEL);
923 // expect database to have RegenHealth=0
924 me->SetHealth(me->CountPctFromMaxHealth(70));
925 }
926
927 void EnterCombat(Unit* /*who*/) OVERRIDE { }
928
929 void SpellHit(Unit* caster, SpellInfo const* spell) OVERRIDE
930 {
931 if (spell->Id == SPELL_LESSER_HEAL_R2 || spell->Id == SPELL_FORTITUDE_R1)
932 {
933 //not while in combat
934 if (me->IsInCombat())
935 return;
936
937 //nothing to be done now
938 if (IsHealed && CanRun)
939 return;
940
941 if (Player* player = caster->ToPlayer())
942 {
943 switch (me->GetEntry())
944 {
945 case ENTRY_SHAYA:
946 if (player->GetQuestStatus(QUEST_MOON) == QUEST_STATUS_INCOMPLETE)
947 {
948 if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1)
949 {
950 Talk(SAY_THANKS, caster);
951 CanRun = true;
952 }
953 else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2)
954 {
955 CasterGUID = caster->GetGUID();
956 me->SetStandState(UNIT_STAND_STATE_STAND);
957 Talk(SAY_HEALED, caster);
958 IsHealed = true;
959 }
960 }
961 break;
962 case ENTRY_ROBERTS:
963 if (player->GetQuestStatus(QUEST_LIGHT_1) == QUEST_STATUS_INCOMPLETE)
964 {
965 if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1)
966 {
967 Talk(SAY_THANKS, caster);
968 CanRun = true;
969 }
970 else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2)
971 {
972 CasterGUID = caster->GetGUID();
973 me->SetStandState(UNIT_STAND_STATE_STAND);
974 Talk(SAY_HEALED, caster);
975 IsHealed = true;
976 }
977 }
978 break;
979 case ENTRY_DOLF:
980 if (player->GetQuestStatus(QUEST_LIGHT_2) == QUEST_STATUS_INCOMPLETE)
981 {
982 if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1)
983 {
984 Talk(SAY_THANKS, caster);
985 CanRun = true;
986 }
987 else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2)
988 {
989 CasterGUID = caster->GetGUID();
990 me->SetStandState(UNIT_STAND_STATE_STAND);
991 Talk(SAY_HEALED, caster);
992 IsHealed = true;
993 }
994 }
995 break;
996 case ENTRY_KORJA:
997 if (player->GetQuestStatus(QUEST_SPIRIT) == QUEST_STATUS_INCOMPLETE)
998 {
999 if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1)
1000 {
1001 Talk(SAY_THANKS, caster);
1002 CanRun = true;
1003 }
1004 else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2)
1005 {
1006 CasterGUID = caster->GetGUID();
1007 me->SetStandState(UNIT_STAND_STATE_STAND);
1008 Talk(SAY_HEALED, caster);
1009 IsHealed = true;
1010 }
1011 }
1012 break;
1013 case ENTRY_DG_KEL:
1014 if (player->GetQuestStatus(QUEST_DARKNESS) == QUEST_STATUS_INCOMPLETE)
1015 {
1016 if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1)
1017 {
1018 Talk(SAY_THANKS, caster);
1019 CanRun = true;
1020 }
1021 else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2)
1022 {
1023 CasterGUID = caster->GetGUID();
1024 me->SetStandState(UNIT_STAND_STATE_STAND);
1025 Talk(SAY_HEALED, caster);
1026 IsHealed = true;
1027 }
1028 }
1029 break;
1030 }
1031
1032 // give quest credit, not expect any special quest objectives
1033 if (CanRun)
1034 player->TalkedToCreature(me->GetEntry(), me->GetGUID());
1035 }
1036 }
1037 }
1038
1039 void WaypointReached(uint32 /*waypointId*/) OVERRIDE { }
1040
1042 {
1043 if (CanRun && !me->IsInCombat())
1044 {
1045 if (RunAwayTimer <= diff)
1046 {
1047 if (Unit* unit = Unit::GetUnit(*me, CasterGUID))
1048 {
1049 switch (me->GetEntry())
1050 {
1051 case ENTRY_SHAYA:
1052 Talk(SAY_GOODBYE, unit);
1053 break;
1054 case ENTRY_ROBERTS:
1055 Talk(SAY_GOODBYE, unit);
1056 break;
1057 case ENTRY_DOLF:
1058 Talk(SAY_GOODBYE, unit);
1059 break;
1060 case ENTRY_KORJA:
1061 Talk(SAY_GOODBYE, unit);
1062 break;
1063 case ENTRY_DG_KEL:
1064 Talk(SAY_GOODBYE, unit);
1065 break;
1066 }
1067
1068 Start(false, true, true);
1069 }
1070 else
1071 EnterEvadeMode(); //something went wrong
1072
1073 RunAwayTimer = 30000;
1074 }
1075 else
1076 RunAwayTimer -= diff;
1077 }
1078
1080 }
1081 };
1082
1084 {
1085 return new npc_garments_of_questsAI(creature);
1086 }
1087};
1088
1089/*######
1090## npc_guardian
1091######*/
1092
1097
1099{
1100public:
1101 npc_guardian() : CreatureScript("npc_guardian") { }
1102
1104 {
1105 npc_guardianAI(Creature* creature) : ScriptedAI(creature) { }
1106
1108 {
1110 }
1111
1113 {
1114 }
1115
1116 void UpdateAI(uint32 /*diff*/) OVERRIDE
1117 {
1118 if (!UpdateVictim())
1119 return;
1120
1121 if (me->isAttackReady())
1122 {
1124 me->resetAttackTimer();
1125 }
1126 }
1127 };
1128
1130 {
1131 return new npc_guardianAI(creature);
1132 }
1133};
1134
1135/*######
1136## npc_mount_vendor
1137######*/
1138
1140{
1141public:
1142 npc_mount_vendor() : CreatureScript("npc_mount_vendor") { }
1143
1144 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
1145 {
1146 if (creature->IsQuestGiver())
1147 player->PrepareQuestMenu(creature->GetGUID());
1148
1149 bool canBuy = false;
1150 uint32 vendor = creature->GetEntry();
1151 uint8 race = player->getRace();
1152
1153 switch (vendor)
1154 {
1155 case 384: //Katie Hunter
1156 case 1460: //Unger Statforth
1157 case 2357: //Merideth Carlson
1158 case 4885: //Gregor MacVince
1159 if (player->GetReputationRank(72) != REP_EXALTED && race != RACE_HUMAN)
1160 player->SEND_GOSSIP_MENU(5855, creature->GetGUID());
1161 else canBuy = true;
1162 break;
1163 case 1261: //Veron Amberstill
1164 if (player->GetReputationRank(47) != REP_EXALTED && race != RACE_DWARF)
1165 player->SEND_GOSSIP_MENU(5856, creature->GetGUID());
1166 else canBuy = true;
1167 break;
1168 case 3362: //Ogunaro Wolfrunner
1169 if (player->GetReputationRank(76) != REP_EXALTED && race != RACE_ORC)
1170 player->SEND_GOSSIP_MENU(5841, creature->GetGUID());
1171 else canBuy = true;
1172 break;
1173 case 3685: //Harb Clawhoof
1174 if (player->GetReputationRank(81) != REP_EXALTED && race != RACE_TAUREN)
1175 player->SEND_GOSSIP_MENU(5843, creature->GetGUID());
1176 else canBuy = true;
1177 break;
1178 case 4730: //Lelanai
1179 if (player->GetReputationRank(69) != REP_EXALTED && race != RACE_NIGHTELF)
1180 player->SEND_GOSSIP_MENU(5844, creature->GetGUID());
1181 else canBuy = true;
1182 break;
1183 case 4731: //Zachariah Post
1184 if (player->GetReputationRank(68) != REP_EXALTED && race != RACE_UNDEAD_PLAYER)
1185 player->SEND_GOSSIP_MENU(5840, creature->GetGUID());
1186 else canBuy = true;
1187 break;
1188 case 7952: //Zjolnir
1189 if (player->GetReputationRank(530) != REP_EXALTED && race != RACE_TROLL)
1190 player->SEND_GOSSIP_MENU(5842, creature->GetGUID());
1191 else canBuy = true;
1192 break;
1193 case 7955: //Milli Featherwhistle
1194 if (player->GetReputationRank(54) != REP_EXALTED && race != RACE_GNOME)
1195 player->SEND_GOSSIP_MENU(5857, creature->GetGUID());
1196 else canBuy = true;
1197 break;
1198 case 16264: //Winaestra
1199 if (player->GetReputationRank(911) != REP_EXALTED && race != RACE_BLOODELF)
1200 player->SEND_GOSSIP_MENU(10305, creature->GetGUID());
1201 else canBuy = true;
1202 break;
1203 case 17584: //Torallius the Pack Handler
1204 if (player->GetReputationRank(930) != REP_EXALTED && race != RACE_DRAENEI)
1205 player->SEND_GOSSIP_MENU(10239, creature->GetGUID());
1206 else canBuy = true;
1207 break;
1208 }
1209
1210 if (canBuy)
1211 {
1212 if (creature->IsVendor())
1214 player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
1215 }
1216 return true;
1217 }
1218
1219 bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
1220 {
1221 player->PlayerTalkClass->ClearMenus();
1222 if (action == GOSSIP_ACTION_TRADE)
1223 player->GetSession()->SendListInventory(creature->GetGUID());
1224
1225 return true;
1226 }
1227};
1228
1229/*######
1230## npc_rogue_trainer
1231######*/
1232
1233#define GOSSIP_HELLO_ROGUE1 "I wish to unlearn my talents"
1234#define GOSSIP_HELLO_ROGUE2 "<Take the letter>"
1235#define GOSSIP_HELLO_ROGUE3 "Purchase a Dual Talent Specialization."
1236#define GOSSIP_HELLO_ROGUE4 "I wish to unlearn my specialization"
1237
1239{
1240public:
1241 npc_rogue_trainer() : CreatureScript("npc_rogue_trainer") { }
1242
1243 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
1244 {
1245 if (creature->IsQuestGiver())
1246 player->PrepareQuestMenu(creature->GetGUID());
1247
1248 if (creature->IsTrainer())
1250
1251 if (player->getClass() == CLASS_ROGUE)
1253
1254 if (player->getClass() == CLASS_ROGUE)
1256
1257 if (player->GetSpecsCount() == 1 && player->getLevel() >= sWorld->getIntConfig(WorldIntConfigs::CONFIG_MIN_DUALSPEC_LEVEL))
1259
1260 if (player->getClass() == CLASS_ROGUE && player->getLevel() >= 24 && !player->HasItemCount(17126) && !player->GetQuestRewardStatus(6681))
1261 {
1263 player->SEND_GOSSIP_MENU(5996, creature->GetGUID());
1264 } else
1265 player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
1266
1267 return true;
1268 }
1269
1270 bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
1271 {
1272 player->PlayerTalkClass->ClearMenus();
1273 switch (action)
1274 {
1275 case GOSSIP_ACTION_INFO_DEF + 1:
1276 player->CLOSE_GOSSIP_MENU();
1277 player->CastSpell(player, 21100, false);
1278 break;
1280 player->GetSession()->SendTrainerList(creature->GetGUID());
1281 break;
1283 player->CLOSE_GOSSIP_MENU();
1284 player->SendTalentWipeConfirm(creature->GetGUID(), false);
1285 break;
1287 player->CLOSE_GOSSIP_MENU();
1288 player->SendTalentWipeConfirm(creature->GetGUID(), true);
1289 break;
1291 if (player->GetSpecsCount() == 1 && !(player->getLevel() < sWorld->getIntConfig(WorldIntConfigs::CONFIG_MIN_DUALSPEC_LEVEL)))
1292 {
1293 // 10 gold — matches gossip_menu_option BoxMoney for dual-spec purchase
1294 if (!player->HasEnoughMoney(uint64(100000)))
1295 {
1296 player->SendBuyFailed(BuyResult::BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0);
1297 player->PlayerTalkClass->SendCloseGossip();
1298 break;
1299 }
1300 else
1301 {
1302 player->ModifyMoney(int64(-100000));
1303
1304 // Cast spells that teach dual spec
1305 // Both are also ImplicitTarget self and must be cast by player
1306 player->CastSpell(player, 63680, true, NULL, NULL, player->GetGUID());
1307 player->CastSpell(player, 63624, true, NULL, NULL, player->GetGUID());
1308
1309 // Congratulations gossip (npc_text 14393)
1310 player->PrepareGossipMenu(creature, 10373);
1311 player->SendPreparedGossip(creature);
1312 }
1313 }
1314 break;
1315 }
1316 return true;
1317 }
1318};
1319
1320/*######
1321## npc_sayge
1322######*/
1323
1325{
1326 SPELL_DMG = 23768, // dmg
1327 SPELL_RES = 23769, // res
1328 SPELL_ARM = 23767, // arm
1329 SPELL_SPI = 23738, // spi
1330 SPELL_INT = 23766, // int
1331 SPELL_STM = 23737, // stm
1332 SPELL_STR = 23735, // str
1333 SPELL_AGI = 23736, // agi
1334 SPELL_FORTUNE = 23765 // faire fortune
1335};
1336
1337#define GOSSIP_HELLO_SAYGE "Yes"
1338#define GOSSIP_SENDACTION_SAYGE1 "Slay the Man"
1339#define GOSSIP_SENDACTION_SAYGE2 "Turn him over to liege"
1340#define GOSSIP_SENDACTION_SAYGE3 "Confiscate the corn"
1341#define GOSSIP_SENDACTION_SAYGE4 "Let him go and have the corn"
1342#define GOSSIP_SENDACTION_SAYGE5 "Execute your friend painfully"
1343#define GOSSIP_SENDACTION_SAYGE6 "Execute your friend painlessly"
1344#define GOSSIP_SENDACTION_SAYGE7 "Let your friend go"
1345#define GOSSIP_SENDACTION_SAYGE8 "Confront the diplomat"
1346#define GOSSIP_SENDACTION_SAYGE9 "Show not so quiet defiance"
1347#define GOSSIP_SENDACTION_SAYGE10 "Remain quiet"
1348#define GOSSIP_SENDACTION_SAYGE11 "Speak against your brother openly"
1349#define GOSSIP_SENDACTION_SAYGE12 "Help your brother in"
1350#define GOSSIP_SENDACTION_SAYGE13 "Keep your brother out without letting him know"
1351#define GOSSIP_SENDACTION_SAYGE14 "Take credit, keep gold"
1352#define GOSSIP_SENDACTION_SAYGE15 "Take credit, share the gold"
1353#define GOSSIP_SENDACTION_SAYGE16 "Let the knight take credit"
1354#define GOSSIP_SENDACTION_SAYGE17 "Thanks"
1355
1357{
1358public:
1359 npc_sayge() : CreatureScript("npc_sayge") { }
1360
1361 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
1362 {
1363 if (creature->IsQuestGiver())
1364 player->PrepareQuestMenu(creature->GetGUID());
1365
1366 if (player->HasSpellCooldown(SPELL_INT) ||
1367 player->HasSpellCooldown(SPELL_ARM) ||
1368 player->HasSpellCooldown(SPELL_DMG) ||
1369 player->HasSpellCooldown(SPELL_RES) ||
1370 player->HasSpellCooldown(SPELL_STR) ||
1371 player->HasSpellCooldown(SPELL_AGI) ||
1372 player->HasSpellCooldown(SPELL_STM) ||
1373 player->HasSpellCooldown(SPELL_SPI))
1374 player->SEND_GOSSIP_MENU(7393, creature->GetGUID());
1375 else
1376 {
1378 player->SEND_GOSSIP_MENU(7339, creature->GetGUID());
1379 }
1380
1381 return true;
1382 }
1383
1384 void SendAction(Player* player, Creature* creature, uint32 action)
1385 {
1386 switch (action)
1387 {
1388 case GOSSIP_ACTION_INFO_DEF + 1:
1393 player->SEND_GOSSIP_MENU(7340, creature->GetGUID());
1394 break;
1395 case GOSSIP_ACTION_INFO_DEF + 2:
1399 player->SEND_GOSSIP_MENU(7341, creature->GetGUID());
1400 break;
1401 case GOSSIP_ACTION_INFO_DEF + 3:
1405 player->SEND_GOSSIP_MENU(7361, creature->GetGUID());
1406 break;
1407 case GOSSIP_ACTION_INFO_DEF + 4:
1411 player->SEND_GOSSIP_MENU(7362, creature->GetGUID());
1412 break;
1413 case GOSSIP_ACTION_INFO_DEF + 5:
1417 player->SEND_GOSSIP_MENU(7363, creature->GetGUID());
1418 break;
1421 player->SEND_GOSSIP_MENU(7364, creature->GetGUID());
1422 break;
1423 case GOSSIP_ACTION_INFO_DEF + 6:
1424 creature->CastSpell(player, SPELL_FORTUNE, false);
1425 player->SEND_GOSSIP_MENU(7365, creature->GetGUID());
1426 break;
1427 }
1428 }
1429
1430 bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) OVERRIDE
1431 {
1432 player->PlayerTalkClass->ClearMenus();
1433 switch (sender)
1434 {
1435 case GOSSIP_SENDER_MAIN:
1436 SendAction(player, creature, action);
1437 break;
1438 case GOSSIP_SENDER_MAIN + 1:
1439 creature->CastSpell(player, SPELL_DMG, false);
1440 player->AddSpellCooldown(SPELL_DMG, 0, time(NULL) + 7200);
1441 SendAction(player, creature, action);
1442 break;
1443 case GOSSIP_SENDER_MAIN + 2:
1444 creature->CastSpell(player, SPELL_RES, false);
1445 player->AddSpellCooldown(SPELL_RES, 0, time(NULL) + 7200);
1446 SendAction(player, creature, action);
1447 break;
1448 case GOSSIP_SENDER_MAIN + 3:
1449 creature->CastSpell(player, SPELL_ARM, false);
1450 player->AddSpellCooldown(SPELL_ARM, 0, time(NULL) + 7200);
1451 SendAction(player, creature, action);
1452 break;
1453 case GOSSIP_SENDER_MAIN + 4:
1454 creature->CastSpell(player, SPELL_SPI, false);
1455 player->AddSpellCooldown(SPELL_SPI, 0, time(NULL) + 7200);
1456 SendAction(player, creature, action);
1457 break;
1458 case GOSSIP_SENDER_MAIN + 5:
1459 creature->CastSpell(player, SPELL_INT, false);
1460 player->AddSpellCooldown(SPELL_INT, 0, time(NULL) + 7200);
1461 SendAction(player, creature, action);
1462 break;
1463 case GOSSIP_SENDER_MAIN + 6:
1464 creature->CastSpell(player, SPELL_STM, false);
1465 player->AddSpellCooldown(SPELL_STM, 0, time(NULL) + 7200);
1466 SendAction(player, creature, action);
1467 break;
1468 case GOSSIP_SENDER_MAIN + 7:
1469 creature->CastSpell(player, SPELL_STR, false);
1470 player->AddSpellCooldown(SPELL_STR, 0, time(NULL) + 7200);
1471 SendAction(player, creature, action);
1472 break;
1473 case GOSSIP_SENDER_MAIN + 8:
1474 creature->CastSpell(player, SPELL_AGI, false);
1475 player->AddSpellCooldown(SPELL_AGI, 0, time(NULL) + 7200);
1476 SendAction(player, creature, action);
1477 break;
1478 }
1479 return true;
1480 }
1481};
1482
1484{
1485public:
1486 npc_steam_tonk() : CreatureScript("npc_steam_tonk") { }
1487
1489 {
1490 npc_steam_tonkAI(Creature* creature) : ScriptedAI(creature) { }
1491
1492 void Reset() OVERRIDE { }
1493 void EnterCombat(Unit* /*who*/) OVERRIDE { }
1494
1495 void OnPossess(bool apply)
1496 {
1497 if (apply)
1498 {
1499 // Initialize the action bar without the melee attack command
1500 me->InitCharmInfo();
1501 me->GetCharmInfo()->InitEmptyActionBar(false);
1502
1503 me->SetReactState(REACT_PASSIVE);
1504 }
1505 else
1506 me->SetReactState(REACT_AGGRESSIVE);
1507 }
1508 };
1509
1511 {
1512 return new npc_steam_tonkAI(creature);
1513 }
1514};
1515
1517{
1519};
1520
1522{
1523public:
1524 npc_tonk_mine() : CreatureScript("npc_tonk_mine") { }
1525
1527 {
1528 npc_tonk_mineAI(Creature* creature) : ScriptedAI(creature)
1529 {
1530 me->SetReactState(REACT_PASSIVE);
1531 }
1532
1534
1536 {
1537 ExplosionTimer = 3000;
1538 }
1539
1540 void EnterCombat(Unit* /*who*/) OVERRIDE { }
1541 void AttackStart(Unit* /*who*/) OVERRIDE { }
1543
1544
1546 {
1547 if (ExplosionTimer <= diff)
1548 {
1550 me->setDeathState(DeathState::DEAD); // unsummon it
1551 }
1552 else
1553 ExplosionTimer -= diff;
1554 }
1555 };
1556
1558 {
1559 return new npc_tonk_mineAI(creature);
1560 }
1561};
1562
1563/*####
1564## npc_brewfest_reveler
1565####*/
1566
1571
1573{
1574 public:
1575 npc_brewfest_reveler() : CreatureScript("npc_brewfest_reveler") { }
1576
1578 {
1579 npc_brewfest_revelerAI(Creature* creature) : ScriptedAI(creature) { }
1580
1581 void ReceiveEmote(Player* player, uint32 emote) OVERRIDE
1582 {
1584 return;
1585
1586 if (emote == TEXT_EMOTE_DANCE)
1587 me->CastSpell(player, SPELL_BREWFEST_TOAST, false);
1588 }
1589 };
1590
1592 {
1593 return new npc_brewfest_revelerAI(creature);
1594 }
1595};
1596
1602
1604{
1605public:
1606 npc_training_dummy() : CreatureScript("npc_training_dummy") { }
1607
1609 {
1611 {
1612 SetCombatMovement(false);
1613 entry = creature->GetEntry();
1614 }
1615
1619
1621 {
1622 me->SetControlled(true, UNIT_STATE_STUNNED);//disable rotate
1623 me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);//imune to knock aways like blast wave
1624
1625 resetTimer = 5000;
1626 despawnTimer = 15000;
1627 }
1628
1630 {
1631 if (!_EnterEvadeMode())
1632 return;
1633
1634 Reset();
1635 }
1636
1637 void DamageTaken(Unit* /*doneBy*/, uint32& damage) OVERRIDE
1638 {
1639 resetTimer = 5000;
1640 damage = 0;
1641 }
1642
1644 {
1645 if (!UpdateVictim())
1646 return;
1647
1648 if (!me->HasUnitState(UNIT_STATE_STUNNED))
1649 me->SetControlled(true, UNIT_STATE_STUNNED);//disable rotate
1650
1652 {
1653 if (resetTimer <= diff)
1654 {
1656 resetTimer = 5000;
1657 }
1658 else
1659 resetTimer -= diff;
1660 return;
1661 }
1662 else
1663 {
1664 if (despawnTimer <= diff)
1665 me->DespawnOrUnsummon();
1666 else
1667 despawnTimer -= diff;
1668 }
1669 }
1670
1672 };
1673
1675 {
1676 return new npc_training_dummyAI(creature);
1677 }
1678};
1679
1680/*######
1681# npc_wormhole
1682######*/
1683
1684#define GOSSIP_ENGINEERING1 "Borean Tundra"
1685#define GOSSIP_ENGINEERING2 "Howling Fjord"
1686#define GOSSIP_ENGINEERING3 "Sholazar Basin"
1687#define GOSSIP_ENGINEERING4 "Icecrown"
1688#define GOSSIP_ENGINEERING5 "Storm Peaks"
1689#define GOSSIP_ENGINEERING6 "Underground..."
1690
1704
1706{
1707 public:
1708 npc_wormhole() : CreatureScript("npc_wormhole") { }
1709
1711 {
1712 npc_wormholeAI(Creature* creature) : PassiveAI(creature) { }
1713
1715 {
1716 _showUnderground = (std::rand() % 100) == 0; // Guessed value, it is really rare though
1717 }
1718
1720 {
1721 return (type == DATA_SHOW_UNDERGROUND && _showUnderground) ? 1 : 0;
1722 }
1723
1724 private:
1726 };
1727
1728 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
1729 {
1730 if (creature->IsSummon())
1731 {
1732 if (player == creature->ToTempSummon()->GetSummoner())
1733 {
1739
1740 if (creature->AI()->GetData(DATA_SHOW_UNDERGROUND))
1742
1743 player->PlayerTalkClass->SendGossipMenu(TEXT_WORMHOLE, creature->GetGUID());
1744 }
1745 }
1746
1747 return true;
1748 }
1749
1750 bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
1751 {
1752 player->PlayerTalkClass->ClearMenus();
1753
1754 switch (action)
1755 {
1756 case GOSSIP_ACTION_INFO_DEF + 1: // Borean Tundra
1757 player->CLOSE_GOSSIP_MENU();
1758 creature->CastSpell(player, SPELL_BOREAN_TUNDRA, false);
1759 break;
1760 case GOSSIP_ACTION_INFO_DEF + 2: // Howling Fjord
1761 player->CLOSE_GOSSIP_MENU();
1762 creature->CastSpell(player, SPELL_HOWLING_FJORD, false);
1763 break;
1764 case GOSSIP_ACTION_INFO_DEF + 3: // Sholazar Basin
1765 player->CLOSE_GOSSIP_MENU();
1766 creature->CastSpell(player, SPELL_SHOLAZAR_BASIN, false);
1767 break;
1768 case GOSSIP_ACTION_INFO_DEF + 4: // Icecrown
1769 player->CLOSE_GOSSIP_MENU();
1770 creature->CastSpell(player, SPELL_ICECROWN, false);
1771 break;
1772 case GOSSIP_ACTION_INFO_DEF + 5: // Storm peaks
1773 player->CLOSE_GOSSIP_MENU();
1774 creature->CastSpell(player, SPELL_STORM_PEAKS, false);
1775 break;
1776 case GOSSIP_ACTION_INFO_DEF + 6: // Underground
1777 player->CLOSE_GOSSIP_MENU();
1778 creature->CastSpell(player, SPELL_UNDERGROUND, false);
1779 break;
1780 }
1781
1782 return true;
1783 }
1784
1786 {
1787 return new npc_wormholeAI(creature);
1788 }
1789};
1790
1791/*######
1792## npc_pet_trainer
1793######*/
1794
1802
1803#define GOSSIP_PET1 "How do I train my pet?"
1804#define GOSSIP_PET2 "I wish to untrain my pet."
1805#define GOSSIP_PET_CONFIRM "Yes, please do."
1806
1808{
1809public:
1810 npc_pet_trainer() : CreatureScript("npc_pet_trainer") { }
1811
1812 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
1813 {
1814 if (creature->IsQuestGiver())
1815 player->PrepareQuestMenu(creature->GetGUID());
1816
1817 if (player->getClass() == CLASS_HUNTER)
1818 {
1820 if (player->GetPet() && player->GetPet()->getPetType() == PetType::HUNTER_PET)
1822
1823 player->PlayerTalkClass->SendGossipMenu(TEXT_ISHUNTER, creature->GetGUID());
1824 return true;
1825 }
1826 player->PlayerTalkClass->SendGossipMenu(TEXT_NOTHUNTER, creature->GetGUID());
1827 return true;
1828 }
1829
1830 bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) OVERRIDE
1831 {
1832 player->PlayerTalkClass->ClearMenus();
1833 switch (action)
1834 {
1835 case GOSSIP_ACTION_INFO_DEF + 1:
1836 player->PlayerTalkClass->SendGossipMenu(TEXT_PETINFO, creature->GetGUID());
1837 break;
1838 case GOSSIP_ACTION_INFO_DEF + 2:
1839 {
1841 player->PlayerTalkClass->SendGossipMenu(TEXT_CONFIRM, creature->GetGUID());
1842 }
1843 break;
1844 case GOSSIP_ACTION_INFO_DEF + 3:
1845 {
1846 player->ResetPetTalents();
1847 player->CLOSE_GOSSIP_MENU();
1848 }
1849 break;
1850 }
1851 return true;
1852 }
1853};
1854
1855/*######
1856## npc_locksmith
1857######*/
1858
1891
1892#define GOSSIP_LOST_ARCATRAZ_KEY "I've lost my key to the Arcatraz."
1893#define GOSSIP_LOST_SHADOWFORGE_KEY "I've lost my key to the Blackrock Depths."
1894#define GOSSIP_LOST_SKELETON_KEY "I've lost my key to the Scholomance."
1895#define GOSSIP_LOST_SHATTERED_HALLS_KEY "I've lost my key to the Shattered Halls."
1896#define GOSSIP_LOST_THE_MASTERS_KEY "I've lost my key to the Karazhan."
1897#define GOSSIP_LOST_VIOLET_HOLD_KEY "I've lost my key to the Violet Hold."
1898#define GOSSIP_LOST_ESSENCE_INFUSED_MOONSTONE "I've lost my Essence-Infused Moonstone."
1899#define GOSSIP_LOST_KEY_TO_THE_FOCUSING_IRIS "I've lost my Key to the Focusing Iris."
1900#define GOSSIP_LOST_HC_KEY_TO_THE_FOCUSING_IRIS "I've lost my Heroic Key to the Focusing Iris."
1901
1903{
1904public:
1905 npc_locksmith() : CreatureScript("npc_locksmith") { }
1906
1907 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
1908 {
1909 // Arcatraz Key
1910 if (player->GetQuestRewardStatus(QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ) && !player->HasItemCount(ITEM_ARCATRAZ_KEY, 1, true))
1912
1913 // Shadowforge Key
1914 if (player->GetQuestRewardStatus(QUEST_DARK_IRON_LEGACY) && !player->HasItemCount(ITEM_SHADOWFORGE_KEY, 1, true))
1916
1917 // Skeleton Key
1918 if ((player->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_A) || player->GetQuestRewardStatus(QUEST_THE_KEY_TO_SCHOLOMANCE_H)) &&
1919 !player->HasItemCount(ITEM_SKELETON_KEY, 1, true))
1921
1922 // Shatered Halls Key
1923 if ((player->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_A) || player->GetQuestRewardStatus(QUEST_HOTTER_THAN_HELL_H)) &&
1924 !player->HasItemCount(ITEM_SHATTERED_HALLS_KEY, 1, true))
1926
1927 // Master's Key
1928 if (player->GetQuestRewardStatus(QUEST_RETURN_TO_KHAGDAR) && !player->HasItemCount(ITEM_THE_MASTERS_KEY, 1, true))
1930
1931 // Violet Hold Key
1932 if (player->GetQuestRewardStatus(QUEST_CONTAINMENT) && !player->HasItemCount(ITEM_VIOLET_HOLD_KEY, 1, true))
1934
1935 // Essence-Infused Moonstone
1936 if (player->GetQuestRewardStatus(QUEST_ETERNAL_VIGILANCE) && !player->HasItemCount(ITEM_ESSENCE_INFUSED_MOONSTONE, 1, true))
1938
1939 // Key to the Focusing Iris
1940 if (player->GetQuestRewardStatus(QUEST_KEY_TO_THE_FOCUSING_IRIS) && !player->HasItemCount(ITEM_KEY_TO_THE_FOCUSING_IRIS, 1, true))
1942
1943 // Heroic Key to the Focusing Iris
1944 if (player->GetQuestRewardStatus(QUEST_HC_KEY_TO_THE_FOCUSING_IRIS) && !player->HasItemCount(ITEM_HC_KEY_TO_THE_FOCUSING_IRIS, 1, true))
1946
1947 player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
1948
1949 return true;
1950 }
1951
1952 bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) OVERRIDE
1953 {
1954 player->PlayerTalkClass->ClearMenus();
1955 switch (action)
1956 {
1957 case GOSSIP_ACTION_INFO_DEF + 1:
1958 player->CLOSE_GOSSIP_MENU();
1959 player->CastSpell(player, SPELL_ARCATRAZ_KEY, false);
1960 break;
1961 case GOSSIP_ACTION_INFO_DEF + 2:
1962 player->CLOSE_GOSSIP_MENU();
1963 player->CastSpell(player, SPELL_SHADOWFORGE_KEY, false);
1964 break;
1965 case GOSSIP_ACTION_INFO_DEF + 3:
1966 player->CLOSE_GOSSIP_MENU();
1967 player->CastSpell(player, SPELL_SKELETON_KEY, false);
1968 break;
1969 case GOSSIP_ACTION_INFO_DEF + 4:
1970 player->CLOSE_GOSSIP_MENU();
1971 player->CastSpell(player, SPELL_SHATTERED_HALLS_KEY, false);
1972 break;
1973 case GOSSIP_ACTION_INFO_DEF + 5:
1974 player->CLOSE_GOSSIP_MENU();
1975 player->CastSpell(player, SPELL_THE_MASTERS_KEY, false);
1976 break;
1977 case GOSSIP_ACTION_INFO_DEF + 6:
1978 player->CLOSE_GOSSIP_MENU();
1979 player->CastSpell(player, SPELL_VIOLET_HOLD_KEY, false);
1980 break;
1981 case GOSSIP_ACTION_INFO_DEF + 7:
1982 player->CLOSE_GOSSIP_MENU();
1983 player->CastSpell(player, SPELL_ESSENCE_INFUSED_MOONSTONE, false);
1984 break;
1985 case GOSSIP_ACTION_INFO_DEF + 8:
1986 player->CLOSE_GOSSIP_MENU();
1987 player->AddItem(ITEM_KEY_TO_THE_FOCUSING_IRIS, 1);
1988 break;
1989 case GOSSIP_ACTION_INFO_DEF + 9:
1990 player->CLOSE_GOSSIP_MENU();
1991 player->AddItem(ITEM_HC_KEY_TO_THE_FOCUSING_IRIS, 1);
1992 break;
1993 }
1994 return true;
1995 }
1996};
1997
1998/*######
1999## npc_experience
2000######*/
2001
2002#define EXP_COST 100000 //10 00 00 copper (10golds)
2003#define GOSSIP_TEXT_EXP 14736
2004#define GOSSIP_XP_OFF "I no longer wish to gain experience."
2005#define GOSSIP_XP_ON "I wish to start gaining experience again."
2006
2008{
2009public:
2010 npc_experience() : CreatureScript("npc_experience") { }
2011
2012 bool OnGossipHello(Player* player, Creature* creature) OVERRIDE
2013 {
2016 player->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_EXP, creature->GetGUID());
2017 return true;
2018 }
2019
2020 bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) OVERRIDE
2021 {
2022 player->PlayerTalkClass->ClearMenus();
2023 bool noXPGain = player->HasFlag(PLAYER_FIELD_PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); //PLAYER_FIELD_FLAGS_NO_XP_GAIN
2024 bool doSwitch = false;
2025
2026 switch (action)
2027 {
2028 case GOSSIP_ACTION_INFO_DEF + 1://xp off
2029 {
2030 if (!noXPGain)//does gain xp
2031 doSwitch = true;//switch to don't gain xp
2032 }
2033 break;
2034 case GOSSIP_ACTION_INFO_DEF + 2://xp on
2035 {
2036 if (noXPGain)//doesn't gain xp
2037 doSwitch = true;//switch to gain xp
2038 }
2039 break;
2040 }
2041 if (doSwitch)
2042 {
2043 if (!player->HasEnoughMoney(uint64(EXP_COST)))
2044 player->SendBuyFailed(BuyResult::BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0);
2045 else if (noXPGain)
2046 {
2047 player->ModifyMoney(-int64(EXP_COST));
2049 }
2050 else if (!noXPGain)
2051 {
2052 player->ModifyMoney(-EXP_COST);
2054 }
2055 }
2056 player->PlayerTalkClass->SendCloseGossip();
2057 return true;
2058 }
2059};
2060
2062{
2063 NPC_OMEN = 15467,
2077
2091
2099
2113
2116};
2117
2118Position omenSummonPos = {7558.993f, -2839.999f, 450.0214f, 4.46f};
2119
2121{
2122public:
2123 npc_firework() : CreatureScript("npc_firework") { }
2124
2126 {
2127 npc_fireworkAI(Creature* creature) : ScriptedAI(creature) { }
2128
2130 {
2131 switch (me->GetEntry())
2132 {
2133 case NPC_FIREWORK_BLUE:
2134 case NPC_FIREWORK_GREEN:
2136 case NPC_FIREWORK_RED:
2138 case NPC_FIREWORK_WHITE:
2145 return false;
2146 case NPC_CLUSTER_BLUE:
2147 case NPC_CLUSTER_GREEN:
2148 case NPC_CLUSTER_PURPLE:
2149 case NPC_CLUSTER_RED:
2150 case NPC_CLUSTER_YELLOW:
2151 case NPC_CLUSTER_WHITE:
2158 case NPC_CLUSTER_ELUNE:
2159 default:
2160 return true;
2161 }
2162 }
2163
2165 {
2166 GameObject* launcher = NULL;
2167
2168 if (isCluster())
2169 {
2174
2175 if (launcher1)
2176 launcher = launcher1;
2177 else if (launcher2)
2178 launcher = launcher2;
2179 else if (launcher3)
2180 launcher = launcher3;
2181 else if (launcher4)
2182 launcher = launcher4;
2183 }
2184 else
2185 {
2189
2190 if (launcher1)
2191 launcher = launcher1;
2192 else if (launcher2)
2193 launcher = launcher2;
2194 else if (launcher3)
2195 launcher = launcher3;
2196 }
2197
2198 return launcher;
2199 }
2200
2202 {
2203 switch (entry)
2204 {
2205 case NPC_FIREWORK_BLUE:
2206 return SPELL_ROCKET_BLUE;
2207 case NPC_FIREWORK_GREEN:
2208 return SPELL_ROCKET_GREEN;
2210 return SPELL_ROCKET_PURPLE;
2211 case NPC_FIREWORK_RED:
2212 return SPELL_ROCKET_RED;
2214 return SPELL_ROCKET_YELLOW;
2215 case NPC_FIREWORK_WHITE:
2216 return SPELL_ROCKET_WHITE;
2218 return SPELL_ROCKET_BIG_BLUE;
2224 return SPELL_ROCKET_BIG_RED;
2229 default:
2230 return 0;
2231 }
2232 }
2233
2235 {
2236 uint32 spellId = 0;
2237
2238 switch (me->GetEntry())
2239 {
2240 case NPC_CLUSTER_BLUE:
2242 break;
2243 case NPC_CLUSTER_GREEN:
2245 break;
2246 case NPC_CLUSTER_PURPLE:
2248 break;
2249 case NPC_CLUSTER_RED:
2251 break;
2252 case NPC_CLUSTER_YELLOW:
2254 break;
2255 case NPC_CLUSTER_WHITE:
2257 break;
2260 break;
2263 break;
2266 break;
2269 break;
2272 break;
2275 break;
2276 case NPC_CLUSTER_ELUNE:
2277 spellId = GetFireworkSpell(std::rand() % NPC_FIREWORK_WHITE + NPC_FIREWORK_BLUE);
2278 break;
2279 }
2280
2281 const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId);
2282
2283 if (spellInfo && spellInfo->Effects[0].Effect == SPELL_EFFECT_SUMMON_OBJECT_WILD)
2284 return spellInfo->Effects[0].MiscValue;
2285
2286 return 0;
2287 }
2288
2290 {
2291 if (GameObject* launcher = FindNearestLauncher())
2292 {
2293 launcher->SendCustomAnim(ANIM_GO_LAUNCH_FIREWORK);
2294 me->SetOrientation(launcher->GetOrientation() + M_PI/2);
2295 }
2296 else
2297 return;
2298
2299 if (isCluster())
2300 {
2301 // Check if we are near Elune'ara lake south, if so try to summon Omen or a minion
2302 if (me->GetZoneId() == ZONE_MOONGLADE)
2303 {
2304 if (!me->FindNearestCreature(NPC_OMEN, 100.0f, false) && me->GetDistance2d(omenSummonPos.GetPositionX(), omenSummonPos.GetPositionY()) <= 100.0f)
2305 {
2306 switch (std::rand() % 9)
2307 {
2308 case 0:
2309 case 1:
2310 case 2:
2311 case 3:
2312 if (Creature* minion = me->SummonCreature(NPC_MINION_OF_OMEN, me->GetPositionX()+frand(-5.0f, 5.0f), me->GetPositionY()+frand(-5.0f, 5.0f), me->GetPositionZ(), 0.0f, TempSummonType::TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000))
2313 minion->AI()->AttackStart(me->SelectNearestPlayer(20.0f));
2314 break;
2315 case 9:
2316 me->SummonCreature(NPC_OMEN, omenSummonPos);
2317 break;
2318 }
2319 }
2320 }
2321 if (me->GetEntry() == NPC_CLUSTER_ELUNE)
2323
2324 float displacement = 0.7f;
2325 for (uint8 i = 0; i < 4; i++)
2326 me->SummonGameObject(GetFireworkGameObjectId(), me->GetPositionX() + (i%2 == 0 ? displacement : -displacement), me->GetPositionY() + (i > 1 ? displacement : -displacement), me->GetPositionZ() + 4.0f, me->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 1);
2327 }
2328 else
2329 //me->CastSpell(me, GetFireworkSpell(me->GetEntry()), true);
2330 me->CastSpell(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), GetFireworkSpell(me->GetEntry()), true);
2331 }
2332 };
2333
2335 {
2336 return new npc_fireworkAI(creature);
2337 }
2338};
2339
2340/*#####
2341# npc_spring_rabbit
2342#####*/
2343
2353
2355{
2356public:
2357 npc_spring_rabbit() : CreatureScript("npc_spring_rabbit") { }
2358
2360 {
2362 {
2363 bool inLove = false;
2364 uint32 jumpTimer = 0;
2365 uint32 bunnyTimer = 0;
2366 uint32 searchTimer = 0;
2367 uint64 rabbitGUID = 0;
2368 }
2369
2371 {
2372 inLove = false;
2373 rabbitGUID = 0;
2374 jumpTimer = std::rand() % 10000 + 5000;
2375 bunnyTimer = std::rand() % 20000 + 10000;
2376 searchTimer = std::rand() % 10000 + 5000;
2377 if (Unit* owner = me->GetOwner())
2378 me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
2379 }
2380
2381 void EnterCombat(Unit* /*who*/) OVERRIDE { }
2382
2383 void DoAction(int32 /*param*/) OVERRIDE
2384 {
2385 inLove = true;
2386 if (Unit* owner = me->GetOwner())
2387 owner->CastSpell(owner, SPELL_SPRING_FLING, true);
2388 }
2389
2391 {
2392 if (inLove)
2393 {
2394 if (jumpTimer <= diff)
2395 {
2396 if (Unit* rabbit = Unit::GetUnit(*me, rabbitGUID))
2398 jumpTimer = std::rand() % 10000 + 5000;
2399 } else jumpTimer -= diff;
2400
2401 if (bunnyTimer <= diff)
2402 {
2404 bunnyTimer = std::rand() % 40000 + 20000;
2405 } else bunnyTimer -= diff;
2406 }
2407 else
2408 {
2409 if (searchTimer <= diff)
2410 {
2411 if (Creature* rabbit = me->FindNearestCreature(NPC_SPRING_RABBIT, 10.0f))
2412 {
2413 if (rabbit == me || rabbit->HasAura(SPELL_SPRING_RABBIT_IN_LOVE))
2414 return;
2415
2417 DoAction(1);
2418 rabbit->AddAura(SPELL_SPRING_RABBIT_IN_LOVE, rabbit);
2419 rabbit->AI()->DoAction(1);
2420 rabbit->CastSpell(rabbit, SPELL_SPRING_RABBIT_JUMP, true);
2421 rabbitGUID = rabbit->GetGUID();
2422 }
2423 searchTimer = std::rand() % 10000 + 5000;
2424 } else searchTimer -= diff;
2425 }
2426 }
2427
2428 private:
2434 };
2435
2437 {
2438 return new npc_spring_rabbitAI(creature);
2439 }
2440};
2441
2442#define GOSSIP_TEXT_EXP 14736
2443#define GOSSIP_CHOOSE_FACTION "I would like to choose my faction"
2444
2446{
2447public:
2448 npc_Spirit_of_Master_Shang_Xi() : CreatureScript("npc_Spirit_of_Master_Shang_Xi") { }
2449
2450 bool OnGossipHello(Player* player, Creature* creature)
2451 {
2452 if (creature->IsQuestGiver())
2453 player->PrepareQuestMenu(creature->GetGUID());
2454
2455 if (player->getRace() == RACE_PANDAREN_NEUTRAL)
2456 {
2457 if (player->GetQuestStatus(31450) == QUEST_STATUS_INCOMPLETE)
2459 }
2461 return true;
2462 }
2463
2464 bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action)
2465 {
2466 if (action == GOSSIP_ACTION_INFO_DEF + 1)
2468
2470 return true;
2471 }
2472};
2473
2475{
2476public:
2477 npc_training_target() : CreatureScript("npc_training_target") { }
2478
2480 {
2482 {
2483 SetCombatMovement(false);
2484 }
2485
2486 void Reset() override
2487 {
2488 me->SetReactState(REACT_PASSIVE);
2489 // disable rotate
2490 me->SetControlled(true, UNIT_STATE_STUNNED);
2491 }
2492
2493 void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override
2494 {
2495 }
2496
2497 void EnterEvadeMode() override
2498 {
2499 if (_EnterEvadeMode())
2500 Reset();
2501 }
2502
2503 void UpdateAI(uint32 diff) override
2504 {
2505 if (!UpdateVictim())
2506 return;
2507
2508 if (!me->HasUnitState(UNIT_STATE_STUNNED))
2509 me->SetControlled(true, UNIT_STATE_STUNNED);
2510 }
2511 };
2512
2514 {
2515 return new npc_training_targetAI(creature);
2516 }
2517};
2518
2519
2521{
2522 new npc_air_force_bots();
2523 new npc_lunaclaw_spirit();
2524 new npc_chicken_cluck();
2525 new npc_dancing_flames();
2526 new npc_doctor();
2527 new npc_injured_patient();
2529 new npc_guardian();
2530 new npc_mount_vendor();
2531 new npc_rogue_trainer();
2532 new npc_sayge();
2533 new npc_steam_tonk();
2534 new npc_tonk_mine();
2536 new npc_training_dummy();
2537 new npc_wormhole();
2538 new npc_pet_trainer();
2539 new npc_locksmith();
2540 new npc_experience();
2541 new npc_firework();
2543 new npc_spring_rabbit();
2544 new npc_training_target();
2545}
#define M_PI
Definition Common.h:192
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
std::int64_t int64
Definition Define.h:72
bool IsHolidayActive(HolidayIds id)
@ GOSSIP_ICON_CHAT
Definition GossipDef.h:46
@ GOSSIP_ICON_TRAINER
Definition GossipDef.h:49
@ GOSSIP_ICON_VENDOR
Definition GossipDef.h:47
@ GOSSIP_OPTION_UNLEARN_SPEC
Definition GossipDef.h:40
@ GOSSIP_OPTION_UNLEARNTALENTS
Definition GossipDef.h:36
@ GOSSIP_OPTION_LEARNDUALSPEC
Definition GossipDef.h:38
@ BUY_ERR_NOT_ENOUGHT_MONEY
Definition Item.h:128
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
Definition Object.h:71
@ TEMPSUMMON_CORPSE_TIMED_DESPAWN
Definition Object.h:73
#define PET_FOLLOW_ANGLE
Definition PetDefines.h:58
#define PET_FOLLOW_DIST
Definition PetDefines.h:57
@ HUNTER_PET
Definition PetDefines.h:12
@ PLAYER_FLAGS_NO_XP_GAIN
Definition Player.h:562
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:89
@ QUEST_STATUS_NONE
Definition QuestDef.h:86
@ QUEST_STATUS_COMPLETE
Definition QuestDef.h:87
GameObject * GetClosestGameObjectWithEntry(WorldObject *source, uint32 entry, float maxSearchRange)
#define CAST_AI(a, b)
#define GOSSIP_TEXT_TRAIN
#define GOSSIP_TEXT_BROWSE_GOODS
@ GOSSIP_SENDER_MAIN
@ GOSSIP_ACTION_TRADE
@ GOSSIP_ACTION_TRAIN
@ GOSSIP_ACTION_INFO_DEF
@ EMOTE_ONESHOT_SHY
@ EMOTE_ONESHOT_LAUGH
@ EMOTE_ONESHOT_BOW
@ EMOTE_ONESHOT_DANCE
@ EMOTE_ONESHOT_WAVE
@ SPELL_EFFECT_KNOCK_BACK
@ SPELL_EFFECT_SUMMON_OBJECT_WILD
@ TEXT_EMOTE_BOW
@ TEXT_EMOTE_CHICKEN
@ TEXT_EMOTE_CHEER
@ TEXT_EMOTE_DANCE
@ TEXT_EMOTE_KISS
@ TEXT_EMOTE_WAVE
@ TEXT_EMOTE_JOKE
@ CLASS_HUNTER
@ CLASS_ROGUE
@ IMMUNITY_EFFECT
@ ALLIANCE
@ HORDE
@ REP_EXALTED
@ RACE_TROLL
@ RACE_UNDEAD_PLAYER
@ RACE_PANDAREN_NEUTRAL
@ RACE_ORC
@ RACE_DRAENEI
@ RACE_NIGHTELF
@ RACE_BLOODELF
@ RACE_DWARF
@ RACE_GNOME
@ RACE_HUMAN
@ RACE_TAUREN
#define sSpellMgr
Definition SpellMgr.h:744
@ UNIT_NPC_FLAG_QUESTGIVER
Definition Unit.h:688
@ JUST_DIED
Definition Unit.h:504
@ UNIT_STAND_STATE_DEAD
Definition Unit.h:169
@ UNIT_STAND_STATE_KNEEL
Definition Unit.h:170
@ UNIT_STAND_STATE_STAND
Definition Unit.h:162
@ UNIT_STATE_STUNNED
Definition Unit.h:515
@ REACT_PASSIVE
Definition Unit.h:1156
@ REACT_AGGRESSIVE
Definition Unit.h:1158
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FLAG_IN_COMBAT
Definition Unit.h:644
@ UNIT_FLAG_PVP_ATTACKABLE
Definition Unit.h:628
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ UNIT_FIELD_NPC_FLAGS
@ UNIT_FIELD_ANIM_TIER
@ UNIT_FIELD_FLAGS
@ OBJECT_FIELD_DYNAMIC_FLAGS
@ PLAYER_FIELD_PLAYER_FLAGS
float frand(float min, float max)
Definition Util.cpp:39
int32 GetDuration() const
Definition SpellAuras.h:119
bool _EnterEvadeMode()
void Talk(uint8 id, WorldObject const *whisperTarget=NULL)
bool UpdateVictim()
virtual void EnterEvadeMode()
CreatureAI * AI() const
Definition Creature.h:483
CreatureScript(const char *name)
static Player * GetPlayer(WorldObject const &, uint64 guid)
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
uint32 GetEntry() const
Definition Object.h:125
PassiveAI(Creature *c)
Definition PassiveAI.cpp:10
void ShowNeutralPlayerFactionSelectUI()
Definition Player.cpp:19884
void PrepareQuestMenu(uint64 guid)
void AreaExploredOrEventHappens(uint32 questId)
QuestStatus GetQuestStatus(uint32 quest_id) const
void FailQuest(uint32 quest_id)
PlayerMenu * PlayerTalkClass
Definition Player.h:2680
void SendGossipMenu(uint32 titleTextId, uint64 objectGUID) const
void SendCloseGossip() const
SpellEffectInfo Effects[MAX_SPELL_EFFECTS]
Definition SpellInfo.h:255
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:28
void DoCast(uint32 spellId)
Definition UnitAI.cpp:110
void DoCastVictim(uint32 spellId, bool triggered=false)
Definition UnitAI.cpp:168
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:16
Definition Unit.h:1367
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)
bool IsAlive() const
Definition Unit.h:2032
bool IsQuestGiver() const
Definition Unit.h:1833
static Creature * GetCreature(WorldObject &object, uint64 guid)
Definition Unit.cpp:4905
static Unit * GetUnit(WorldObject &object, uint64 guid)
Definition Unit.cpp:4895
Unit * GetVictim() const
Definition Unit.h:1468
bool IsFlying() const
Definition Unit.h:2780
uint8 getRace() const
Definition Unit.h:1535
bool OnGossipSelect(Player *player, Creature *, uint32, uint32 action)
bool OnGossipHello(Player *player, Creature *creature)
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnQuestComplete(Player *, Creature *creature, Quest const *quest) OVERRIDE
bool OnQuestAccept(Player *, Creature *creature, Quest const *quest) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnQuestAccept(Player *player, Creature *creature, Quest const *quest) OVERRIDE
bool OnGossipHello(Player *player, Creature *creature) OVERRIDE
bool OnGossipSelect(Player *player, Creature *, uint32, uint32 action) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnGossipSelect(Player *player, Creature *, uint32, uint32 action) 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 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 OnGossipHello(Player *player, Creature *creature) OVERRIDE
bool OnGossipSelect(Player *player, Creature *creature, uint32 sender, uint32 action) OVERRIDE
bool OnGossipHello(Player *player, Creature *creature) OVERRIDE
void SendAction(Player *player, Creature *creature, uint32 action)
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
bool OnGossipSelect(Player *player, Creature *creature, uint32, uint32 action) OVERRIDE
bool OnGossipHello(Player *player, Creature *creature) OVERRIDE
CreatureAI * GetAI(Creature *creature) const OVERRIDE
#define sWorld
Definition World.h:910
@ CONFIG_MIN_DUALSPEC_LEVEL
Definition World.h:226
@ TEXT_ID_PROGRESS
#define GOSSIP_SENDACTION_SAYGE7
TrainingDummy
@ NPC_TARGET_DUMMY
@ NPC_ADVANCED_TARGET_DUMMY
#define GOSSIP_CHOOSE_FACTION
#define GOSSIP_HELLO_ROGUE1
#define A_RUNTOX
#define GOSSIP_SENDACTION_SAYGE15
#define GOSSIP_ITEM_GRANT
float const RANGE_GUARDS_MARK
#define GOSSIP_ENGINEERING1
#define A_RUNTOZ
WormholeSpells
@ DATA_SHOW_UNDERGROUND
@ SPELL_STORM_PEAKS
@ SPELL_UNDERGROUND
@ SPELL_SHOLAZAR_BASIN
@ SPELL_BOREAN_TUNDRA
@ SPELL_HOWLING_FJORD
@ TEXT_WORMHOLE
@ SPELL_ICECROWN
#define GOSSIP_SENDACTION_SAYGE12
#define GOSSIP_ENGINEERING2
#define H_RUNTOX
@ SPELL_TONK_MINE_DETONATE
SpawnType
@ SPAWNTYPE_TRIPWIRE_ROOFTOP
@ SPAWNTYPE_ALARMBOT
#define GOSSIP_LOST_THE_MASTERS_KEY
#define GOSSIP_LOST_SKELETON_KEY
@ SPELL_DMG
@ SPELL_FORTUNE
@ SPELL_STM
@ SPELL_AGI
@ SPELL_ARM
@ SPELL_INT
@ SPELL_RES
@ SPELL_STR
@ SPELL_SPI
PetTrainer
@ TEXT_ISHUNTER
@ TEXT_CONFIRM
@ TEXT_PETINFO
@ TEXT_NOTHUNTER
#define GOSSIP_PET_CONFIRM
#define GOSSIP_HELLO_ROGUE3
Garments
@ QUEST_DARKNESS
@ SAY_THANKS
@ SAY_GOODBYE
@ QUEST_MOON
@ QUEST_LIGHT_1
@ SAY_HEALED
@ ENTRY_SHAYA
@ ENTRY_DOLF
@ ENTRY_DG_KEL
@ QUEST_SPIRIT
@ SPELL_FORTITUDE_R1
@ QUEST_LIGHT_2
@ ENTRY_ROBERTS
@ ENTRY_KORJA
@ SPELL_LESSER_HEAL_R2
#define GOSSIP_SENDACTION_SAYGE16
#define GOSSIP_HELLO_SAYGE
Fireworks
@ SPELL_ROCKET_BIG_RED
@ ANIM_GO_LAUNCH_FIREWORK
@ NPC_FIREWORK_BIG_YELLOW
@ NPC_FIREWORK_BIG_WHITE
@ NPC_FIREWORK_BIG_GREEN
@ NPC_FIREWORK_GREEN
@ NPC_CLUSTER_RED
@ NPC_FIREWORK_BIG_RED
@ ZONE_MOONGLADE
@ SPELL_ROCKET_YELLOW
@ GO_CLUSTER_LAUNCHER_1
@ GO_CLUSTER_LAUNCHER_3
@ NPC_CLUSTER_WHITE
@ GO_FIREWORK_LAUNCHER_2
@ GO_FIREWORK_LAUNCHER_1
@ NPC_FIREWORK_BIG_PURPLE
@ NPC_CLUSTER_BIG_YELLOW
@ NPC_CLUSTER_PURPLE
@ NPC_OMEN
@ NPC_CLUSTER_YELLOW
@ NPC_FIREWORK_WHITE
@ GO_CLUSTER_LAUNCHER_2
@ NPC_CLUSTER_BIG_WHITE
@ NPC_CLUSTER_GREEN
@ NPC_FIREWORK_RED
@ NPC_FIREWORK_PURPLE
@ NPC_FIREWORK_BIG_BLUE
@ NPC_CLUSTER_BIG_PURPLE
@ SPELL_ROCKET_BIG_WHITE
@ SPELL_ROCKET_RED
@ SPELL_LUNAR_FORTUNE
@ NPC_FIREWORK_YELLOW
@ GO_CLUSTER_LAUNCHER_4
@ NPC_CLUSTER_BIG_GREEN
@ SPELL_ROCKET_PURPLE
@ SPELL_ROCKET_BLUE
@ NPC_CLUSTER_BLUE
@ SPELL_ROCKET_BIG_YELLOW
@ NPC_MINION_OF_OMEN
@ SPELL_ROCKET_WHITE
@ SPELL_ROCKET_BIG_BLUE
@ NPC_FIREWORK_BLUE
@ SPELL_ROCKET_GREEN
@ SPELL_ROCKET_BIG_GREEN
@ NPC_CLUSTER_BIG_BLUE
@ NPC_CLUSTER_BIG_RED
@ GO_FIREWORK_LAUNCHER_3
@ SPELL_ROCKET_BIG_PURPLE
@ NPC_CLUSTER_ELUNE
#define GOSSIP_XP_OFF
#define GOSSIP_SENDACTION_SAYGE11
#define GOSSIP_SENDACTION_SAYGE4
#define GOSSIP_ENGINEERING3
#define GOSSIP_SENDACTION_SAYGE14
#define GOSSIP_LOST_SHADOWFORGE_KEY
#define GOSSIP_SENDACTION_SAYGE9
#define GOSSIP_SENDACTION_SAYGE6
#define EXP_COST
AirFoceBots
@ SPELL_GUARDS_MARK
@ AURA_DURATION_TIME_LEFT
Position omenSummonPos
#define GOSSIP_SENDACTION_SAYGE17
#define A_RUNTOY
BrewfestReveler
@ SPELL_BREWFEST_TOAST
@ ALLIANCE_COORDS
@ SAY_DOC
@ HORDE_COORDS
@ DOCTOR_HORDE
@ DOCTOR_ALLIANCE
LockSmith
@ ITEM_VIOLET_HOLD_KEY
@ ITEM_SHADOWFORGE_KEY
@ QUEST_CONTAINMENT
@ QUEST_RETURN_TO_KHAGDAR
@ QUEST_THE_KEY_TO_SCHOLOMANCE_H
@ SPELL_ESSENCE_INFUSED_MOONSTONE
@ QUEST_HOTTER_THAN_HELL_H
@ QUEST_HOW_TO_BRAKE_IN_TO_THE_ARCATRAZ
@ ITEM_THE_MASTERS_KEY
@ QUEST_DARK_IRON_LEGACY
@ SPELL_SHATTERED_HALLS_KEY
@ ITEM_ESSENCE_INFUSED_MOONSTONE
@ QUEST_THE_KEY_TO_SCHOLOMANCE_A
@ SPELL_THE_MASTERS_KEY
@ QUEST_ETERNAL_VIGILANCE
@ ITEM_SKELETON_KEY
@ ITEM_SHATTERED_HALLS_KEY
@ ITEM_ARCATRAZ_KEY
@ SPELL_SHADOWFORGE_KEY
@ QUEST_HC_KEY_TO_THE_FOCUSING_IRIS
@ QUEST_HOTTER_THAN_HELL_A
@ QUEST_KEY_TO_THE_FOCUSING_IRIS
@ SPELL_VIOLET_HOLD_KEY
@ SPELL_ARCATRAZ_KEY
@ ITEM_HC_KEY_TO_THE_FOCUSING_IRIS
@ SPELL_SKELETON_KEY
@ ITEM_KEY_TO_THE_FOCUSING_IRIS
#define GOSSIP_SENDACTION_SAYGE8
#define GOSSIP_SENDACTION_SAYGE13
#define GOSSIP_SENDACTION_SAYGE1
float const RANGE_TRIPWIRE
DancingFlames
@ SPELL_FIERY_AURA
@ SPELL_SEDUCTION
@ SPELL_BRAZIER
#define GOSSIP_LOST_SHATTERED_HALLS_KEY
#define GOSSIP_ENGINEERING6
ChickenCluck
@ QUEST_CLUCK
@ EMOTE_HELLO_A
@ FACTION_CHICKEN
@ EMOTE_HELLO_H
@ FACTION_FRIENDLY
@ EMOTE_CLUCK_TEXT
rabbitSpells
@ NPC_SPRING_RABBIT
@ SPELL_SPRING_RABBIT_WANDER
@ SPELL_SPRING_FLING
@ SPELL_SPRING_RABBIT_JUMP
@ SPELL_SPRING_RABBIT_IN_LOVE
@ SPELL_SUMMON_BABY_BUNNY
uint32 const AllianceSoldierId[3]
#define GOSSIP_TEXT_EXP
void AddSC_npcs_special()
#define GOSSIP_HELLO_ROGUE2
#define GOSSIP_LOST_VIOLET_HOLD_KEY
SpawnAssociation spawnAssociations[]
#define GOSSIP_XP_ON
#define H_RUNTOY
#define GOSSIP_PET1
#define GOSSIP_SENDACTION_SAYGE10
LunaclawSpirit
@ QUEST_BODY_HEART_A
@ TEXT_ID_PROGRESS
@ QUEST_BODY_HEART_H
@ TEXT_ID_DEFAULT
static Location HordeCoords[]
uint32 const HordeSoldierId[3]
#define GOSSIP_ENGINEERING4
#define GOSSIP_SENDACTION_SAYGE5
#define GOSSIP_LOST_HC_KEY_TO_THE_FOCUSING_IRIS
#define GOSSIP_ENGINEERING5
#define GOSSIP_SENDACTION_SAYGE3
#define GOSSIP_HELLO_ROGUE4
#define GOSSIP_LOST_KEY_TO_THE_FOCUSING_IRIS
#define H_RUNTOZ
#define GOSSIP_LOST_ESSENCE_INFUSED_MOONSTONE
#define GOSSIP_LOST_ARCATRAZ_KEY
static Location AllianceCoords[]
#define GOSSIP_PET2
#define GOSSIP_SENDACTION_SAYGE2
GuardianSpells
@ SPELL_DEATHTOUCH
float y
Definition chapter5.cpp:210
float o
Definition chapter5.cpp:210
float z
Definition chapter5.cpp:210
float x
Definition chapter5.cpp:210
void SetCombatMovement(bool allowMovement)
Creature * me
ScriptedAI(Creature *creature)
uint32 spawnedCreatureEntry
void MoveInLineOfSight(Unit *who) OVERRIDE
void ReceiveEmote(Player *player, uint32 emote) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void ReceiveEmote(Player *player, uint32 emote) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void ReceiveEmote(Player *player, uint32 emote) OVERRIDE
void PatientSaved(Creature *, Player *player, Location *point)
void BeginEvent(Player *player)
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void EnterCombat(Unit *) OVERRIDE
std::list< uint64 > Patients
npc_doctorAI(Creature *creature)
std::vector< Location * > Coordinates
void PatientDied(Location *point)
void EnterEvadeMode() OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
npc_escortAI(Creature *creature)
void Start(bool isActiveAttacker=true, bool run=false, uint64 playerGUID=0, Quest const *quest=NULL, bool instantRespawn=false, bool canLoopPath=false, bool resetWaypoints=true)
uint32 GetFireworkSpell(uint32 entry)
npc_fireworkAI(Creature *creature)
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void SpellHit(Unit *caster, SpellInfo const *spell) OVERRIDE
void UpdateAI(uint32) OVERRIDE
== Triggered Actions Requested ==================
void EnterCombat(Unit *) OVERRIDE
npc_guardianAI(Creature *creature)
void UpdateAI(uint32) OVERRIDE
== Triggered Actions Requested ==================
void SpellHit(Unit *caster, SpellInfo const *spell) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void EnterCombat(Unit *) OVERRIDE
void AttackStart(Unit *) OVERRIDE
npc_tonk_mineAI(Creature *creature)
void EnterCombat(Unit *) OVERRIDE
void MoveInLineOfSight(Unit *) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void DamageTaken(Unit *, uint32 &damage) OVERRIDE
void UpdateAI(uint32 diff) OVERRIDE
== Triggered Actions Requested ==================
void DamageTaken(Unit *, uint32 &) override
void UpdateAI(uint32 diff) override
== Triggered Actions Requested ==================
uint32 GetData(uint32 type) const OVERRIDE
npc_wormholeAI(Creature *creature)
@ NPC_OMEN
@ FACTION_FRIENDLY