TrinityCore
npcs_special.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ScriptMgr.h"
19#include "CellImpl.h"
20#include "CharmInfo.h"
21#include "CombatAI.h"
22#include "Containers.h"
23#include "CreatureTextMgr.h"
24#include "GameEventMgr.h"
25#include "GameObject.h"
26#include "GameObjectAI.h"
27#include "GridNotifiersImpl.h"
28#include "Log.h"
29#include "MotionMaster.h"
30#include "MoveSplineInit.h"
31#include "ObjectAccessor.h"
32#include "ObjectMgr.h"
33#include "PassiveAI.h"
34#include "Player.h"
35#include "QuestDef.h"
36#include "ScriptedEscortAI.h"
37#include "ScriptedGossip.h"
38#include "SpellAuras.h"
39#include "SpellHistory.h"
40#include "SpellInfo.h"
41#include "SpellMgr.h"
42#include "TemporarySummon.h"
43#include "Vehicle.h"
44
45/*########
46# npc_air_force_bots
47#########*/
48
50{
51 TRIPWIRE, // do not attack flying players, smaller range
52 ALARMBOT, // attack flying players, casts guard's mark
53
54 SPELL_GUARDS_MARK = 38067
55};
56
57float constexpr RANGE_TRIPWIRE = 15.0f;
58float constexpr RANGE_ALARMBOT = 100.0f;
59
61{
65};
66
68{
69 {2614, 15241, ALARMBOT}, // Air Force Alarm Bot (Alliance)
70 {2615, 15242, ALARMBOT}, // Air Force Alarm Bot (Horde)
71 {21974, 21976, ALARMBOT}, // Air Force Alarm Bot (Area 52)
72 {21993, 15242, ALARMBOT}, // Air Force Guard Post (Horde - Bat Rider)
73 {21996, 15241, ALARMBOT}, // Air Force Guard Post (Alliance - Gryphon)
74 {21997, 21976, ALARMBOT}, // Air Force Guard Post (Goblin - Area 52 - Zeppelin)
75 {21999, 15241, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Alliance)
76 {22001, 15242, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Horde)
77 {22002, 15242, TRIPWIRE}, // Air Force Trip Wire - Ground (Horde)
78 {22003, 15241, TRIPWIRE}, // Air Force Trip Wire - Ground (Alliance)
79 {22063, 21976, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Goblin - Area 52)
80 {22065, 22064, ALARMBOT}, // Air Force Guard Post (Ethereal - Stormspire)
81 {22066, 22067, ALARMBOT}, // Air Force Guard Post (Scryer - Dragonhawk)
82 {22068, 22064, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Ethereal - Stormspire)
83 {22069, 22064, ALARMBOT}, // Air Force Alarm Bot (Stormspire)
84 {22070, 22067, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Scryer)
85 {22071, 22067, ALARMBOT}, // Air Force Alarm Bot (Scryer)
86 {22078, 22077, ALARMBOT}, // Air Force Alarm Bot (Aldor)
87 {22079, 22077, ALARMBOT}, // Air Force Guard Post (Aldor - Gryphon)
88 {22080, 22077, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Aldor)
89 {22086, 22085, ALARMBOT}, // Air Force Alarm Bot (Sporeggar)
90 {22087, 22085, ALARMBOT}, // Air Force Guard Post (Sporeggar - Spore Bat)
91 {22088, 22085, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Sporeggar)
92 {22090, 22089, ALARMBOT}, // Air Force Guard Post (Toshley's Station - Flying Machine)
93 {22124, 22122, ALARMBOT}, // Air Force Alarm Bot (Cenarion)
94 {22125, 22122, ALARMBOT}, // Air Force Guard Post (Cenarion - Stormcrow)
95 {22126, 22122, ALARMBOT} // Air Force Trip Wire - Rooftop (Cenarion Expedition)
96};
97
99{
100public:
101 npc_air_force_bots() : CreatureScript("npc_air_force_bots") { }
102
104 {
105 static AirForceSpawn const& FindSpawnFor(uint32 entry)
106 {
107 for (AirForceSpawn const& spawn : airforceSpawns)
108 {
109 if (spawn.myEntry == entry)
110 {
111 ASSERT_NODEBUGINFO(sObjectMgr->GetCreatureTemplate(spawn.otherEntry), "Invalid creature entry %u in 'npc_air_force_bots' script", spawn.otherEntry);
112 return spawn;
113 }
114 }
115 ASSERT_NODEBUGINFO(false, "Unhandled creature with entry %u is assigned 'npc_air_force_bots' script", entry);
116 }
117
119
121 {
123
124 if (!guard && (guard = me->SummonCreature(_spawn.otherEntry, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5min)))
125 _myGuard = guard->GetGUID();
126
127 return guard;
128 }
129
130 void UpdateAI(uint32 /*diff*/) override
131 {
132 if (_toAttack.empty())
133 return;
134
135 Creature* guard = GetOrSummonGuard();
136 if (!guard)
137 return;
138
139 // Keep the list of targets for later on when the guards will be alive
140 if (!guard->IsAlive())
141 return;
142
143 for (ObjectGuid guid : _toAttack)
144 {
145 Unit* target = ObjectAccessor::GetUnit(*me, guid);
146 if (!target)
147 continue;
148 if (guard->IsEngagedBy(target))
149 continue;
150
151 guard->EngageWithTarget(target);
152 if (_spawn.type == ALARMBOT)
153 guard->CastSpell(target, SPELL_GUARDS_MARK, true);
154 }
155
156 _toAttack.clear();
157 }
158
159 void MoveInLineOfSight(Unit* who) override
160 {
161 // guards are only spawned against players
162 if (who->GetTypeId() != TYPEID_PLAYER)
163 return;
164
165 // we're already scheduled to attack this player on our next tick, don't bother checking
166 if (_toAttack.find(who->GetGUID()) != _toAttack.end())
167 return;
168
169 // check if they're in range
171 return;
172
173 // check if they're hostile
174 if (!(me->IsHostileTo(who) || who->IsHostileTo(me)))
175 return;
176
177 // check if they're a valid attack target
178 if (!me->IsValidAttackTarget(who))
179 return;
180
181 if ((_spawn.type == TRIPWIRE) && who->IsFlying())
182 return;
183
184 _toAttack.insert(who->GetGUID());
185 }
186
187 private:
190 std::unordered_set<ObjectGuid> _toAttack;
191
192 };
193
194 CreatureAI* GetAI(Creature* creature) const override
195 {
196 return new npc_air_force_botsAI(creature);
197 }
198};
199
200/*########
201# npc_chicken_cluck
202#########*/
203
205{
209
211};
212
214{
215public:
216 npc_chicken_cluck() : CreatureScript("npc_chicken_cluck") { }
217
219 {
221 {
222 Initialize();
223 }
224
226 {
227 ResetFlagTimer = 120000;
228 }
229
231
232 void Reset() override
233 {
234 Initialize();
237 }
238
239 void JustEngagedWith(Unit* /*who*/) override { }
240
241 void UpdateAI(uint32 diff) override
242 {
243 // Reset flags after a certain time has passed so that the next player has to start the 'event' again
245 {
246 if (ResetFlagTimer <= diff)
247 {
249 return;
250 }
251 else
252 ResetFlagTimer -= diff;
253 }
254
255 UpdateVictim();
256 }
257
258 void ReceiveEmote(Player* player, uint32 emote) override
259 {
260 switch (emote)
261 {
263 if (player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_NONE && rand32() % 30 == 1)
264 {
267 Talk(player->GetTeam() == HORDE ? EMOTE_HELLO_H : EMOTE_HELLO_A);
268 }
269 break;
270 case TEXT_EMOTE_CHEER:
272 {
276 }
277 break;
278 }
279 }
280
281 void OnQuestAccept(Player* /*player*/, Quest const* quest) override
282 {
283 if (quest->GetQuestId() == QUEST_CLUCK)
284 Reset();
285 }
286
287 void OnQuestReward(Player* /*player*/, Quest const* quest, LootItemType /*type*/, uint32 /*opt*/) override
288 {
289 if (quest->GetQuestId() == QUEST_CLUCK)
290 Reset();
291 }
292 };
293
294 CreatureAI* GetAI(Creature* creature) const override
295 {
296 return new npc_chicken_cluckAI(creature);
297 }
298};
299
300/*######
301## npc_dancing_flames
302######*/
303
305{
310
312{
313 npc_dancing_flames(Creature* creature) : ScriptedAI(creature) { }
314
315 void Reset() override
316 {
320 float x, y, z;
321 me->GetPosition(x, y, z);
322 me->Relocate(x, y, z + 1.05f);
323 }
324
325 void UpdateAI(uint32 diff) override
326 {
327 _scheduler.Update(diff);
328 }
329
330 void ReceiveEmote(Player* player, uint32 emote) override
331 {
332 if (me->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()) && me->IsWithinDistInMap(player, 30.0f))
333 {
334 // She responds to emotes not instantly but ~1500ms later
335 // If you first /bow, then /wave before dancing flames bow back, it doesnt bow at all and only does wave
336 // If you're performing emotes too fast, she will not respond to them
337 // Means she just replaces currently scheduled event with new after receiving new emote
339
340 switch (emote)
341 {
342 case TEXT_EMOTE_KISS:
343 _scheduler.Schedule(1500ms, [this](TaskContext /*context*/)
344 {
346 });
347 break;
348 case TEXT_EMOTE_WAVE:
349 _scheduler.Schedule(1500ms, [this](TaskContext /*context*/)
350 {
352 });
353 break;
354 case TEXT_EMOTE_BOW:
355 _scheduler.Schedule(1500ms, [this](TaskContext /*context*/)
356 {
358 });
359 break;
360 case TEXT_EMOTE_JOKE:
361 _scheduler.Schedule(1500ms, [this](TaskContext /*context*/)
362 {
364 });
365 break;
366 case TEXT_EMOTE_DANCE:
367 if (!player->HasAura(SPELL_FIERY_SEDUCTION))
368 {
369 DoCast(player, SPELL_FIERY_SEDUCTION, true);
371 }
372 break;
373 }
374 }
375 }
376
377private:
379};
380
381/*######
382## npc_torch_tossing_target_bunny_controller
383######*/
384
386{
389
391{
392public:
393 npc_torch_tossing_target_bunny_controller() : CreatureScript("npc_torch_tossing_target_bunny_controller") { }
394
396 {
398
399 void Reset() override
400 {
401 _scheduler.Schedule(Seconds(2), [this](TaskContext context)
402 {
404 _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
405 {
407 });
408 context.Repeat(Seconds(5));
409 });
410 }
411
412 void UpdateAI(uint32 diff) override
413 {
414 _scheduler.Update(diff);
415 }
416
417 private:
419 };
420
421 CreatureAI* GetAI(Creature* creature) const override
422 {
424 }
425};
426
427/*######
428## npc_midsummer_bunny_pole
429######*/
430
432{
440
442{
443public:
444 npc_midsummer_bunny_pole() : CreatureScript("npc_midsummer_bunny_pole") { }
445
447 {
449 {
450 Initialize();
451 }
452
454 {
455 events.Reset();
456 running = false;
457 }
458
459 void Reset() override
460 {
461 Initialize();
462 }
463
464 void DoAction(int32 /*action*/) override
465 {
466 // Don't start event if it's already running.
467 if (running)
468 return;
469
470 running = true;
472 }
473
475 {
476 // Returns true if no nearby player has aura "Test Ribbon Pole Channel".
477 std::list<Player*> players;
480 Cell::VisitWorldObjects(me, searcher, 10.0f);
481
482 return players.empty();
483 }
484
485 void UpdateAI(uint32 diff) override
486 {
487 if (!running)
488 return;
489
490 events.Update(diff);
491
492 switch (events.ExecuteEvent())
493 {
495 {
496 if (checkNearbyPlayers())
497 {
498 Reset();
499 return;
500 }
501
503 me->CastSpell(go, SPELL_RED_FIRE_RING, true);
504
506 }
507 break;
509 {
510 if (checkNearbyPlayers())
511 {
512 Reset();
513 return;
514 }
515
518
520 }
521 break;
522 }
523 }
524
525 private:
528 };
529
530 CreatureAI* GetAI(Creature* creature) const override
531 {
532 return new npc_midsummer_bunny_poleAI(creature);
533 }
534};
535
536/*######
537## Triage quest
538######*/
539
541{
543
547 HORDE_COORDS = 6
549
551{
552 {-3757.38f, -4533.05f, 14.16f, 3.62f}, // Top-far-right bunk as seen from entrance
553 {-3754.36f, -4539.13f, 14.16f, 5.13f}, // Top-far-left bunk
554 {-3749.54f, -4540.25f, 14.28f, 3.34f}, // Far-right bunk
555 {-3742.10f, -4536.85f, 14.28f, 3.64f}, // Right bunk near entrance
556 {-3755.89f, -4529.07f, 14.05f, 0.57f}, // Far-left bunk
557 {-3749.51f, -4527.08f, 14.07f, 5.26f}, // Mid-left bunk
558 {-3746.37f, -4525.35f, 14.16f, 5.22f}, // Left bunk near entrance
559};
560
561//alliance run to where
562#define A_RUNTOX -3742.96f
563#define A_RUNTOY -4531.52f
564#define A_RUNTOZ 11.91f
565
567{
568 {-1013.75f, -3492.59f, 62.62f, 4.34f}, // Left, Behind
569 {-1017.72f, -3490.92f, 62.62f, 4.34f}, // Right, Behind
570 {-1015.77f, -3497.15f, 62.82f, 4.34f}, // Left, Mid
571 {-1019.51f, -3495.49f, 62.82f, 4.34f}, // Right, Mid
572 {-1017.25f, -3500.85f, 62.98f, 4.34f}, // Left, front
573 {-1020.95f, -3499.21f, 62.98f, 4.34f} // Right, Front
574};
575
576//horde run to where
577#define H_RUNTOX -1016.44f
578#define H_RUNTOY -3508.48f
579#define H_RUNTOZ 62.96f
580
582{
583 12938, // 12938 Injured Alliance Soldier
584 12936, // 12936 Badly injured Alliance Soldier
585 12937 // 12937 Critically injured Alliance Soldier
586};
587
589{
590 12923, //12923 Injured Soldier
591 12924, //12924 Badly injured Soldier
592 12925 //12925 Critically injured Soldier
593};
594
595/*######
596## npc_doctor (handles both Gustaf Vanhowzen and Gregory Victor)
597######*/
599{
600public:
601 npc_doctor() : CreatureScript("npc_doctor") { }
602
603 struct npc_doctorAI : public ScriptedAI
604 {
605 npc_doctorAI(Creature* creature) : ScriptedAI(creature)
606 {
607 Initialize();
608 }
609
611 {
613
614 SummonPatientTimer = 10000;
618
619 Patients.clear();
620 Coordinates.clear();
621
622 Event = false;
623 }
624
626
631
632 bool Event;
633
635 std::vector<Position const*> Coordinates;
636
637 void Reset() override
638 {
639 Initialize();
640 me->SetUninteractible(false);
641 }
642
643 void BeginEvent(Player* player)
644 {
645 PlayerGUID = player->GetGUID();
646
647 SummonPatientTimer = 10000;
651
652 switch (me->GetEntry())
653 {
654 case DOCTOR_ALLIANCE:
655 for (uint8 i = 0; i < ALLIANCE_COORDS; ++i)
656 Coordinates.push_back(&AllianceCoords[i]);
657 break;
658 case DOCTOR_HORDE:
659 for (uint8 i = 0; i < HORDE_COORDS; ++i)
660 Coordinates.push_back(&HordeCoords[i]);
661 break;
662 }
663
664 Event = true;
665 me->SetUninteractible(true);
666 }
667
668 void PatientDied(Position const* point)
669 {
671 if (player && ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)))
672 {
674
675 if (PatientDiedCount > 5 && Event)
676 {
677 if (player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
678 player->FailQuest(6624);
679 else if (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
680 player->FailQuest(6622);
681
682 Reset();
683 return;
684 }
685
686 Coordinates.push_back(point);
687 }
688 else
689 // If no player or player abandon quest in progress
690 Reset();
691 }
692
693 void PatientSaved(Creature* /*soldier*/, Player* player, Position const* point)
694 {
695 if (player && PlayerGUID == player->GetGUID())
696 {
697 if ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))
698 {
700
701 if (PatientSavedCount == 15)
702 {
703 if (!Patients.empty())
704 {
705 for (GuidList::const_iterator itr = Patients.begin(); itr != Patients.end(); ++itr)
706 {
707 if (Creature* patient = ObjectAccessor::GetCreature(*me, *itr))
708 patient->setDeathState(JUST_DIED);
709 }
710 }
711
712 if (player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
713 player->AreaExploredOrEventHappens(6624);
714 else if (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
715 player->AreaExploredOrEventHappens(6622);
716
717 Reset();
718 return;
719 }
720
721 Coordinates.push_back(point);
722 }
723 }
724 }
725
726 void UpdateAI(uint32 diff) override;
727
728 void JustEngagedWith(Unit* /*who*/) override { }
729
730 void OnQuestAccept(Player* player, Quest const* quest) override
731 {
732 if ((quest->GetQuestId() == 6624) || (quest->GetQuestId() == 6622))
733 BeginEvent(player);
734 }
735 };
736
737 CreatureAI* GetAI(Creature* creature) const override
738 {
739 return new npc_doctorAI(creature);
740 }
741};
742
743/*#####
744## npc_injured_patient (handles all the patients, no matter Horde or Alliance)
745#####*/
746
748{
749public:
750 npc_injured_patient() : CreatureScript("npc_injured_patient") { }
751
753 {
755 {
756 Initialize();
757 }
758
760 {
762 Coord = nullptr;
763 }
764
767
768 void Reset() override
769 {
770 Initialize();
771
772 //no select
773 me->SetUninteractible(false);
774
775 //no regen health
777
778 //to make them lay with face down
780
781 uint32 mobId = me->GetEntry();
782
783 switch (mobId)
784 { //lower max health
785 case 12923:
786 case 12938: //Injured Soldier
788 break;
789 case 12924:
790 case 12936: //Badly injured Soldier
792 break;
793 case 12925:
794 case 12937: //Critically injured Soldier
796 break;
797 }
798 }
799
800 void JustEngagedWith(Unit* /*who*/) override { }
801
802 void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override
803 {
804 Player* player = caster->ToPlayer();
805 if (!player || !me->IsAlive() || spellInfo->Id != 20804)
806 return;
807
808 if (player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
809 if (!DoctorGUID.IsEmpty())
811 ENSURE_AI(npc_doctor::npc_doctorAI, doctor->AI())->PatientSaved(me, player, Coord);
812
813 //make uninteractible
814 me->SetUninteractible(true);
815
816 //regen health
818
819 //stand up
821
822 Talk(SAY_DOC);
823
824 uint32 mobId = me->GetEntry();
825 me->SetWalk(false);
826
827 switch (mobId)
828 {
829 case 12923:
830 case 12924:
831 case 12925:
833 break;
834 case 12936:
835 case 12937:
836 case 12938:
838 break;
839 }
840 }
841
842 void UpdateAI(uint32 /*diff*/) override
843 {
844 //lower HP on every world tick makes it a useful counter, not officlone though
845 if (me->IsAlive() && me->GetHealth() > 6)
846 me->ModifyHealth(-5);
847
848 if (me->IsAlive() && me->GetHealth() <= 6)
849 {
851 me->SetUninteractible(true);
854
855 if (!DoctorGUID.IsEmpty())
857 ENSURE_AI(npc_doctor::npc_doctorAI, doctor->AI())->PatientDied(Coord);
858 }
859 }
860 };
861
862 CreatureAI* GetAI(Creature* creature) const override
863 {
864 return new npc_injured_patientAI(creature);
865 }
866};
867
869{
870 if (Event && SummonPatientCount >= 20)
871 {
872 Reset();
873 return;
874 }
875
876 if (Event)
877 {
878 if (SummonPatientTimer <= diff)
879 {
880 if (Coordinates.empty())
881 return;
882
883 uint32 patientEntry = 0;
884
885 switch (me->GetEntry())
886 {
887 case DOCTOR_ALLIANCE:
888 patientEntry = AllianceSoldierId[rand32() % 3];
889 break;
890 case DOCTOR_HORDE:
891 patientEntry = HordeSoldierId[rand32() % 3];
892 break;
893 default:
894 TC_LOG_ERROR("scripts", "Invalid entry for Triage doctor. Please check your database");
895 return;
896 }
897
898 std::vector<Position const*>::iterator point = Coordinates.begin();
899 std::advance(point, urand(0, Coordinates.size() - 1));
900
901 if (Creature* Patient = me->SummonCreature(patientEntry, **point, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s))
902 {
903 //303, this flag appear to be required for client side item->spell to work (TARGET_SINGLE_FRIEND)
904 Patient->SetUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED);
905
906 Patients.push_back(Patient->GetGUID());
907 ENSURE_AI(npc_injured_patient::npc_injured_patientAI, Patient->AI())->DoctorGUID = me->GetGUID();
908 ENSURE_AI(npc_injured_patient::npc_injured_patientAI, Patient->AI())->Coord = *point;
909
910 Coordinates.erase(point);
911 }
912
913 SummonPatientTimer = 10000;
915 }
916 else
917 SummonPatientTimer -= diff;
918 }
919}
920
921/*######
922## npc_garments_of_quests
923######*/
924
926
928{
931
937
938 ENTRY_SHAYA = 12429,
940 ENTRY_DOLF = 12427,
941 ENTRY_KORJA = 12430,
943
944 // used by 12429, 12423, 12427, 12430, 12428, but signed for 12429
948};
949
951{
952public:
953 npc_garments_of_quests() : CreatureScript("npc_garments_of_quests") { }
954
956 {
958 {
959 switch (me->GetEntry())
960 {
961 case ENTRY_SHAYA:
962 quest = QUEST_MOON;
963 break;
964 case ENTRY_ROBERTS:
965 quest = QUEST_LIGHT_1;
966 break;
967 case ENTRY_DOLF:
968 quest = QUEST_LIGHT_2;
969 break;
970 case ENTRY_KORJA:
971 quest = QUEST_SPIRIT;
972 break;
973 case ENTRY_DG_KEL:
974 quest = QUEST_DARKNESS;
975 break;
976 default:
977 quest = 0;
978 break;
979 }
980
981 Initialize();
982 }
983
985 {
986 IsHealed = false;
987 CanRun = false;
988
989 RunAwayTimer = 5000;
990 }
991
993
995 bool CanRun;
996
999
1000 void Reset() override
1001 {
1002 CasterGUID.Clear();
1003
1004 Initialize();
1005
1006 me->SetStandState(UNIT_STAND_STATE_KNEEL);
1007 // expect database to have RegenHealth=0
1008 me->SetHealth(me->CountPctFromMaxHealth(70));
1009 }
1010
1011 void JustEngagedWith(Unit* /*who*/) override { }
1012
1013 void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override
1014 {
1015 if (spellInfo->Id == SPELL_LESSER_HEAL_R2 || spellInfo->Id == SPELL_FORTITUDE_R1)
1016 {
1017 //not while in combat
1018 if (me->IsInCombat())
1019 return;
1020
1021 //nothing to be done now
1022 if (IsHealed && CanRun)
1023 return;
1024
1025 if (Player* player = caster->ToPlayer())
1026 {
1027 if (quest && player->GetQuestStatus(quest) == QUEST_STATUS_INCOMPLETE)
1028 {
1029 if (IsHealed && !CanRun && spellInfo->Id == SPELL_FORTITUDE_R1)
1030 {
1031 Talk(SAY_THANKS, player);
1032 CanRun = true;
1033 }
1034 else if (!IsHealed && spellInfo->Id == SPELL_LESSER_HEAL_R2)
1035 {
1036 CasterGUID = player->GetGUID();
1037 me->SetStandState(UNIT_STAND_STATE_STAND);
1038 Talk(SAY_HEALED, player);
1039 IsHealed = true;
1040 }
1041 }
1042
1043 // give quest credit, not expect any special quest objectives
1044 if (CanRun)
1045 player->TalkedToCreature(me->GetEntry(), me->GetGUID());
1046 }
1047 }
1048 }
1049
1050 void UpdateAI(uint32 diff) override
1051 {
1052 if (CanRun && !me->IsInCombat())
1053 {
1054 if (RunAwayTimer <= diff)
1055 {
1056 if (Unit* unit = ObjectAccessor::GetUnit(*me, CasterGUID))
1057 {
1058 switch (me->GetEntry())
1059 {
1060 case ENTRY_SHAYA:
1061 case ENTRY_ROBERTS:
1062 case ENTRY_DOLF:
1063 case ENTRY_KORJA:
1064 case ENTRY_DG_KEL:
1065 Talk(SAY_GOODBYE, unit);
1066 break;
1067 }
1068
1069 LoadPath((me->GetEntry() << 3) | 2);
1070 Start(false);
1071 }
1072 else
1073 EnterEvadeMode(EvadeReason::Other); //something went wrong
1074
1075 RunAwayTimer = 30000;
1076 }
1077 else
1078 RunAwayTimer -= diff;
1079 }
1080
1081 EscortAI::UpdateAI(diff);
1082 }
1083 };
1084
1085 CreatureAI* GetAI(Creature* creature) const override
1086 {
1087 return new npc_garments_of_questsAI(creature);
1088 }
1089};
1090
1091/*######
1092## npc_guardian
1093######*/
1094
1096{
1099
1101{
1102public:
1103 npc_guardian() : CreatureScript("npc_guardian") { }
1104
1106 {
1107 npc_guardianAI(Creature* creature) : ScriptedAI(creature) { }
1108
1109 void Reset() override
1110 {
1111 me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
1112 }
1113
1114 void JustEngagedWith(Unit* /*who*/) override
1115 {
1116 }
1117
1118 void UpdateAI(uint32 /*diff*/) override
1119 {
1120 if (!UpdateVictim())
1121 return;
1122
1123 if (me->isAttackReady())
1124 {
1125 DoCastVictim(SPELL_DEATHTOUCH, true);
1126 me->resetAttackTimer();
1127 }
1128 }
1129 };
1130
1131 CreatureAI* GetAI(Creature* creature) const override
1132 {
1133 return new npc_guardianAI(creature);
1134 }
1135};
1136
1138{
1139public:
1140 npc_steam_tonk() : CreatureScript("npc_steam_tonk") { }
1141
1143 {
1144 npc_steam_tonkAI(Creature* creature) : ScriptedAI(creature) { }
1145
1146 void Reset() override { }
1147 void JustEngagedWith(Unit* /*who*/) override { }
1148
1149 void OnPossess(bool apply)
1150 {
1151 if (apply)
1152 {
1153 // Initialize the action bar without the melee attack command
1154 me->InitCharmInfo();
1155 me->GetCharmInfo()->InitEmptyActionBar(false);
1156
1157 me->SetReactState(REACT_PASSIVE);
1158 }
1159 else
1160 me->SetReactState(REACT_AGGRESSIVE);
1161 }
1162 };
1163
1164 CreatureAI* GetAI(Creature* creature) const override
1165 {
1166 return new npc_steam_tonkAI(creature);
1167 }
1168};
1169
1171{
1209
1211{
1226
1228{
1242
1264
1266{
1267 public:
1268 npc_tournament_mount() : CreatureScript("npc_tournament_mount") { }
1269
1271 {
1273 {
1274 _pennantSpellId = 0;
1275 }
1276
1277 void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override
1278 {
1279 Player* player = passenger->ToPlayer();
1280 if (!player)
1281 return;
1282
1283 if (apply)
1284 {
1285 _pennantSpellId = GetPennantSpellId(player);
1286 player->CastSpell(nullptr, _pennantSpellId, true);
1287 }
1288 else
1289 player->RemoveAurasDueToSpell(_pennantSpellId);
1290 }
1291
1292 private:
1294
1296 {
1297 switch (me->GetEntry())
1298 {
1301 {
1306 else
1308 }
1310 {
1315 else
1317 }
1319 {
1324 else
1326 }
1329 {
1334 else
1336 }
1338 {
1343 else
1345 }
1346 case NPC_EXODAR_ELEKK:
1347 {
1352 else
1354 }
1355 case NPC_IRONFORGE_RAM:
1356 {
1361 else
1363 }
1365 {
1370 else
1372 }
1373 case NPC_ORGRIMMAR_WOLF:
1374 {
1379 else
1381 }
1383 {
1388 else
1390 }
1392 {
1395 else if (player->HasAchieved(ACHIEVEMENT_ARGENT_VALOR))
1397 else
1399 }
1400 default:
1401 return 0;
1402 }
1403 }
1404 };
1405
1406 CreatureAI* GetAI(Creature* creature) const override
1407 {
1408 return new npc_tournament_mountAI(creature);
1409 }
1410};
1411
1412/*####
1413## npc_brewfest_reveler
1414####*/
1415
1417{
1418 SPELL_BREWFEST_TOAST = 41586
1420
1422{
1423 public:
1424 npc_brewfest_reveler() : CreatureScript("npc_brewfest_reveler") { }
1425
1427 {
1428 npc_brewfest_revelerAI(Creature* creature) : ScriptedAI(creature) { }
1429
1430 void ReceiveEmote(Player* player, uint32 emote) override
1431 {
1433 return;
1434
1435 if (emote == TEXT_EMOTE_DANCE)
1436 me->CastSpell(player, SPELL_BREWFEST_TOAST, false);
1437 }
1438 };
1439
1440 CreatureAI* GetAI(Creature* creature) const override
1441 {
1442 return new npc_brewfest_revelerAI(creature);
1443 }
1444};
1445
1446/*######
1447# npc_brewfest_reveler_2
1448######*/
1449
1451{
1457};
1458
1460{
1462 {
1463 NPC_BREWFEST_REVELER = 24484,
1464
1465 EVENT_FILL_LIST = 1,
1466 EVENT_FACE_TO = 2,
1468 EVENT_NEXT = 4
1470
1471 npc_brewfest_reveler_2(Creature* creature) : ScriptedAI(creature) { }
1472
1473 void Reset() override
1474 {
1475 _events.Reset();
1476 _events.ScheduleEvent(EVENT_FILL_LIST, 1s, 2s);
1477 }
1478
1479 // Copied from old script. I don't know if this is 100% correct.
1480 void ReceiveEmote(Player* player, uint32 emote) override
1481 {
1483 return;
1484
1485 if (emote == TEXT_EMOTE_DANCE)
1486 me->CastSpell(player, SPELL_BREWFEST_TOAST, false);
1487 }
1488
1489 void UpdateAI(uint32 diff) override
1490 {
1491 UpdateVictim();
1492
1493 _events.Update(diff);
1494
1495 while (uint32 eventId = _events.ExecuteEvent())
1496 {
1497 switch (eventId)
1498 {
1499 case EVENT_FILL_LIST:
1500 {
1501 std::list<Creature*> creatureList;
1502 GetCreatureListWithEntryInGrid(creatureList, me, NPC_BREWFEST_REVELER, 5.0f);
1503 for (Creature* creature : creatureList)
1504 if (creature != me)
1505 _revelerGuids.push_back(creature->GetGUID());
1506
1507 _events.ScheduleEvent(EVENT_FACE_TO, 1s, 2s);
1508 break;
1509 }
1510 case EVENT_FACE_TO:
1511 {
1512 // Turn to random brewfest reveler within set range
1513 if (!_revelerGuids.empty())
1515 me->SetFacingToObject(creature);
1516
1517 _events.ScheduleEvent(EVENT_EMOTE, 2s, 6s);
1518 break;
1519 }
1520 case EVENT_EMOTE:
1521 // Play random emote or dance
1522 if (roll_chance_i(50))
1523 {
1525 _events.ScheduleEvent(EVENT_NEXT, 4s, 6s);
1526 }
1527 else
1528 {
1529 me->SetEmoteState(EMOTE_STATE_DANCE);
1530 _events.ScheduleEvent(EVENT_NEXT, 8s, 12s);
1531 }
1532 break;
1533 case EVENT_NEXT:
1534 // If dancing stop before next random state
1535 if (me->GetEmoteState() == EMOTE_STATE_DANCE)
1536 me->SetEmoteState(EMOTE_ONESHOT_NONE);
1537
1538 // Random EVENT_EMOTE or EVENT_FACETO
1539 if (roll_chance_i(50))
1540 _events.ScheduleEvent(EVENT_FACE_TO, 1s);
1541 else
1542 _events.ScheduleEvent(EVENT_EMOTE, 1s);
1543 break;
1544 default:
1545 break;
1546 }
1547 }
1548 }
1549
1550private:
1553};
1554
1556{
1557 npc_training_dummy(Creature* creature) : NullCreatureAI(creature) { }
1558
1559 void JustEnteredCombat(Unit* who) override
1560 {
1561 _combatTimer[who->GetGUID()] = 5s;
1562 }
1563
1564 void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damageType, SpellInfo const* /*spellInfo = nullptr*/) override
1565 {
1566 damage = 0;
1567
1568 if (!attacker || damageType == DOT)
1569 return;
1570
1571 _combatTimer[attacker->GetGUID()] = 5s;
1572 }
1573
1574 void UpdateAI(uint32 diff) override
1575 {
1576 for (auto itr = _combatTimer.begin(); itr != _combatTimer.end();)
1577 {
1578 itr->second -= Milliseconds(diff);
1579 if (itr->second <= 0s)
1580 {
1581 // The attacker has not dealt any damage to the dummy for over 5 seconds. End combat.
1582 auto const& pveRefs = me->GetCombatManager().GetPvECombatRefs();
1583 auto it = pveRefs.find(itr->first);
1584 if (it != pveRefs.end())
1585 it->second->EndCombat();
1586
1587 itr = _combatTimer.erase(itr);
1588 }
1589 else
1590 ++itr;
1591 }
1592 }
1593private:
1594 std::unordered_map<ObjectGuid /*attackerGUID*/, Milliseconds /*combatTime*/> _combatTimer;
1595};
1596
1597/*######
1598# npc_wormhole
1599######*/
1600
1602{
1603 MENU_ID_WORMHOLE = 10668, // "This tear in the fabric of time and space looks ominous."
1604 NPC_TEXT_WORMHOLE = 14785, // (not 907 "What brings you to this part of the world, $n?")
1605 GOSSIP_OPTION_1 = 0, // "Borean Tundra"
1606 GOSSIP_OPTION_2 = 1, // "Howling Fjord"
1607 GOSSIP_OPTION_3 = 2, // "Sholazar Basin"
1608 GOSSIP_OPTION_4 = 3, // "Icecrown"
1609 GOSSIP_OPTION_5 = 4, // "Storm Peaks"
1610 GOSSIP_OPTION_6 = 5, // "Underground..."
1611
1615 SPELL_ICECROWN = 67836, // 3
1616 SPELL_STORM_PEAKS = 67837, // 4
1617 SPELL_UNDERGROUND = 68081 // 5
1619
1621{
1622 public:
1623 npc_wormhole() : CreatureScript("npc_wormhole") { }
1624
1626 {
1627 npc_wormholeAI(Creature* creature) : PassiveAI(creature)
1628 {
1629 Initialize();
1630 }
1631
1633 {
1634 _showUnderground = urand(0, 100) == 0; // Guessed value, it is really rare though
1635 }
1636
1637 void InitializeAI() override
1638 {
1639 Initialize();
1640 }
1641
1642 bool OnGossipHello(Player* player) override
1643 {
1645 if (me->IsSummon())
1646 {
1647 if (player == me->ToTempSummon()->GetSummoner())
1648 {
1654
1655 if (_showUnderground)
1657
1658 SendGossipMenuFor(player, NPC_TEXT_WORMHOLE, me->GetGUID());
1659 }
1660 }
1661
1662 return true;
1663 }
1664
1665 bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
1666 {
1667 uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
1668 ClearGossipMenuFor(player);
1669
1670 switch (action)
1671 {
1672 case GOSSIP_ACTION_INFO_DEF + 1: // Borean Tundra
1673 CloseGossipMenuFor(player);
1674 DoCast(player, SPELL_BOREAN_TUNDRA, false);
1675 break;
1676 case GOSSIP_ACTION_INFO_DEF + 2: // Howling Fjord
1677 CloseGossipMenuFor(player);
1678 DoCast(player, SPELL_HOWLING_FJORD, false);
1679 break;
1680 case GOSSIP_ACTION_INFO_DEF + 3: // Sholazar Basin
1681 CloseGossipMenuFor(player);
1682 DoCast(player, SPELL_SHOLAZAR_BASIN, false);
1683 break;
1684 case GOSSIP_ACTION_INFO_DEF + 4: // Icecrown
1685 CloseGossipMenuFor(player);
1686 DoCast(player, SPELL_ICECROWN, false);
1687 break;
1688 case GOSSIP_ACTION_INFO_DEF + 5: // Storm peaks
1689 CloseGossipMenuFor(player);
1690 DoCast(player, SPELL_STORM_PEAKS, false);
1691 break;
1692 case GOSSIP_ACTION_INFO_DEF + 6: // Underground
1693 CloseGossipMenuFor(player);
1694 DoCast(player, SPELL_UNDERGROUND, false);
1695 break;
1696 }
1697
1698 return true;
1699 }
1700
1701 private:
1703 };
1704
1705 CreatureAI* GetAI(Creature* creature) const override
1706 {
1707 return new npc_wormholeAI(creature);
1708 }
1709};
1710
1711/*#####
1712# npc_spring_rabbit
1713#####*/
1714
1716{
1722 NPC_SPRING_RABBIT = 32791
1724
1726{
1727public:
1728 npc_spring_rabbit() : CreatureScript("npc_spring_rabbit") { }
1729
1730 CreatureAI* GetAI(Creature* creature) const override
1731 {
1732 return new npc_spring_rabbitAI(creature);
1733 }
1734
1736 {
1738 {
1739 Initialize();
1740 }
1741
1743 {
1744 inLove = false;
1745 rabbitGUID.Clear();
1746 jumpTimer = urand(5000, 10000);
1747 bunnyTimer = urand(10000, 20000);
1748 searchTimer = urand(5000, 10000);
1749 }
1750
1756
1757 void Reset() override
1758 {
1759 Initialize();
1760 if (Unit* owner = me->GetOwner())
1761 me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
1762 }
1763
1764 void JustEngagedWith(Unit* /*who*/) override { }
1765
1766 void DoAction(int32 /*param*/) override
1767 {
1768 inLove = true;
1769 if (Unit* owner = me->GetOwner())
1770 owner->CastSpell(owner, SPELL_SPRING_FLING, true);
1771 }
1772
1773 void UpdateAI(uint32 diff) override
1774 {
1775 if (inLove)
1776 {
1777 if (jumpTimer <= diff)
1778 {
1779 if (Unit* rabbit = ObjectAccessor::GetUnit(*me, rabbitGUID))
1780 DoCast(rabbit, SPELL_SPRING_RABBIT_JUMP);
1781 jumpTimer = urand(5000, 10000);
1782 } else jumpTimer -= diff;
1783
1784 if (bunnyTimer <= diff)
1785 {
1787 bunnyTimer = urand(20000, 40000);
1788 } else bunnyTimer -= diff;
1789 }
1790 else
1791 {
1792 if (searchTimer <= diff)
1793 {
1794 if (Creature* rabbit = me->FindNearestCreature(NPC_SPRING_RABBIT, 10.0f))
1795 {
1796 if (rabbit == me || rabbit->HasAura(SPELL_SPRING_RABBIT_IN_LOVE))
1797 return;
1798
1799 me->AddAura(SPELL_SPRING_RABBIT_IN_LOVE, me);
1800 DoAction(1);
1801 rabbit->AddAura(SPELL_SPRING_RABBIT_IN_LOVE, rabbit);
1802 rabbit->AI()->DoAction(1);
1803 rabbit->CastSpell(rabbit, SPELL_SPRING_RABBIT_JUMP, true);
1804 rabbitGUID = rabbit->GetGUID();
1805 }
1806 searchTimer = urand(5000, 10000);
1807 } else searchTimer -= diff;
1808 }
1809 }
1810 };
1811};
1812
1814{
1815private:
1816 enum
1817 {
1819
1821 };
1822
1823public:
1824 npc_imp_in_a_ball() : CreatureScript("npc_imp_in_a_ball") { }
1825
1827 {
1829 {
1830 summonerGUID.Clear();
1831 }
1832
1833 void IsSummonedBy(WorldObject* summoner) override
1834 {
1835 if (summoner->GetTypeId() == TYPEID_PLAYER)
1836 {
1837 summonerGUID = summoner->GetGUID();
1838 events.ScheduleEvent(EVENT_TALK, 3s);
1839 }
1840 }
1841
1842 void UpdateAI(uint32 diff) override
1843 {
1844 events.Update(diff);
1845
1846 if (events.ExecuteEvent() == EVENT_TALK)
1847 {
1848 if (Player* owner = ObjectAccessor::GetPlayer(*me, summonerGUID))
1849 {
1850 sCreatureTextMgr->SendChat(me, SAY_RANDOM, owner,
1852 }
1853 }
1854 }
1855
1856 private:
1859 };
1860
1861 CreatureAI* GetAI(Creature* creature) const override
1862 {
1863 return new npc_imp_in_a_ballAI(creature);
1864 }
1865};
1866
1868{
1878
1882{
1883 public:
1884 npc_train_wrecker() : CreatureScript("npc_train_wrecker") { }
1885
1887 {
1888 npc_train_wreckerAI(Creature* creature) : NullCreatureAI(creature), _isSearching(true), _nextAction(0), _timer(1 * IN_MILLISECONDS) { }
1889
1891 {
1892 if (GameObject* target = ObjectAccessor::GetGameObject(*me, _target))
1893 return target;
1894 me->HandleEmoteCommand(EMOTE_ONESHOT_RUDE);
1895 me->DespawnOrUnsummon(3s);
1896 return nullptr;
1897 }
1898
1899 void UpdateAI(uint32 diff) override
1900 {
1901 if (_isSearching)
1902 {
1903 if (diff < _timer)
1904 _timer -= diff;
1905 else
1906 {
1907 if (GameObject* target = me->FindNearestGameObject(GO_TOY_TRAIN, 15.0f))
1908 {
1909 _isSearching = false;
1910 _target = target->GetGUID();
1911 me->SetWalk(true);
1912 me->GetMotionMaster()->MovePoint(MOVEID_CHASE, target->GetNearPosition(3.0f, target->GetAbsoluteAngle(me)));
1913 }
1914 else
1915 _timer = 3 * IN_MILLISECONDS;
1916 }
1917 }
1918 else
1919 {
1920 switch (_nextAction)
1921 {
1922 case EVENT_DO_JUMP:
1923 if (GameObject* target = VerifyTarget())
1924 me->GetMotionMaster()->MoveJump(*target, 5.0, 10.0, MOVEID_JUMP);
1925 _nextAction = 0;
1926 break;
1927 case EVENT_DO_FACING:
1928 if (GameObject* target = VerifyTarget())
1929 {
1930 me->SetFacingTo(target->GetOrientation());
1931 me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK1H);
1932 _timer = 1.5 * AsUnderlyingType(IN_MILLISECONDS);
1933 _nextAction = EVENT_DO_WRECK;
1934 }
1935 else
1936 _nextAction = 0;
1937 break;
1938 case EVENT_DO_WRECK:
1939 if (diff < _timer)
1940 {
1941 _timer -= diff;
1942 break;
1943 }
1944 if (GameObject* target = VerifyTarget())
1945 {
1946 me->CastSpell(target, SPELL_WRECK_TRAIN, false);
1947 _timer = 2 * IN_MILLISECONDS;
1948 _nextAction = EVENT_DO_DANCE;
1949 }
1950 else
1951 _nextAction = 0;
1952 break;
1953 case EVENT_DO_DANCE:
1954 if (diff < _timer)
1955 {
1956 _timer -= diff;
1957 break;
1958 }
1959 me->UpdateEntry(NPC_EXULTING_WIND_UP_TRAIN_WRECKER);
1960 me->SetEmoteState(EMOTE_ONESHOT_DANCE);
1961 me->DespawnOrUnsummon(5s);
1962 _nextAction = 0;
1963 break;
1964 default:
1965 break;
1966 }
1967 }
1968 }
1969
1970 void MovementInform(uint32 /*type*/, uint32 id) override
1971 {
1972 if (id == MOVEID_CHASE)
1973 _nextAction = EVENT_DO_JUMP;
1974 else if (id == MOVEID_JUMP)
1975 _nextAction = EVENT_DO_FACING;
1976 }
1977
1978 private:
1983 };
1984
1985 CreatureAI* GetAI(Creature* creature) const override
1986 {
1987 return new npc_train_wreckerAI(creature);
1988 }
1989};
1990
1991/*######
1992## npc_argent_squire/gruntling
1993######*/
1994
1996{
2015 SPELL_TIRED_PLAYER = 67334
2017
2019{
2029
2031{
2033 ACHIEVEMENT_PONY_UP = 3736
2035
2037{
2040};
2041
2043{
2049};
2050
2052{
2053public:
2054 npc_argent_squire_gruntling() : CreatureScript("npc_argent_squire_gruntling") { }
2055
2057 {
2059 {
2060 }
2061
2062 void Reset() override
2063 {
2064 if (Player* owner = Object::ToPlayer(me->GetOwner()))
2065 {
2066 if (Aura* ownerTired = owner->GetAura(SPELL_TIRED_PLAYER))
2067 if (Aura* squireTired = me->AddAura(IsArgentSquire() ? SPELL_AURA_TIRED_S : SPELL_AURA_TIRED_G, me))
2068 squireTired->SetDuration(ownerTired->GetDuration());
2069
2070 if (owner->HasAchieved(ACHIEVEMENT_PONY_UP) && !me->HasAura(SPELL_AURA_TIRED_S) && !me->HasAura(SPELL_AURA_TIRED_G))
2071 {
2073 return;
2074 }
2075 }
2076
2078 }
2079
2080 bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
2081 {
2082 switch (gossipListId)
2083 {
2084 case GOSSIP_OPTION_BANK:
2085 {
2086 me->RemoveNpcFlag(UNIT_NPC_FLAG_MAILBOX | UNIT_NPC_FLAG_VENDOR);
2087 uint32 _bankAura = IsArgentSquire() ? SPELL_AURA_BANK_S : SPELL_AURA_BANK_G;
2088 if (!me->HasAura(_bankAura))
2089 DoCastSelf(_bankAura);
2090
2091 if (!player->HasAura(SPELL_TIRED_PLAYER))
2092 player->CastSpell(player, SPELL_TIRED_PLAYER, true);
2093 break;
2094 }
2095 case GOSSIP_OPTION_SHOP:
2096 {
2097 me->RemoveNpcFlag(UNIT_NPC_FLAG_BANKER | UNIT_NPC_FLAG_MAILBOX);
2098 uint32 _shopAura = IsArgentSquire() ? SPELL_AURA_SHOP_S : SPELL_AURA_SHOP_G;
2099 if (!me->HasAura(_shopAura))
2100 DoCastSelf(_shopAura);
2101
2102 if (!player->HasAura(SPELL_TIRED_PLAYER))
2103 player->CastSpell(player, SPELL_TIRED_PLAYER, true);
2104 break;
2105 }
2106 case GOSSIP_OPTION_MAIL:
2107 {
2108 me->RemoveNpcFlag(UNIT_NPC_FLAG_BANKER | UNIT_NPC_FLAG_VENDOR);
2109 uint32 _mailAura = IsArgentSquire() ? SPELL_AURA_POSTMAN_S : SPELL_AURA_POSTMAN_G;
2110 if (!me->HasAura(_mailAura))
2111 DoCastSelf(_mailAura);
2112
2113 if (!player->HasAura(SPELL_TIRED_PLAYER))
2114 player->CastSpell(player, SPELL_TIRED_PLAYER, true);
2115 break;
2116 }
2122 if (IsArgentSquire())
2123 DoCastSelf(bannerSpells[gossipListId - 3].spellSquire, true);
2124 else
2125 DoCastSelf(bannerSpells[gossipListId - 3].spellGruntling, true);
2126
2127 player->PlayerTalkClass->SendCloseGossip();
2128 break;
2129 default:
2130 break;
2131 }
2132
2133 return false;
2134 }
2135
2136 bool IsArgentSquire() const { return me->GetEntry() == NPC_ARGENT_SQUIRE; }
2137 };
2138
2139 CreatureAI* GetAI(Creature *creature) const override
2140 {
2141 return new npc_argent_squire_gruntlingAI(creature);
2142 }
2143};
2144
2146{
2165
2166typedef std::unordered_map<uint32 /*Entry*/, uint32 /*Spell*/> ChairSpells;
2168{
2174};
2175
2177{
2178 public:
2179 CastFoodSpell(Unit* owner, uint32 spellId) : _owner(owner), _spellId(spellId) { }
2180
2181 bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
2182 {
2183 _owner->CastSpell(_owner, _spellId, true);
2184 return true;
2185 }
2186
2187 private:
2190};
2191
2193{
2194public:
2195 npc_bountiful_table() : CreatureScript("npc_bountiful_table") { }
2196
2198 {
2199 npc_bountiful_tableAI(Creature* creature) : PassiveAI(creature) { }
2200
2201 void PassengerBoarded(Unit* who, int8 seatId, bool /*apply*/) override
2202 {
2203 float x = 0.0f;
2204 float y = 0.0f;
2205 float z = 0.0f;
2206 float o = 0.0f;
2207
2208 switch (seatId)
2209 {
2210 case SEAT_TURKEY_CHAIR:
2211 x = 3.87f;
2212 y = 2.07f;
2213 o = 3.700098f;
2214 break;
2216 x = 3.87f;
2217 y = -2.07f;
2218 o = 2.460914f;
2219 break;
2221 x = -2.52f;
2222 break;
2224 x = -0.09f;
2225 y = -3.24f;
2226 o = 1.186824f;
2227 break;
2228 case SEAT_PIE_CHAIR:
2229 x = -0.18f;
2230 y = 3.24f;
2231 o = 5.009095f;
2232 break;
2233 case SEAT_FOOD_HOLDER:
2234 case SEAT_PLATE_HOLDER:
2235 if (Vehicle* holders = who->GetVehicleKit())
2236 holders->InstallAllAccessories(true);
2237 return;
2238 default:
2239 break;
2240 }
2241
2242 std::function<void(Movement::MoveSplineInit&)> initializer = [=](Movement::MoveSplineInit& init)
2243 {
2244 init.DisableTransportPathTransformations();
2245 init.MoveTo(x, y, z, false);
2246 init.SetFacing(o);
2247 };
2249 who->m_Events.AddEvent(new CastFoodSpell(who, _chairSpells.at(who->GetEntry())), who->m_Events.CalculateTime(1s));
2250 if (Creature* creature = who->ToCreature())
2251 creature->SetDisplayFromModel(0);
2252 }
2253 };
2254
2255 CreatureAI* GetAI(Creature* creature) const override
2256 {
2257 return new npc_bountiful_tableAI(creature);
2258 }
2259};
2260
2262{
2263 SPELL_CONSUMPTION = 28874
2265
2267{
2268 npc_gen_void_zone(Creature* creature) : ScriptedAI(creature) { }
2269
2270 void InitializeAI() override
2271 {
2272 me->SetReactState(REACT_PASSIVE);
2273 }
2274
2275 void JustAppeared() override
2276 {
2277 _scheduler.Schedule(2s, [this](TaskContext /*task*/)
2278 {
2279 DoCastSelf(SPELL_CONSUMPTION);
2280 });
2281 }
2282
2283 void UpdateAI(uint32 diff) override
2284 {
2285 _scheduler.Update(diff);
2286 }
2287
2288private:
2290};
2291
2293{
2294 new npc_air_force_bots();
2295 new npc_chicken_cluck();
2299 new npc_doctor();
2300 new npc_injured_patient();
2302 new npc_guardian();
2303 new npc_steam_tonk();
2308 new npc_wormhole();
2309 new npc_spring_rabbit();
2310 new npc_imp_in_a_ball();
2311 new npc_train_wrecker();
2313 new npc_bountiful_table();
2315}
@ IN_MILLISECONDS
Definition: Common.h:35
#define sCreatureTextMgr
@ TEXT_RANGE_NORMAL
T GetEntry(std::unordered_map< uint32, T > const &map, CriteriaTreeEntry const *tree)
uint8_t uint8
Definition: Define.h:144
int8_t int8
Definition: Define.h:140
int32_t int32
Definition: Define.h:138
uint64_t uint64
Definition: Define.h:141
uint32_t uint32
Definition: Define.h:142
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition: Duration.h:32
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition: Duration.h:29
#define ASSERT_NODEBUGINFO
Definition: Errors.h:69
bool IsHolidayActive(HolidayIds id)
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
LootItemType
Definition: LootItemType.h:24
@ MOTION_PRIORITY_HIGHEST
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
Definition: ObjectDefines.h:66
std::list< ObjectGuid > GuidList
Definition: ObjectGuid.h:394
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
std::vector< ObjectGuid > GuidVector
Definition: ObjectGuid.h:395
#define sObjectMgr
Definition: ObjectMgr.h:1946
#define PET_FOLLOW_ANGLE
Definition: PetDefines.h:98
#define PET_FOLLOW_DIST
Definition: PetDefines.h:97
@ QUEST_STATUS_INCOMPLETE
Definition: QuestDef.h:145
@ QUEST_STATUS_NONE
Definition: QuestDef.h:142
@ QUEST_STATUS_COMPLETE
Definition: QuestDef.h:143
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:42
uint32 rand32()
Definition: Random.cpp:70
bool roll_chance_i(int chance)
Definition: Random.h:59
#define RegisterCreatureAI(ai_name)
Definition: ScriptMgr.h:1380
void GetCreatureListWithEntryInGrid(Container &container, WorldObject *source, uint32 entry, float maxSearchRange)
void AddGossipItemFor(Player *player, GossipOptionNpc optionNpc, std::string text, uint32 sender, uint32 action)
void SendGossipMenuFor(Player *player, uint32 npcTextID, ObjectGuid const &guid)
void ClearGossipMenuFor(Player *player)
void InitGossipMenuFor(Player *player, uint32 menuId)
void CloseGossipMenuFor(Player *player)
@ GOSSIP_SENDER_MAIN
@ GOSSIP_ACTION_INFO_DEF
@ CLASS_DEATH_KNIGHT
@ LANG_ADDON
Emote
@ EMOTE_ONESHOT_LAUGH_NO_SHEATHE
@ EMOTE_ONESHOT_ATTACK1H
@ EMOTE_ONESHOT_APPLAUD
@ EMOTE_ONESHOT_QUESTION
@ EMOTE_ONESHOT_SHY
@ EMOTE_ONESHOT_LAUGH
@ EMOTE_ONESHOT_BOW
@ EMOTE_ONESHOT_RUDE
@ EMOTE_STATE_DANCE
@ EMOTE_ONESHOT_DANCE
@ EMOTE_ONESHOT_EAT_NO_SHEATHE
@ EMOTE_ONESHOT_NONE
@ EMOTE_ONESHOT_SHOUT
@ EMOTE_ONESHOT_WAVE
@ EVENT_VEHICLE_BOARD
@ TEXT_EMOTE_BOW
@ TEXT_EMOTE_CHICKEN
@ TEXT_EMOTE_CHEER
@ TEXT_EMOTE_DANCE
@ TEXT_EMOTE_KISS
@ TEXT_EMOTE_WAVE
@ TEXT_EMOTE_JOKE
@ HORDE
@ FACTION_FRIENDLY
@ FACTION_PREY
@ HOLIDAY_BREWFEST
@ CHAT_MSG_MONSTER_WHISPER
@ CHAT_MSG_MONSTER_PARTY
#define ENSURE_AI(a, b)
Definition: UnitAI.h:29
@ REACT_PASSIVE
Definition: UnitDefines.h:506
@ REACT_AGGRESSIVE
Definition: UnitDefines.h:508
@ UNIT_STAND_STATE_DEAD
Definition: UnitDefines.h:49
@ UNIT_STAND_STATE_KNEEL
Definition: UnitDefines.h:50
@ UNIT_STAND_STATE_STAND
Definition: UnitDefines.h:42
@ UNIT_NPC_FLAG_BANKER
Definition: UnitDefines.h:314
@ UNIT_NPC_FLAG_VENDOR
Definition: UnitDefines.h:304
@ UNIT_NPC_FLAG_QUESTGIVER
Definition: UnitDefines.h:298
@ UNIT_NPC_FLAG_MAILBOX
Definition: UnitDefines.h:323
DamageEffectType
Definition: UnitDefines.h:131
@ DOT
Definition: UnitDefines.h:134
@ UNIT_FLAG3_FAKE_DEAD
Definition: UnitDefines.h:259
@ UNIT_FLAG_NON_ATTACKABLE
Definition: UnitDefines.h:145
@ UNIT_FLAG_IN_COMBAT
Definition: UnitDefines.h:163
@ UNIT_FLAG_PLAYER_CONTROLLED
Definition: UnitDefines.h:147
@ JUST_DIED
Definition: Unit.h:247
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition: Util.h:491
@ SAY_RANDOM
@ EVENT_EMOTE
Definition: boss_laj.cpp:48
bool Execute(uint64, uint32) override
CastFoodSpell(Unit *owner, uint32 spellId)
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
Definition: CreatureAI.cpp:219
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool UpdateVictim()
Definition: CreatureAI.cpp:245
Creature *const me
Definition: CreatureAI.h:61
void setDeathState(DeathState s) override
Definition: Creature.cpp:2197
uint32 ExecuteEvent()
Definition: EventMap.cpp:73
void Update(uint32 time)
Definition: EventMap.h:56
void ScheduleEvent(uint32 eventId, Milliseconds time, uint32 group=0, uint8 phase=0)
Definition: EventMap.cpp:36
void Reset()
Definition: EventMap.cpp:21
void AddEvent(BasicEvent *event, Milliseconds e_time, bool set_addtime=true)
Milliseconds CalculateTime(Milliseconds t_offset) const
void DespawnOrUnsummon(Milliseconds delay=0ms, Seconds forceRespawnTime=0s)
void LaunchMoveSpline(std::function< void(Movement::MoveSplineInit &init)> &&initializer, uint32 id=0, MovementGeneratorPriority priority=MOTION_PRIORITY_NORMAL, MovementGeneratorType type=EFFECT_MOTION_TYPE)
void MovePoint(uint32 id, Position const &pos, bool generatePath=true, Optional< float > finalOrient={}, Optional< float > speed={}, MovementWalkRunSpeedSelectionMode speedSelectionMode=MovementWalkRunSpeedSelectionMode::Default, Optional< float > closeEnoughDistance={})
bool IsEmpty() const
Definition: ObjectGuid.h:319
void Clear()
Definition: ObjectGuid.h:286
static Creature * ToCreature(Object *o)
Definition: Object.h:219
Player * ToPlayer()
Definition: Object.h:215
TypeID GetTypeId() const
Definition: Object.h:173
uint32 GetEntry() const
Definition: Object.h:161
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
static Player * ToPlayer(Object *o)
Definition: Object.h:213
bool GetQuestRewardStatus(uint32 quest_id) const
Definition: Player.cpp:16033
bool HasAchieved(uint32 achievementId) const
Definition: Player.cpp:26751
void AreaExploredOrEventHappens(uint32 questId)
Definition: Player.cpp:16577
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition: Player.cpp:16050
void FailQuest(uint32 quest_id)
Definition: Player.cpp:15446
std::unique_ptr< PlayerMenu > PlayerTalkClass
Definition: Player.h:2380
Team GetTeam() const
Definition: Player.h:2235
uint32 GetQuestId() const
Definition: QuestDef.h:587
uint32 const Id
Definition: SpellInfo.h:325
TaskContext & Repeat(std::chrono::duration< Rep, Period > duration)
TaskScheduler & CancelAll()
TaskScheduler & Schedule(std::chrono::duration< Rep, Period > time, task_handler_t task)
TaskScheduler & Update(success_t const &callback=nullptr)
WorldObject * GetSummoner() const
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.h:159
SpellCastResult DoCast(uint32 spellId)
Definition: UnitAI.cpp:89
Definition: Unit.h:627
void SetHealth(uint64 val)
Definition: Unit.cpp:9346
void SetUnitFlag3(UnitFlags3 flags)
Definition: Unit.h:843
int64 ModifyHealth(int64 val)
Definition: Unit.cpp:8182
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition: Unit.cpp:10100
uint8 GetClass() const
Definition: Unit.h:752
void SetFaction(uint32 faction) override
Definition: Unit.h:859
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
bool IsAlive() const
Definition: Unit.h:1164
void RemoveNpcFlag(NPCFlags flags)
Definition: Unit.h:983
TempSummon * ToTempSummon()
Definition: Unit.h:1756
void SetUninteractible(bool apply)
Definition: Unit.cpp:8147
void SetEmoteState(Emote emote)
Definition: Unit.h:852
uint64 GetHealth() const
Definition: Unit.h:776
void SetNpcFlag(NPCFlags flags)
Definition: Unit.h:982
bool SetWalk(bool enable)
Definition: Unit.cpp:12707
void EngageWithTarget(Unit *who)
Definition: Unit.cpp:8077
bool HasNpcFlag(NPCFlags flags) const
Definition: Unit.h:981
uint64 CountPctFromMaxHealth(int32 pct) const
Definition: Unit.h:785
void SetFacingTo(float const ori, bool force=true)
Definition: Unit.cpp:12653
bool IsEngagedBy(Unit const *who) const
Definition: Unit.h:1020
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4664
void HandleEmoteCommand(Emote emoteId, Player *target=nullptr, Trinity::IteratorPair< int32 const * > spellVisualKitIds={}, int32 sequenceVariation=0)
Definition: Unit.cpp:1598
void SetUnitFlag(UnitFlags flags)
Definition: Unit.h:833
bool IsFlying() const
Definition: Unit.h:1735
Vehicle * GetVehicleKit() const
Definition: Unit.h:1711
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition: Unit.cpp:3831
void RemoveUnitFlag(UnitFlags flags)
Definition: Unit.h:834
GameObject * FindNearestGameObject(uint32 entry, float range, bool spawnedOnly=true) const
Definition: Object.cpp:2170
bool IsWithinLOS(float x, float y, float z, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags=VMAP::ModelIgnoreFlags::Nothing) const
Definition: Object.cpp:1161
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
bool IsValidAttackTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition: Object.cpp:2991
bool IsHostileTo(WorldObject const *target) const
Definition: Object.cpp:2860
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition: Object.cpp:2025
Unit * GetOwner() const
Definition: Object.cpp:2229
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition: Object.cpp:2148
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition: Object.cpp:1147
EventProcessor m_Events
Definition: Object.h:777
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
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
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
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
@ EVENT_TALK
RibbonPoleData
Definition: midsummer.cpp:112
void apply(T *val)
Definition: ByteConverter.h:41
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API GameObject * GetGameObject(WorldObject const &u, ObjectGuid const &guid)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition: Containers.h:109
ArgentPetGossipOptions
@ GOSSIP_OPTION_GNOMEREGAN_ORGRIMMAR_PENNANT
@ GOSSIP_OPTION_EXODAR_UNDERCITY_PENNANT
@ GOSSIP_OPTION_SHOP
@ GOSSIP_OPTION_STORMWIND_THUNDERBLUFF_PENNANT
@ GOSSIP_OPTION_DARNASSUS_SENJIN_PENNANT
@ GOSSIP_OPTION_MAIL
@ GOSSIP_OPTION_IRONFORGE_SILVERMOON_PENNANT
@ GOSSIP_OPTION_BANK
Position const HordeCoords[]
#define A_RUNTOX
TournamentQuestsAchievements
@ ACHIEVEMENT_CHAMPION_UNDERCITY
@ QUEST_VALIANT_OF_UNDERCITY
@ ACHIEVEMENT_CHAMPION_THUNDER_BLUFF
@ QUEST_A_VALIANT_OF_STORMWIND
@ QUEST_A_VALIANT_OF_GNOMEREGAN
@ ACHIEVEMENT_CHAMPION_IRONFORGE
@ ACHIEVEMENT_CHAMPION_DARNASSUS
@ QUEST_VALIANT_OF_STORMWIND
@ QUEST_VALIANT_OF_GNOMEREGAN
@ ACHIEVEMENT_CHAMPION_SILVERMOON
@ QUEST_VALIANT_OF_DARNASSUS
@ ACHIEVEMENT_CHAMPION_GNOMEREGAN
@ QUEST_VALIANT_OF_ORGRIMMAR
@ QUEST_VALIANT_OF_THUNDER_BLUFF
@ QUEST_VALIANT_OF_IRONFORGE
@ QUEST_VALIANT_OF_SILVERMOON
@ QUEST_A_VALIANT_OF_SILVERMOON
@ QUEST_VALIANT_OF_SEN_JIN
@ ACHIEVEMENT_CHAMPION_HORDE
@ QUEST_VALIANT_OF_THE_EXODAR
@ ACHIEVEMENT_CHAMPION_STORMWIND
@ QUEST_A_VALIANT_OF_DARNASSUS
@ ACHIEVEMENT_CHAMPION_ALLIANCE
@ ACHIEVEMENT_ARGENT_VALOR
@ QUEST_A_VALIANT_OF_ORGRIMMAR
@ ACHIEVEMENT_CHAMPION_SEN_JIN
@ QUEST_A_VALIANT_OF_UNDERCITY
@ QUEST_A_VALIANT_OF_THUNDER_BLUFF
@ QUEST_A_VALIANT_OF_SEN_JIN
@ QUEST_A_VALIANT_OF_IRONFORGE
@ ACHIEVEMENT_CHAMPION_ORGRIMMAR
@ QUEST_A_VALIANT_OF_THE_EXODAR
@ ACHIEVEMENT_CHAMPION_THE_EXODAR
VoidZone
@ SPELL_CONSUMPTION
float constexpr RANGE_ALARMBOT
#define A_RUNTOZ
NPC_Wormhole
@ GOSSIP_OPTION_4
@ SPELL_STORM_PEAKS
@ GOSSIP_OPTION_6
@ SPELL_UNDERGROUND
@ MENU_ID_WORMHOLE
@ SPELL_SHOLAZAR_BASIN
@ GOSSIP_OPTION_3
@ SPELL_BOREAN_TUNDRA
@ GOSSIP_OPTION_2
@ SPELL_HOWLING_FJORD
@ GOSSIP_OPTION_5
@ GOSSIP_OPTION_1
@ SPELL_ICECROWN
@ NPC_TEXT_WORMHOLE
#define H_RUNTOX
float constexpr RANGE_TRIPWIRE
ArgentPonyBannerSpells const bannerSpells[5]
@ ACHIEVEMENT_PONY_UP
@ NPC_ARGENT_SQUIRE
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
TrainWrecker
@ MOVEID_CHASE
@ EVENT_DO_JUMP
@ SPELL_TOY_TRAIN_PULSE
@ NPC_EXULTING_WIND_UP_TRAIN_WRECKER
@ GO_TOY_TRAIN
@ EVENT_DO_DANCE
@ EVENT_DO_FACING
@ MOVEID_JUMP
@ SPELL_WRECK_TRAIN
@ EVENT_DO_WRECK
TournamentMounts
@ NPC_ARGENT_WARHORSE
@ NPC_DARNASSIAN_NIGHTSABER
@ NPC_STORMWIND_STEED
@ NPC_IRONFORGE_RAM
@ NPC_SILVERMOON_HAWKSTRIDER
@ NPC_FORSAKEN_WARHORSE
@ NPC_ARGENT_STEED_ASPIRANT
@ NPC_THUNDER_BLUFF_KODO
@ NPC_EXODAR_ELEKK
@ NPC_DARK_SPEAR_RAPTOR
@ NPC_GNOMEREGAN_MECHANOSTRIDER
@ NPC_ARGENT_HAWKSTRIDER_ASPIRANT
@ NPC_ORGRIMMAR_WOLF
Pennants
@ SPELL_SILVERMOON_PENNANT
@ SPELL_UNDERCITY_PENNANT
@ SPELL_AURA_BANK_G
@ SPELL_TIRED_PLAYER
@ SPELL_AURA_POSTMAN_S
@ SPELL_GNOMEREGAN_PENNANT
@ SPELL_IRONFORGE_PENNANT
@ SPELL_AURA_SHOP_S
@ SPELL_AURA_TIRED_G
@ SPELL_DARNASSUS_PENNANT
@ SPELL_SENJIN_PENNANT
@ SPELL_ORGRIMMAR_PENNANT
@ SPELL_AURA_BANK_S
@ SPELL_AURA_SHOP_G
@ SPELL_STORMWIND_PENNANT
@ SPELL_AURA_TIRED_S
@ SPELL_AURA_POSTMAN_G
@ SPELL_THUNDERBLUFF_PENNANT
@ SPELL_EXODAR_PENNANT
#define A_RUNTOY
BrewfestReveler
@ SPELL_BREWFEST_TOAST
Doctor
@ ALLIANCE_COORDS
@ SAY_DOC
@ HORDE_COORDS
@ DOCTOR_HORDE
@ DOCTOR_ALLIANCE
ChairSpells const _chairSpells
AirForceSpawn constexpr airforceSpawns[]
@ EVENT_CAST_RED_FIRE_RING
@ SPELL_RED_FIRE_RING
@ SPELL_RIBBON_DANCE_COSMETIC
@ GO_RIBBON_POLE
@ SPELL_BLUE_FIRE_RING
@ EVENT_CAST_BLUE_FIRE_RING
DancingFlames
@ SPELL_SUMMON_BRAZIER
@ SPELL_FIERY_SEDUCTION
@ SPELL_BRAZIER_DANCE
Emote const BrewfestRandomEmote[]
ChickenCluck
@ QUEST_CLUCK
@ EMOTE_HELLO_A
@ EMOTE_HELLO_H
@ EMOTE_CLUCK_TEXT
Position const AllianceCoords[]
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]
TournamentPennantSpells
@ SPELL_PENNANT_EXODAR_ASPIRANT
@ SPELL_PENNANT_IRONFORGE_ASPIRANT
@ SPELL_PENNANT_GNOMEREGAN_ASPIRANT
@ SPELL_PENNANT_EBON_BLADE_CHAMPION
@ SPELL_PENNANT_IRONFORGE_CHAMPION
@ SPELL_PENNANT_ORGRIMMAR_CHAMPION
@ SPELL_PENNANT_THUNDER_BLUFF_CHAMPION
@ SPELL_PENNANT_ORGRIMMAR_VALIANT
@ SPELL_PENNANT_STORMWIND_CHAMPION
@ SPELL_PENNANT_THUNDER_BLUFF_VALIANT
@ SPELL_PENNANT_SEN_JIN_ASPIRANT
@ SPELL_PENNANT_ORGRIMMAR_ASPIRANT
@ SPELL_PENNANT_UNDERCITY_CHAMPION
@ SPELL_PENNANT_GNOMEREGAN_VALIANT
@ SPELL_PENNANT_GNOMEREGAN_CHAMPION
@ SPELL_PENNANT_EBON_BLADE_VALIANT
@ SPELL_PENNANT_IRONFORGE_VALIANT
@ SPELL_PENNANT_STORMWIND_VALIANT
@ SPELL_PENNANT_UNDERCITY_ASPIRANT
@ SPELL_PENNANT_UNDERCITY_VALIANT
@ SPELL_PENNANT_ARGENT_CRUSADE_VALIANT
@ SPELL_PENNANT_STORMWIND_ASPIRANT
@ SPELL_PENNANT_EXODAR_VALIANT
@ SPELL_PENNANT_ARGENT_CRUSADE_CHAMPION
@ SPELL_PENNANT_EBON_BLADE_ASPIRANT
@ SPELL_PENNANT_SILVERMOON_VALIANT
@ SPELL_PENNANT_SILVERMOON_CHAMPION
@ SPELL_PENNANT_SEN_JIN_VALIANT
@ SPELL_PENNANT_ARGENT_CRUSADE_ASPIRANT
@ SPELL_PENNANT_SEN_JIN_CHAMPION
@ SPELL_PENNANT_DARNASSUS_CHAMPION
@ SPELL_PENNANT_THUNDER_BLUFF_ASPIRANT
@ SPELL_PENNANT_DARNASSUS_VALIANT
@ SPELL_PENNANT_DARNASSUS_ASPIRANT
@ SPELL_PENNANT_EXODAR_CHAMPION
@ SPELL_PENNANT_SILVERMOON_ASPIRANT
void AddSC_npcs_special()
BountifulTable
@ SPELL_TURKEY_SERVER
@ NPC_THE_TURKEY_CHAIR
@ NPC_THE_PIE_CHAIR
@ NPC_THE_SWEET_POTATO_CHAIR
@ SEAT_STUFFING_CHAIR
@ SPELL_CRANBERRY_SERVER
@ SEAT_CRANBERRY_CHAIR
@ SEAT_TURKEY_CHAIR
@ SEAT_SWEET_POTATO_CHAIR
@ NPC_THE_STUFFING_CHAIR
@ SEAT_PIE_CHAIR
@ SEAT_FOOD_HOLDER
@ SPELL_STUFFING_SERVER
@ NPC_THE_CRANBERRY_CHAIR
@ SPELL_SWEET_POTATOES_SERVER
@ SPELL_PIE_SERVER
@ SEAT_PLATE_HOLDER
TorchTossingTarget
@ SPELL_TORCH_TARGET_PICKER
#define H_RUNTOY
uint32 const HordeSoldierId[3]
AirForceBots
@ SPELL_GUARDS_MARK
@ ALARMBOT
@ TRIPWIRE
std::unordered_map< uint32, uint32 > ChairSpells
#define H_RUNTOZ
GuardianSpells
@ SPELL_DEATHTOUCH
AirForceBots type
static void VisitWorldObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition: CellImpl.h:191
void UpdateAI(uint32 diff) override
constexpr float GetPositionX() const
Definition: Position.h:76
constexpr float GetPositionY() const
Definition: Position.h:77
float GetAbsoluteAngle(float x, float y) const
Definition: Position.h:125
constexpr void GetPosition(float &x, float &y) const
Definition: Position.h:81
constexpr void Relocate(float x, float y)
Definition: Position.h:63
constexpr float GetPositionZ() const
Definition: Position.h:78
static AirForceSpawn const & FindSpawnFor(uint32 entry)
void MoveInLineOfSight(Unit *who) override
std::unordered_set< ObjectGuid > _toAttack
bool OnGossipSelect(Player *player, uint32, uint32 gossipListId) override
void PassengerBoarded(Unit *who, int8 seatId, bool) override
== Fields =======================================
void ReceiveEmote(Player *player, uint32 emote) override
void ReceiveEmote(Player *player, uint32 emote) override
npc_brewfest_reveler_2(Creature *creature)
void UpdateAI(uint32 diff) override
void UpdateAI(uint32 diff) override
void ReceiveEmote(Player *player, uint32 emote) override
void OnQuestAccept(Player *, Quest const *quest) override
void OnQuestReward(Player *, Quest const *quest, LootItemType, uint32) override
void ReceiveEmote(Player *player, uint32 emote) override
void Reset() override
TaskScheduler _scheduler
npc_dancing_flames(Creature *creature)
void UpdateAI(uint32 diff) override
void BeginEvent(Player *player)
void PatientSaved(Creature *, Player *player, Position const *point)
void PatientDied(Position const *point)
npc_doctorAI(Creature *creature)
std::vector< Position const * > Coordinates
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *) override
void OnQuestAccept(Player *player, Quest const *quest) override
void SpellHit(WorldObject *caster, SpellInfo const *spellInfo) override
void UpdateAI(uint32 diff) override
TaskScheduler _scheduler
npc_gen_void_zone(Creature *creature)
void JustAppeared() override
void InitializeAI() override
void JustEngagedWith(Unit *) override
void UpdateAI(uint32) override
npc_guardianAI(Creature *creature)
void IsSummonedBy(WorldObject *summoner) override
void UpdateAI(uint32 diff) override
void SpellHit(WorldObject *caster, SpellInfo const *spellInfo) override
void UpdateAI(uint32 diff) override
npc_steam_tonkAI(Creature *creature)
void JustEngagedWith(Unit *) override
uint32 GetPennantSpellId(Player *player) const
void PassengerBoarded(Unit *passenger, int8, bool apply) override
== Fields =======================================
void UpdateAI(uint32 diff) override
void MovementInform(uint32, uint32 id) override
void JustEnteredCombat(Unit *who) override
std::unordered_map< ObjectGuid, Milliseconds > _combatTimer
void DamageTaken(Unit *attacker, uint32 &damage, DamageEffectType damageType, SpellInfo const *) override
npc_training_dummy(Creature *creature)
void UpdateAI(uint32 diff) override
bool OnGossipHello(Player *player) override
npc_wormholeAI(Creature *creature)
bool OnGossipSelect(Player *player, uint32, uint32 gossipListId) override