TrinityCore
Loading...
Searching...
No Matches
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 "CombatAI.h"
21#include "Containers.h"
22#include "CreatureTextMgr.h"
23#include "GameEventMgr.h"
24#include "GridNotifiersImpl.h"
25#include "Log.h"
26#include "MotionMaster.h"
27#include "MoveSplineInit.h"
28#include "ObjectAccessor.h"
29#include "ObjectMgr.h"
30#include "PassiveAI.h"
31#include "Pet.h"
32#include "ScriptedEscortAI.h"
33#include "ScriptedGossip.h"
34#include "SmartAI.h"
35#include "SpellAuras.h"
36#include "SpellHistory.h"
37#include "SpellMgr.h"
38#include "Vehicle.h"
39#include "World.h"
40
41/*########
42# npc_air_force_bots
43#########*/
44
46{
47 TRIPWIRE, // do not attack flying players, smaller range
48 ALARMBOT, // attack flying players, casts guard's mark
49
50 SPELL_GUARDS_MARK = 38067
51};
52
53float constexpr RANGE_TRIPWIRE = 15.0f;
54float constexpr RANGE_ALARMBOT = 100.0f;
55
62
64{
65 {2614, 15241, ALARMBOT}, // Air Force Alarm Bot (Alliance)
66 {2615, 15242, ALARMBOT}, // Air Force Alarm Bot (Horde)
67 {21974, 21976, ALARMBOT}, // Air Force Alarm Bot (Area 52)
68 {21993, 15242, ALARMBOT}, // Air Force Guard Post (Horde - Bat Rider)
69 {21996, 15241, ALARMBOT}, // Air Force Guard Post (Alliance - Gryphon)
70 {21997, 21976, ALARMBOT}, // Air Force Guard Post (Goblin - Area 52 - Zeppelin)
71 {21999, 15241, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Alliance)
72 {22001, 15242, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Horde)
73 {22002, 15242, TRIPWIRE}, // Air Force Trip Wire - Ground (Horde)
74 {22003, 15241, TRIPWIRE}, // Air Force Trip Wire - Ground (Alliance)
75 {22063, 21976, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Goblin - Area 52)
76 {22065, 22064, ALARMBOT}, // Air Force Guard Post (Ethereal - Stormspire)
77 {22066, 22067, ALARMBOT}, // Air Force Guard Post (Scryer - Dragonhawk)
78 {22068, 22064, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Ethereal - Stormspire)
79 {22069, 22064, ALARMBOT}, // Air Force Alarm Bot (Stormspire)
80 {22070, 22067, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Scryer)
81 {22071, 22067, ALARMBOT}, // Air Force Alarm Bot (Scryer)
82 {22078, 22077, ALARMBOT}, // Air Force Alarm Bot (Aldor)
83 {22079, 22077, ALARMBOT}, // Air Force Guard Post (Aldor - Gryphon)
84 {22080, 22077, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Aldor)
85 {22086, 22085, ALARMBOT}, // Air Force Alarm Bot (Sporeggar)
86 {22087, 22085, ALARMBOT}, // Air Force Guard Post (Sporeggar - Spore Bat)
87 {22088, 22085, TRIPWIRE}, // Air Force Trip Wire - Rooftop (Sporeggar)
88 {22090, 22089, ALARMBOT}, // Air Force Guard Post (Toshley's Station - Flying Machine)
89 {22124, 22122, ALARMBOT}, // Air Force Alarm Bot (Cenarion)
90 {22125, 22122, ALARMBOT}, // Air Force Guard Post (Cenarion - Stormcrow)
91 {22126, 22122, ALARMBOT} // Air Force Trip Wire - Rooftop (Cenarion Expedition)
92};
93
95{
96public:
97 npc_air_force_bots() : CreatureScript("npc_air_force_bots") { }
98
100 {
101 static AirForceSpawn const& FindSpawnFor(uint32 entry)
102 {
103 for (AirForceSpawn const& spawn : airforceSpawns)
104 {
105 if (spawn.myEntry == entry)
106 {
107 ASSERT_NODEBUGINFO(sObjectMgr->GetCreatureTemplate(spawn.otherEntry), "Invalid creature entry %u in 'npc_air_force_bots' script", spawn.otherEntry);
108 return spawn;
109 }
110 }
111 ASSERT_NODEBUGINFO(false, "Unhandled creature with entry %u is assigned 'npc_air_force_bots' script", entry);
112 }
113
114 npc_air_force_botsAI(Creature* creature) : NullCreatureAI(creature), _spawn(FindSpawnFor(creature->GetEntry())) {}
115
117 {
119
120 if (!guard && (guard = me->SummonCreature(_spawn.otherEntry, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5min)))
121 _myGuard = guard->GetGUID();
122
123 return guard;
124 }
125
126 void UpdateAI(uint32 /*diff*/) override
127 {
128 if (_toAttack.empty())
129 return;
130
131 Creature* guard = GetOrSummonGuard();
132 if (!guard)
133 return;
134
135 // Keep the list of targets for later on when the guards will be alive
136 if (!guard->IsAlive())
137 return;
138
139 for (ObjectGuid guid : _toAttack)
140 {
141 Unit* target = ObjectAccessor::GetUnit(*me, guid);
142 if (!target)
143 continue;
144 if (guard->IsEngagedBy(target))
145 continue;
146
147 guard->EngageWithTarget(target);
148 if (_spawn.type == ALARMBOT)
149 guard->CastSpell(target, SPELL_GUARDS_MARK, true);
150 }
151
152 _toAttack.clear();
153 }
154
155 void MoveInLineOfSight(Unit* who) override
156 {
157 // guards are only spawned against players
158 if (who->GetTypeId() != TYPEID_PLAYER)
159 return;
160
161 // we're already scheduled to attack this player on our next tick, don't bother checking
162 if (_toAttack.find(who->GetGUID()) != _toAttack.end())
163 return;
164
165 // check if they're in range
167 return;
168
169 // check if they're hostile
170 if (!(me->IsHostileTo(who) || who->IsHostileTo(me)))
171 return;
172
173 // check if they're a valid attack target
174 if (!me->IsValidAttackTarget(who))
175 return;
176
177 if ((_spawn.type == TRIPWIRE) && who->IsFlying())
178 return;
179
180 _toAttack.insert(who->GetGUID());
181 }
182
183 private:
186 std::unordered_set<ObjectGuid> _toAttack;
187
188 };
189
190 CreatureAI* GetAI(Creature* creature) const override
191 {
192 return new npc_air_force_botsAI(creature);
193 }
194};
195
196/*########
197# npc_chicken_cluck
198#########*/
199
208
210{
211public:
212 npc_chicken_cluck() : CreatureScript("npc_chicken_cluck") { }
213
215 {
217 {
218 Initialize();
219 }
220
222 {
223 ResetFlagTimer = 120000;
224 }
225
227
228 void Reset() override
229 {
230 Initialize();
233 }
234
235 void JustEngagedWith(Unit* /*who*/) override { }
236
237 void UpdateAI(uint32 diff) override
238 {
239 // Reset flags after a certain time has passed so that the next player has to start the 'event' again
241 {
242 if (ResetFlagTimer <= diff)
243 {
245 return;
246 }
247 else
248 ResetFlagTimer -= diff;
249 }
250
251 if (UpdateVictim())
253 }
254
255 void ReceiveEmote(Player* player, uint32 emote) override
256 {
257 switch (emote)
258 {
260 if (player->GetQuestStatus(QUEST_CLUCK) == QUEST_STATUS_NONE && rand32() % 30 == 1)
261 {
264 Talk(player->GetTeam() == HORDE ? EMOTE_HELLO_H : EMOTE_HELLO_A);
265 }
266 break;
267 case TEXT_EMOTE_CHEER:
269 {
273 }
274 break;
275 }
276 }
277
278 void OnQuestAccept(Player* /*player*/, Quest const* quest) override
279 {
280 if (quest->GetQuestId() == QUEST_CLUCK)
281 Reset();
282 }
283
284 void OnQuestReward(Player* /*player*/, Quest const* quest, uint32 /*opt*/) override
285 {
286 if (quest->GetQuestId() == QUEST_CLUCK)
287 Reset();
288 }
289 };
290
291 CreatureAI* GetAI(Creature* creature) const override
292 {
293 return new npc_chicken_cluckAI(creature);
294 }
295};
296
297/*######
298## npc_dancing_flames
299######*/
300
307
309{
310 npc_dancing_flames(Creature* creature) : ScriptedAI(creature) { }
311
312 void Reset() override
313 {
317 float x, y, z;
318 me->GetPosition(x, y, z);
319 me->Relocate(x, y, z + 1.05f);
320 }
321
322 void UpdateAI(uint32 diff) override
323 {
324 _scheduler.Update(diff);
325 }
326
327 void ReceiveEmote(Player* player, uint32 emote) override
328 {
329 if (me->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()) && me->IsWithinDistInMap(player, 30.0f))
330 {
331 // She responds to emotes not instantly but ~1500ms later
332 // If you first /bow, then /wave before dancing flames bow back, it doesnt bow at all and only does wave
333 // If you're performing emotes too fast, she will not respond to them
334 // Means she just replaces currently scheduled event with new after receiving new emote
336
337 switch (emote)
338 {
339 case TEXT_EMOTE_KISS:
340 _scheduler.Schedule(1500ms, [this](TaskContext /*context*/)
341 {
343 });
344 break;
345 case TEXT_EMOTE_WAVE:
346 _scheduler.Schedule(1500ms, [this](TaskContext /*context*/)
347 {
349 });
350 break;
351 case TEXT_EMOTE_BOW:
352 _scheduler.Schedule(1500ms, [this](TaskContext /*context*/)
353 {
355 });
356 break;
357 case TEXT_EMOTE_JOKE:
358 _scheduler.Schedule(1500ms, [this](TaskContext /*context*/)
359 {
361 });
362 break;
363 case TEXT_EMOTE_DANCE:
364 if (!player->HasAura(SPELL_FIERY_SEDUCTION))
365 {
366 DoCast(player, SPELL_FIERY_SEDUCTION, true);
368 }
369 break;
370 }
371 }
372 }
373
374private:
376};
377
378/*######
379## npc_torch_tossing_target_bunny_controller
380######*/
381
386
388{
389public:
390 npc_torch_tossing_target_bunny_controller() : CreatureScript("npc_torch_tossing_target_bunny_controller") { }
391
393 {
395
396 void Reset() override
397 {
398 _scheduler.Schedule(Seconds(2), [this](TaskContext context)
399 {
401 _scheduler.Schedule(Seconds(3), [this](TaskContext /*context*/)
402 {
404 });
405 context.Repeat(Seconds(5));
406 });
407 }
408
409 void UpdateAI(uint32 diff) override
410 {
411 _scheduler.Update(diff);
412 }
413
414 private:
416 };
417
418 CreatureAI* GetAI(Creature* creature) const override
419 {
421 }
422};
423
424/*######
425## npc_midsummer_bunny_pole
426######*/
427
437
439{
440public:
441 npc_midsummer_bunny_pole() : CreatureScript("npc_midsummer_bunny_pole") { }
442
444 {
446 {
447 Initialize();
448 }
449
451 {
452 events.Reset();
453 running = false;
454 }
455
456 void Reset() override
457 {
458 Initialize();
459 }
460
461 void DoAction(int32 /*action*/) override
462 {
463 // Don't start event if it's already running.
464 if (running)
465 return;
466
467 running = true;
469 }
470
472 {
473 // Returns true if no nearby player has aura "Test Ribbon Pole Channel".
474 std::list<Player*> players;
477 Cell::VisitWorldObjects(me, searcher, 10.0f);
478
479 return players.empty();
480 }
481
482 void UpdateAI(uint32 diff) override
483 {
484 if (!running)
485 return;
486
487 events.Update(diff);
488
489 switch (events.ExecuteEvent())
490 {
492 {
493 if (checkNearbyPlayers())
494 {
495 Reset();
496 return;
497 }
498
500 me->CastSpell(go, SPELL_RED_FIRE_RING, true);
501
503 }
504 break;
506 {
507 if (checkNearbyPlayers())
508 {
509 Reset();
510 return;
511 }
512
515
517 }
518 break;
519 }
520 }
521
522 private:
525 };
526
527 CreatureAI* GetAI(Creature* creature) const override
528 {
529 return new npc_midsummer_bunny_poleAI(creature);
530 }
531};
532
533/*######
534## Triage quest
535######*/
536
546
548{
549 {-3757.38f, -4533.05f, 14.16f, 3.62f}, // Top-far-right bunk as seen from entrance
550 {-3754.36f, -4539.13f, 14.16f, 5.13f}, // Top-far-left bunk
551 {-3749.54f, -4540.25f, 14.28f, 3.34f}, // Far-right bunk
552 {-3742.10f, -4536.85f, 14.28f, 3.64f}, // Right bunk near entrance
553 {-3755.89f, -4529.07f, 14.05f, 0.57f}, // Far-left bunk
554 {-3749.51f, -4527.08f, 14.07f, 5.26f}, // Mid-left bunk
555 {-3746.37f, -4525.35f, 14.16f, 5.22f}, // Left bunk near entrance
556};
557
558//alliance run to where
559#define A_RUNTOX -3742.96f
560#define A_RUNTOY -4531.52f
561#define A_RUNTOZ 11.91f
562
564{
565 {-1013.75f, -3492.59f, 62.62f, 4.34f}, // Left, Behind
566 {-1017.72f, -3490.92f, 62.62f, 4.34f}, // Right, Behind
567 {-1015.77f, -3497.15f, 62.82f, 4.34f}, // Left, Mid
568 {-1019.51f, -3495.49f, 62.82f, 4.34f}, // Right, Mid
569 {-1017.25f, -3500.85f, 62.98f, 4.34f}, // Left, front
570 {-1020.95f, -3499.21f, 62.98f, 4.34f} // Right, Front
571};
572
573//horde run to where
574#define H_RUNTOX -1016.44f
575#define H_RUNTOY -3508.48f
576#define H_RUNTOZ 62.96f
577
579{
580 12938, // 12938 Injured Alliance Soldier
581 12936, // 12936 Badly injured Alliance Soldier
582 12937 // 12937 Critically injured Alliance Soldier
583};
584
586{
587 12923, //12923 Injured Soldier
588 12924, //12924 Badly injured Soldier
589 12925 //12925 Critically injured Soldier
590};
591
592/*######
593## npc_doctor (handles both Gustaf Vanhowzen and Gregory Victor)
594######*/
596{
597public:
598 npc_doctor() : CreatureScript("npc_doctor") { }
599
600 struct npc_doctorAI : public ScriptedAI
601 {
602 npc_doctorAI(Creature* creature) : ScriptedAI(creature)
603 {
604 Initialize();
605 }
606
608 {
610
611 SummonPatientTimer = 10000;
615
616 Patients.clear();
617 Coordinates.clear();
618
619 Event = false;
620 }
621
623
628
629 bool Event;
630
632 std::vector<Position const*> Coordinates;
633
634 void Reset() override
635 {
636 Initialize();
638 }
639
640 void BeginEvent(Player* player)
641 {
642 PlayerGUID = player->GetGUID();
643
644 SummonPatientTimer = 10000;
648
649 switch (me->GetEntry())
650 {
651 case DOCTOR_ALLIANCE:
652 for (uint8 i = 0; i < ALLIANCE_COORDS; ++i)
653 Coordinates.push_back(&AllianceCoords[i]);
654 break;
655 case DOCTOR_HORDE:
656 for (uint8 i = 0; i < HORDE_COORDS; ++i)
657 Coordinates.push_back(&HordeCoords[i]);
658 break;
659 }
660
661 Event = true;
663 }
664
665 void PatientDied(Position const* point)
666 {
668 if (player && ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)))
669 {
671
672 if (PatientDiedCount > 5 && Event)
673 {
674 if (player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
675 player->FailQuest(6624);
676 else if (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
677 player->FailQuest(6622);
678
679 Reset();
680 return;
681 }
682
683 Coordinates.push_back(point);
684 }
685 else
686 // If no player or player abandon quest in progress
687 Reset();
688 }
689
690 void PatientSaved(Creature* /*soldier*/, Player* player, Position const* point)
691 {
692 if (player && PlayerGUID == player->GetGUID())
693 {
694 if ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))
695 {
697
698 if (PatientSavedCount == 15)
699 {
700 if (!Patients.empty())
701 {
702 for (GuidList::const_iterator itr = Patients.begin(); itr != Patients.end(); ++itr)
703 {
704 if (Creature* patient = ObjectAccessor::GetCreature(*me, *itr))
705 patient->setDeathState(JUST_DIED);
706 }
707 }
708
709 if (player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE)
710 player->AreaExploredOrEventHappens(6624);
711 else if (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
712 player->AreaExploredOrEventHappens(6622);
713
714 Reset();
715 return;
716 }
717
718 Coordinates.push_back(point);
719 }
720 }
721 }
722
723 void UpdateAI(uint32 diff) override;
724
725 void JustEngagedWith(Unit* /*who*/) override { }
726
727 void OnQuestAccept(Player* player, Quest const* quest) override
728 {
729 if ((quest->GetQuestId() == 6624) || (quest->GetQuestId() == 6622))
730 BeginEvent(player);
731 }
732 };
733
734 CreatureAI* GetAI(Creature* creature) const override
735 {
736 return new npc_doctorAI(creature);
737 }
738};
739
740/*#####
741## npc_injured_patient (handles all the patients, no matter Horde or Alliance)
742#####*/
743
745{
746public:
747 npc_injured_patient() : CreatureScript("npc_injured_patient") { }
748
750 {
752 {
753 Initialize();
754 }
755
757 {
759 Coord = nullptr;
760 }
761
764
765 void Reset() override
766 {
767 Initialize();
768
769 //no select
771
772 //no regen health
774
775 //to make them lay with face down
777
778 uint32 mobId = me->GetEntry();
779
780 switch (mobId)
781 { //lower max health
782 case 12923:
783 case 12938: //Injured Soldier
785 break;
786 case 12924:
787 case 12936: //Badly injured Soldier
789 break;
790 case 12925:
791 case 12937: //Critically injured Soldier
793 break;
794 }
795 }
796
797 void JustEngagedWith(Unit* /*who*/) override { }
798
799 void SpellHit(WorldObject* caster, SpellInfo const* spellInfo) override
800 {
801 Player* player = caster->ToPlayer();
802 if (!player || !me->IsAlive() || spellInfo->Id != 20804)
803 return;
804
805 if (player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE)
806 if (!DoctorGUID.IsEmpty())
808 ENSURE_AI(npc_doctor::npc_doctorAI, doctor->AI())->PatientSaved(me, player, Coord);
809
810 //make uninteractible
812
813 //regen health
815
816 //stand up
818
819 Talk(SAY_DOC);
820
821 uint32 mobId = me->GetEntry();
822 me->SetWalk(false);
823
824 switch (mobId)
825 {
826 case 12923:
827 case 12924:
828 case 12925:
830 break;
831 case 12936:
832 case 12937:
833 case 12938:
835 break;
836 }
837 }
838
839 void UpdateAI(uint32 /*diff*/) override
840 {
841 //lower HP on every world tick makes it a useful counter, not officlone though
842 if (me->IsAlive() && me->GetHealth() > 6)
843 me->ModifyHealth(-5);
844
845 if (me->IsAlive() && me->GetHealth() <= 6)
846 {
850 me->SetDynamicFlag(32);
851
852 if (!DoctorGUID.IsEmpty())
854 ENSURE_AI(npc_doctor::npc_doctorAI, doctor->AI())->PatientDied(Coord);
855 }
856 }
857 };
858
859 CreatureAI* GetAI(Creature* creature) const override
860 {
861 return new npc_injured_patientAI(creature);
862 }
863};
864
866{
867 if (Event && SummonPatientCount >= 20)
868 {
869 Reset();
870 return;
871 }
872
873 if (Event)
874 {
875 if (SummonPatientTimer <= diff)
876 {
877 if (Coordinates.empty())
878 return;
879
880 uint32 patientEntry = 0;
881
882 switch (me->GetEntry())
883 {
884 case DOCTOR_ALLIANCE:
885 patientEntry = AllianceSoldierId[rand32() % 3];
886 break;
887 case DOCTOR_HORDE:
888 patientEntry = HordeSoldierId[rand32() % 3];
889 break;
890 default:
891 TC_LOG_ERROR("scripts", "Invalid entry for Triage doctor. Please check your database");
892 return;
893 }
894
895 std::vector<Position const*>::iterator point = Coordinates.begin();
896 std::advance(point, urand(0, Coordinates.size() - 1));
897
898 if (Creature* Patient = me->SummonCreature(patientEntry, **point, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5s))
899 {
900 Patients.push_back(Patient->GetGUID());
901 ENSURE_AI(npc_injured_patient::npc_injured_patientAI, Patient->AI())->DoctorGUID = me->GetGUID();
902 ENSURE_AI(npc_injured_patient::npc_injured_patientAI, Patient->AI())->Coord = *point;
903
904 Coordinates.erase(point);
905 }
906
907 SummonPatientTimer = 10000;
909 }
910 else
911 SummonPatientTimer -= diff;
912 }
913}
914
915/*######
916## npc_guardian
917######*/
918
923
925{
926public:
927 npc_guardian() : CreatureScript("npc_guardian") { }
928
930 {
931 npc_guardianAI(Creature* creature) : ScriptedAI(creature) { }
932
933 void Reset() override
934 {
935 me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
936 }
937
938 void JustEngagedWith(Unit* /*who*/) override
939 {
940 }
941
942 void UpdateAI(uint32 /*diff*/) override
943 {
944 if (!UpdateVictim())
945 return;
946
947 if (me->isAttackReady())
948 {
949 DoCastVictim(SPELL_DEATHTOUCH, true);
950 me->resetAttackTimer();
951 }
952 }
953 };
954
955 CreatureAI* GetAI(Creature* creature) const override
956 {
957 return new npc_guardianAI(creature);
958 }
959};
960
962{
963public:
964 npc_steam_tonk() : CreatureScript("npc_steam_tonk") { }
965
967 {
968 npc_steam_tonkAI(Creature* creature) : ScriptedAI(creature) { }
969
970 void Reset() override { }
971 void JustEngagedWith(Unit* /*who*/) override { }
972
973 void OnPossess(bool apply)
974 {
975 if (apply)
976 {
977 // Initialize the action bar without the melee attack command
978 me->InitCharmInfo();
979 me->GetCharmInfo()->InitEmptyActionBar(false);
980
981 me->SetReactState(REACT_PASSIVE);
982 }
983 else
984 me->SetReactState(REACT_AGGRESSIVE);
985 }
986 };
987
988 CreatureAI* GetAI(Creature* creature) const override
989 {
990 return new npc_steam_tonkAI(creature);
991 }
992};
993
995{
1033
1050
1088
1090{
1091 public:
1092 npc_tournament_mount() : CreatureScript("npc_tournament_mount") { }
1093
1095 {
1097 {
1098 _pennantSpellId = 0;
1099 }
1100
1101 void PassengerBoarded(Unit* passenger, int8 /*seatId*/, bool apply) override
1102 {
1103 Player* player = passenger->ToPlayer();
1104 if (!player)
1105 return;
1106
1107 if (apply)
1108 {
1109 _pennantSpellId = GetPennantSpellId(player);
1110 player->CastSpell(nullptr, _pennantSpellId, true);
1111 }
1112 else
1113 player->RemoveAurasDueToSpell(_pennantSpellId);
1114 }
1115
1116 private:
1118
1120 {
1121 switch (me->GetEntry())
1122 {
1125 {
1130 else
1132 }
1134 {
1139 else
1141 }
1143 {
1148 else
1150 }
1153 {
1158 else
1160 }
1162 {
1167 else
1169 }
1170 case NPC_EXODAR_ELEKK:
1171 {
1176 else
1178 }
1179 case NPC_IRONFORGE_RAM:
1180 {
1185 else
1187 }
1189 {
1194 else
1196 }
1197 case NPC_ORGRIMMAR_WOLF:
1198 {
1203 else
1205 }
1207 {
1212 else
1214 }
1216 {
1219 else if (player->HasAchieved(ACHIEVEMENT_ARGENT_VALOR))
1221 else
1223 }
1224 default:
1225 return 0;
1226 }
1227 }
1228 };
1229
1230 CreatureAI* GetAI(Creature* creature) const override
1231 {
1232 return new npc_tournament_mountAI(creature);
1233 }
1234};
1235
1236/*####
1237## npc_brewfest_reveler
1238####*/
1239
1244
1246{
1247 public:
1248 npc_brewfest_reveler() : CreatureScript("npc_brewfest_reveler") { }
1249
1251 {
1252 npc_brewfest_revelerAI(Creature* creature) : ScriptedAI(creature) { }
1253
1254 void ReceiveEmote(Player* player, uint32 emote) override
1255 {
1257 return;
1258
1259 if (emote == TEXT_EMOTE_DANCE)
1260 me->CastSpell(player, SPELL_BREWFEST_TOAST, false);
1261 }
1262 };
1263
1264 CreatureAI* GetAI(Creature* creature) const override
1265 {
1266 return new npc_brewfest_revelerAI(creature);
1267 }
1268};
1269
1270/*######
1271# npc_brewfest_reveler_2
1272######*/
1273
1282
1284{
1286 {
1287 NPC_BREWFEST_REVELER = 24484,
1288
1289 EVENT_FILL_LIST = 1,
1290 EVENT_FACE_TO = 2,
1292 EVENT_NEXT = 4
1294
1295 npc_brewfest_reveler_2(Creature* creature) : ScriptedAI(creature) { }
1296
1297 void Reset() override
1298 {
1299 _events.Reset();
1300 _events.ScheduleEvent(EVENT_FILL_LIST, 1s, 2s);
1301 }
1302
1303 // Copied from old script. I don't know if this is 100% correct.
1304 void ReceiveEmote(Player* player, uint32 emote) override
1305 {
1307 return;
1308
1309 if (emote == TEXT_EMOTE_DANCE)
1310 me->CastSpell(player, SPELL_BREWFEST_TOAST, false);
1311 }
1312
1313 void UpdateAI(uint32 diff) override
1314 {
1315 UpdateVictim();
1316
1317 _events.Update(diff);
1318
1319 while (uint32 eventId = _events.ExecuteEvent())
1320 {
1321 switch (eventId)
1322 {
1323 case EVENT_FILL_LIST:
1324 {
1325 std::list<Creature*> creatureList;
1326 GetCreatureListWithEntryInGrid(creatureList, me, NPC_BREWFEST_REVELER, 5.0f);
1327 for (Creature* creature : creatureList)
1328 if (creature != me)
1329 _revelerGuids.push_back(creature->GetGUID());
1330
1331 _events.ScheduleEvent(EVENT_FACE_TO, 1s, 2s);
1332 break;
1333 }
1334 case EVENT_FACE_TO:
1335 {
1336 // Turn to random brewfest reveler within set range
1337 if (!_revelerGuids.empty())
1339 me->SetFacingToObject(creature);
1340
1341 _events.ScheduleEvent(EVENT_EMOTE, 2s, 6s);
1342 break;
1343 }
1344 case EVENT_EMOTE:
1345 // Play random emote or dance
1346 if (roll_chance_i(50))
1347 {
1349 _events.ScheduleEvent(EVENT_NEXT, 4s, 6s);
1350 }
1351 else
1352 {
1353 me->SetEmoteState(EMOTE_STATE_DANCE);
1354 _events.ScheduleEvent(EVENT_NEXT, 8s, 12s);
1355 }
1356 break;
1357 case EVENT_NEXT:
1358 // If dancing stop before next random state
1359 if (me->GetEmoteState() == EMOTE_STATE_DANCE)
1360 me->SetEmoteState(EMOTE_ONESHOT_NONE);
1361
1362 // Random EVENT_EMOTE or EVENT_FACETO
1363 if (roll_chance_i(50))
1364 _events.ScheduleEvent(EVENT_FACE_TO, 1s);
1365 else
1366 _events.ScheduleEvent(EVENT_EMOTE, 1s);
1367 break;
1368 default:
1369 break;
1370 }
1371 }
1372 }
1373
1374private:
1377};
1378
1380{
1381 npc_training_dummy(Creature* creature) : NullCreatureAI(creature) { }
1382
1383 void JustEnteredCombat(Unit* who) override
1384 {
1385 _combatTimer[who->GetGUID()] = 5s;
1386 }
1387
1388 void DamageTaken(Unit* attacker, uint32& damage, DamageEffectType damageType, SpellInfo const* /*spellInfo = nullptr*/) override
1389 {
1390 damage = 0;
1391
1392 if (!attacker || damageType == DOT)
1393 return;
1394
1395 _combatTimer[attacker->GetGUID()] = 5s;
1396 }
1397
1398 void UpdateAI(uint32 diff) override
1399 {
1400 for (auto itr = _combatTimer.begin(); itr != _combatTimer.end();)
1401 {
1402 itr->second -= Milliseconds(diff);
1403 if (itr->second <= 0s)
1404 {
1405 // The attacker has not dealt any damage to the dummy for over 5 seconds. End combat.
1406 auto const& pveRefs = me->GetCombatManager().GetPvECombatRefs();
1407 auto it = pveRefs.find(itr->first);
1408 if (it != pveRefs.end())
1409 it->second->EndCombat();
1410
1411 itr = _combatTimer.erase(itr);
1412 }
1413 else
1414 ++itr;
1415 }
1416 }
1417private:
1418 std::unordered_map<ObjectGuid /*attackerGUID*/, Milliseconds /*combatTime*/> _combatTimer;
1419};
1420
1421/*######
1422# npc_wormhole
1423######*/
1424
1426{
1427 MENU_ID_WORMHOLE = 10668, // "This tear in the fabric of time and space looks ominous."
1428 NPC_TEXT_WORMHOLE = 14785, // (not 907 "What brings you to this part of the world, $n?")
1429 GOSSIP_OPTION_1 = 0, // "Borean Tundra"
1430 GOSSIP_OPTION_2 = 1, // "Howling Fjord"
1431 GOSSIP_OPTION_3 = 2, // "Sholazar Basin"
1432 GOSSIP_OPTION_4 = 3, // "Icecrown"
1433 GOSSIP_OPTION_5 = 4, // "Storm Peaks"
1434 GOSSIP_OPTION_6 = 5, // "Underground..."
1435
1439 SPELL_ICECROWN = 67836, // 3
1440 SPELL_STORM_PEAKS = 67837, // 4
1441 SPELL_UNDERGROUND = 68081 // 5
1443
1445{
1446 public:
1447 npc_wormhole() : CreatureScript("npc_wormhole") { }
1448
1450 {
1451 npc_wormholeAI(Creature* creature) : PassiveAI(creature)
1452 {
1453 Initialize();
1454 }
1455
1457 {
1458 _showUnderground = urand(0, 100) == 0; // Guessed value, it is really rare though
1459 }
1460
1461 void InitializeAI() override
1462 {
1463 Initialize();
1464 }
1465
1488
1489 bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
1490 {
1491 uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
1492 ClearGossipMenuFor(player);
1493
1494 switch (action)
1495 {
1496 case GOSSIP_ACTION_INFO_DEF + 1: // Borean Tundra
1497 CloseGossipMenuFor(player);
1498 DoCast(player, SPELL_BOREAN_TUNDRA, false);
1499 break;
1500 case GOSSIP_ACTION_INFO_DEF + 2: // Howling Fjord
1501 CloseGossipMenuFor(player);
1502 DoCast(player, SPELL_HOWLING_FJORD, false);
1503 break;
1504 case GOSSIP_ACTION_INFO_DEF + 3: // Sholazar Basin
1505 CloseGossipMenuFor(player);
1506 DoCast(player, SPELL_SHOLAZAR_BASIN, false);
1507 break;
1508 case GOSSIP_ACTION_INFO_DEF + 4: // Icecrown
1509 CloseGossipMenuFor(player);
1510 DoCast(player, SPELL_ICECROWN, false);
1511 break;
1512 case GOSSIP_ACTION_INFO_DEF + 5: // Storm peaks
1513 CloseGossipMenuFor(player);
1514 DoCast(player, SPELL_STORM_PEAKS, false);
1515 break;
1516 case GOSSIP_ACTION_INFO_DEF + 6: // Underground
1517 CloseGossipMenuFor(player);
1518 DoCast(player, SPELL_UNDERGROUND, false);
1519 break;
1520 }
1521
1522 return true;
1523 }
1524
1525 private:
1527 };
1528
1529 CreatureAI* GetAI(Creature* creature) const override
1530 {
1531 return new npc_wormholeAI(creature);
1532 }
1533};
1534
1535/*######
1536## npc_pet_trainer
1537######*/
1538
1544
1546{
1547public:
1548 npc_pet_trainer() : CreatureScript("npc_pet_trainer") { }
1549
1551 {
1552 npc_pet_trainerAI(Creature* creature) : ScriptedAI(creature) { }
1553
1554 bool OnGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
1555 {
1556 if (menuId == MENU_ID_PET_UNLEARN && gossipListId == OPTION_ID_PLEASE_DO)
1557 {
1558 player->ResetPetTalents();
1559 CloseGossipMenuFor(player);
1560 }
1561 return false;
1562 }
1563 };
1564
1565 CreatureAI* GetAI(Creature* creature) const override
1566 {
1567 return new npc_pet_trainerAI(creature);
1568 }
1569};
1570
1571/*######
1572## npc_experience
1573######*/
1574
1576{
1579 OPTION_ID_XP_OFF = 0, // "I no longer wish to gain experience."
1580 OPTION_ID_XP_ON = 1 // "I wish to start gaining experience again."
1582
1584{
1585public:
1586 npc_experience() : CreatureScript("npc_experience") { }
1587
1589 {
1590 npc_experienceAI(Creature* creature) : ScriptedAI(creature) { }
1591
1592 bool OnGossipHello(Player* player) override
1593 {
1595 if (player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN)) // not gaining XP
1596 {
1599 }
1600 else // currently gaining XP
1601 {
1604 }
1605 return true;
1606 }
1607
1608 bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
1609 {
1610 uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
1611
1612 switch (action)
1613 {
1614 case GOSSIP_ACTION_INFO_DEF + 1: // XP ON selected
1615 player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); // turn on XP gain
1616 break;
1617 case GOSSIP_ACTION_INFO_DEF + 2: // XP OFF selected
1618 player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_NO_XP_GAIN); // turn off XP gain
1619 break;
1620 }
1621 CloseGossipMenuFor(player);
1622 return false;
1623 }
1624 };
1625
1626 CreatureAI* GetAI(Creature* creature) const override
1627 {
1628 return new npc_experienceAI(creature);
1629 }
1630};
1631
1632/*#####
1633# npc_spring_rabbit
1634#####*/
1635
1645
1647{
1648public:
1649 npc_spring_rabbit() : CreatureScript("npc_spring_rabbit") { }
1650
1651 CreatureAI* GetAI(Creature* creature) const override
1652 {
1653 return new npc_spring_rabbitAI(creature);
1654 }
1655
1657 {
1659 {
1660 Initialize();
1661 }
1662
1664 {
1665 inLove = false;
1666 rabbitGUID.Clear();
1667 jumpTimer = urand(5000, 10000);
1668 bunnyTimer = urand(10000, 20000);
1669 searchTimer = urand(5000, 10000);
1670 }
1671
1677
1678 void Reset() override
1679 {
1680 Initialize();
1681 if (Unit* owner = me->GetOwner())
1682 me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
1683 }
1684
1685 void JustEngagedWith(Unit* /*who*/) override { }
1686
1687 void DoAction(int32 /*param*/) override
1688 {
1689 inLove = true;
1690 if (Unit* owner = me->GetOwner())
1691 owner->CastSpell(owner, SPELL_SPRING_FLING, true);
1692 }
1693
1694 void UpdateAI(uint32 diff) override
1695 {
1696 if (inLove)
1697 {
1698 if (jumpTimer <= diff)
1699 {
1700 if (Unit* rabbit = ObjectAccessor::GetUnit(*me, rabbitGUID))
1701 DoCast(rabbit, SPELL_SPRING_RABBIT_JUMP);
1702 jumpTimer = urand(5000, 10000);
1703 } else jumpTimer -= diff;
1704
1705 if (bunnyTimer <= diff)
1706 {
1708 bunnyTimer = urand(20000, 40000);
1709 } else bunnyTimer -= diff;
1710 }
1711 else
1712 {
1713 if (searchTimer <= diff)
1714 {
1715 if (Creature* rabbit = me->FindNearestCreature(NPC_SPRING_RABBIT, 10.0f))
1716 {
1717 if (rabbit == me || rabbit->HasAura(SPELL_SPRING_RABBIT_IN_LOVE))
1718 return;
1719
1720 me->AddAura(SPELL_SPRING_RABBIT_IN_LOVE, me);
1721 DoAction(1);
1722 rabbit->AddAura(SPELL_SPRING_RABBIT_IN_LOVE, rabbit);
1723 rabbit->AI()->DoAction(1);
1724 rabbit->CastSpell(rabbit, SPELL_SPRING_RABBIT_JUMP, true);
1725 rabbitGUID = rabbit->GetGUID();
1726 }
1727 searchTimer = urand(5000, 10000);
1728 } else searchTimer -= diff;
1729 }
1730 }
1731 };
1732};
1733
1735{
1736private:
1737 enum
1738 {
1740
1742 };
1743
1744public:
1745 npc_imp_in_a_ball() : CreatureScript("npc_imp_in_a_ball") { }
1746
1748 {
1750 {
1751 summonerGUID.Clear();
1752 }
1753
1754 void IsSummonedBy(WorldObject* summoner) override
1755 {
1756 if (summoner->GetTypeId() == TYPEID_PLAYER)
1757 {
1758 summonerGUID = summoner->GetGUID();
1759 events.ScheduleEvent(EVENT_TALK, 3s);
1760 }
1761 }
1762
1763 void UpdateAI(uint32 diff) override
1764 {
1765 events.Update(diff);
1766
1767 if (events.ExecuteEvent() == EVENT_TALK)
1768 {
1769 if (Player* owner = ObjectAccessor::GetPlayer(*me, summonerGUID))
1770 {
1771 sCreatureTextMgr->SendChat(me, SAY_RANDOM, owner,
1773 }
1774 }
1775 }
1776
1777 private:
1780 };
1781
1782 CreatureAI* GetAI(Creature* creature) const override
1783 {
1784 return new npc_imp_in_a_ballAI(creature);
1785 }
1786};
1787
1800
1802{
1803 public:
1804 npc_stable_master() : CreatureScript("npc_stable_master") { }
1805
1807 {
1808 npc_stable_masterAI(Creature* creature) : SmartAI(creature) { }
1809
1810 bool OnGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
1811 {
1812 SmartAI::OnGossipSelect(player, menuId, gossipListId);
1813 if (menuId != STABLE_MASTER_GOSSIP_SUB_MENU)
1814 return false;
1815
1816 switch (gossipListId)
1817 {
1818 case 0:
1819 player->CastSpell(player, SPELL_MINIWING, false);
1820 break;
1821 case 1:
1822 player->CastSpell(player, SPELL_JUBLING, false);
1823 break;
1824 case 2:
1825 player->CastSpell(player, SPELL_DARTER, false);
1826 break;
1827 case 3:
1828 player->CastSpell(player, SPELL_WORG, false);
1829 break;
1830 case 4:
1831 player->CastSpell(player, SPELL_SMOLDERWEB, false);
1832 break;
1833 case 5:
1834 player->CastSpell(player, SPELL_CHIKEN, false);
1835 break;
1836 case 6:
1837 player->CastSpell(player, SPELL_WOLPERTINGER, false);
1838 break;
1839 default:
1840 return false;
1841 }
1842
1844 return false;
1845 }
1846 };
1847
1848 CreatureAI* GetAI(Creature* creature) const override
1849 {
1850 return new npc_stable_masterAI(creature);
1851 }
1852};
1853
1867{
1868 public:
1869 npc_train_wrecker() : CreatureScript("npc_train_wrecker") { }
1870
1872 {
1873 npc_train_wreckerAI(Creature* creature) : NullCreatureAI(creature), _isSearching(true), _nextAction(0), _timer(1 * IN_MILLISECONDS) { }
1874
1876 {
1877 if (GameObject* target = ObjectAccessor::GetGameObject(*me, _target))
1878 return target;
1879 me->HandleEmoteCommand(EMOTE_ONESHOT_RUDE);
1880 me->DespawnOrUnsummon(3s);
1881 return nullptr;
1882 }
1883
1884 void UpdateAI(uint32 diff) override
1885 {
1886 if (_isSearching)
1887 {
1888 if (diff < _timer)
1889 _timer -= diff;
1890 else
1891 {
1892 if (GameObject* target = me->FindNearestGameObject(GO_TOY_TRAIN, 15.0f))
1893 {
1894 _isSearching = false;
1895 _target = target->GetGUID();
1896 me->SetWalk(true);
1897 me->GetMotionMaster()->MovePoint(MOVEID_CHASE, target->GetNearPosition(3.0f, target->GetAbsoluteAngle(me)));
1898 }
1899 else
1900 _timer = 3 * IN_MILLISECONDS;
1901 }
1902 }
1903 else
1904 {
1905 switch (_nextAction)
1906 {
1907 case EVENT_DO_JUMP:
1908 if (GameObject* target = VerifyTarget())
1909 me->GetMotionMaster()->MoveJump(*target, 5.0, 10.0, MOVEID_JUMP);
1910 _nextAction = 0;
1911 break;
1912 case EVENT_DO_FACING:
1913 if (GameObject* target = VerifyTarget())
1914 {
1915 me->SetFacingTo(target->GetOrientation());
1916 me->HandleEmoteCommand(EMOTE_ONESHOT_ATTACK1H);
1917 _timer = 1.5 * AsUnderlyingType(IN_MILLISECONDS);
1918 _nextAction = EVENT_DO_WRECK;
1919 }
1920 else
1921 _nextAction = 0;
1922 break;
1923 case EVENT_DO_WRECK:
1924 if (diff < _timer)
1925 {
1926 _timer -= diff;
1927 break;
1928 }
1929 if (GameObject* target = VerifyTarget())
1930 {
1931 me->CastSpell(target, SPELL_WRECK_TRAIN, false);
1932 _timer = 2 * IN_MILLISECONDS;
1933 _nextAction = EVENT_DO_DANCE;
1934 }
1935 else
1936 _nextAction = 0;
1937 break;
1938 case EVENT_DO_DANCE:
1939 if (diff < _timer)
1940 {
1941 _timer -= diff;
1942 break;
1943 }
1944 me->SetEmoteState(EMOTE_ONESHOT_DANCE);
1945 me->DespawnOrUnsummon(5s);
1946 _nextAction = 0;
1947 break;
1948 default:
1949 break;
1950 }
1951 }
1952 }
1953
1954 void MovementInform(uint32 /*type*/, uint32 id) override
1955 {
1956 if (id == MOVEID_CHASE)
1957 _nextAction = EVENT_DO_JUMP;
1958 else if (id == MOVEID_JUMP)
1959 _nextAction = EVENT_DO_FACING;
1960 }
1961
1962 private:
1967 };
1968
1969 CreatureAI* GetAI(Creature* creature) const override
1970 {
1971 return new npc_train_wreckerAI(creature);
1972 }
1973};
1974
1975/*######
1976## npc_argent_squire/gruntling
1977######*/
1978
2001
2013
2015{
2016 NPC_ARGENT_SQUIRE = 33238
2018
2024
2033
2035{
2036public:
2037 npc_argent_squire_gruntling() : CreatureScript("npc_argent_squire_gruntling") { }
2038
2040 {
2042 {
2043 ScheduleTasks();
2044 }
2045
2047 {
2048 _scheduler
2049 .Schedule(Seconds(1), [this](TaskContext /*context*/)
2050 {
2051 if (Aura* ownerTired = me->GetOwner()->GetAura(SPELL_TIRED_PLAYER))
2052 if (Aura* squireTired = me->AddAura(IsArgentSquire() ? SPELL_AURA_TIRED_S : SPELL_AURA_TIRED_G, me))
2053 squireTired->SetDuration(ownerTired->GetDuration());
2054 })
2055 .Schedule(Seconds(1), [this](TaskContext context)
2056 {
2057 if ((me->HasAura(SPELL_AURA_TIRED_S) || me->HasAura(SPELL_AURA_TIRED_G)) && me->HasNpcFlag(UNIT_NPC_FLAG_BANKER | UNIT_NPC_FLAG_MAILBOX | UNIT_NPC_FLAG_VENDOR))
2059 context.Repeat();
2060 });
2061 }
2062
2063 bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
2064 {
2065 switch (gossipListId)
2066 {
2067 case GOSSIP_OPTION_BANK:
2068 {
2069 me->SetNpcFlag(UNIT_NPC_FLAG_BANKER);
2070 uint32 _bankAura = IsArgentSquire() ? SPELL_AURA_BANK_S : SPELL_AURA_BANK_G;
2071 if (!me->HasAura(_bankAura))
2072 DoCastSelf(_bankAura);
2073
2074 if (!player->HasAura(SPELL_TIRED_PLAYER))
2075 player->CastSpell(player, SPELL_TIRED_PLAYER, true);
2076 break;
2077 }
2078 case GOSSIP_OPTION_SHOP:
2079 {
2080 me->SetNpcFlag(UNIT_NPC_FLAG_VENDOR);
2081 uint32 _shopAura = IsArgentSquire() ? SPELL_AURA_SHOP_S : SPELL_AURA_SHOP_G;
2082 if (!me->HasAura(_shopAura))
2083 DoCastSelf(_shopAura);
2084
2085 if (!player->HasAura(SPELL_TIRED_PLAYER))
2086 player->CastSpell(player, SPELL_TIRED_PLAYER, true);
2087 break;
2088 }
2089 case GOSSIP_OPTION_MAIL:
2090 {
2091 me->SetNpcFlag(UNIT_NPC_FLAG_MAILBOX);
2092 player->GetSession()->SendShowMailBox(me->GetGUID());
2093
2094 uint32 _mailAura = IsArgentSquire() ? SPELL_AURA_POSTMAN_S : SPELL_AURA_POSTMAN_G;
2095 if (!me->HasAura(_mailAura))
2096 DoCastSelf(_mailAura);
2097
2098 if (!player->HasAura(SPELL_TIRED_PLAYER))
2099 player->CastSpell(player, SPELL_TIRED_PLAYER, true);
2100 break;
2101 }
2107 if (IsArgentSquire())
2108 DoCastSelf(bannerSpells[gossipListId - 3].spellSquire, true);
2109 else
2110 DoCastSelf(bannerSpells[gossipListId - 3].spellGruntling, true);
2111 break;
2112 }
2114 return false;
2115 }
2116
2117 void UpdateAI(uint32 diff) override
2118 {
2119 _scheduler.Update(diff);
2120 }
2121
2122 bool IsArgentSquire() const { return me->GetEntry() == NPC_ARGENT_SQUIRE; }
2123
2124 private:
2126 };
2127
2128 CreatureAI* GetAI(Creature *creature) const override
2129 {
2130 return new npc_argent_squire_gruntlingAI(creature);
2131 }
2132};
2133
2154
2155typedef std::unordered_map<uint32 /*Entry*/, uint32 /*Spell*/> ChairSpells;
2164
2166{
2167 public:
2168 CastFoodSpell(Unit* owner, uint32 spellId) : _owner(owner), _spellId(spellId) { }
2169
2170 bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
2171 {
2172 _owner->CastSpell(_owner, _spellId, true);
2173 return true;
2174 }
2175
2176 private:
2179};
2180
2182{
2183public:
2184 npc_bountiful_table() : CreatureScript("npc_bountiful_table") { }
2185
2187 {
2188 npc_bountiful_tableAI(Creature* creature) : PassiveAI(creature) { }
2189
2190 void PassengerBoarded(Unit* who, int8 seatId, bool /*apply*/) override
2191 {
2192 float x = 0.0f;
2193 float y = 0.0f;
2194 float z = 0.0f;
2195 float o = 0.0f;
2196
2197 switch (seatId)
2198 {
2199 case SEAT_TURKEY_CHAIR:
2200 x = 3.87f;
2201 y = 2.07f;
2202 o = 3.700098f;
2203 break;
2205 x = 3.87f;
2206 y = -2.07f;
2207 o = 2.460914f;
2208 break;
2210 x = -2.52f;
2211 break;
2213 x = -0.09f;
2214 y = -3.24f;
2215 o = 1.186824f;
2216 break;
2217 case SEAT_PIE_CHAIR:
2218 x = -0.18f;
2219 y = 3.24f;
2220 o = 5.009095f;
2221 break;
2222 case SEAT_FOOD_HOLDER:
2223 case SEAT_PLATE_HOLDER:
2224 if (Vehicle* holders = who->GetVehicleKit())
2225 holders->InstallAllAccessories(true);
2226 return;
2227 default:
2228 break;
2229 }
2230
2231 std::function<void(Movement::MoveSplineInit&)> initializer = [=](Movement::MoveSplineInit& init)
2232 {
2233 init.DisableTransportPathTransformations();
2234 init.MoveTo(x, y, z, false);
2235 init.SetFacing(o);
2236 };
2238 who->m_Events.AddEvent(new CastFoodSpell(who, _chairSpells.at(who->GetEntry())), who->m_Events.CalculateTime(1s));
2239 if (who->GetTypeId() == TYPEID_UNIT)
2241 }
2242 };
2243
2244 CreatureAI* GetAI(Creature* creature) const override
2245 {
2246 return new npc_bountiful_tableAI(creature);
2247 }
2248};
2249
2251{
2252 SPELL_CONSUMPTION = 28874
2254
2256{
2257 npc_gen_void_zone(Creature* creature) : ScriptedAI(creature) { }
2258
2259 void InitializeAI() override
2260 {
2261 me->SetReactState(REACT_PASSIVE);
2262 }
2263
2264 void JustAppeared() override
2265 {
2266 _scheduler.Schedule(2s, [this](TaskContext /*task*/)
2267 {
2268 DoCastSelf(SPELL_CONSUMPTION);
2269 });
2270 }
2271
2272 void UpdateAI(uint32 diff) override
2273 {
2274 _scheduler.Update(diff);
2275 }
2276
2277private:
2279};
2280
@ IN_MILLISECONDS
Definition Common.h:35
#define sCreatureTextMgr
@ TEXT_RANGE_NORMAL
uint8_t uint8
Definition Define.h:135
int8_t int8
Definition Define.h:131
int32_t int32
Definition Define.h:129
uint64_t uint64
Definition Define.h:132
uint32_t uint32
Definition Define.h:133
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:27
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
#define ASSERT_NODEBUGINFO
Definition Errors.h:69
bool IsHolidayActive(HolidayIds id)
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
@ MOTION_PRIORITY_HIGHEST
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
std::list< ObjectGuid > GuidList
Definition ObjectGuid.h:261
@ TYPEID_UNIT
Definition ObjectGuid.h:38
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
std::vector< ObjectGuid > GuidVector
Definition ObjectGuid.h:262
#define sObjectMgr
Definition ObjectMgr.h:1721
#define PET_FOLLOW_ANGLE
Definition PetDefines.h:86
#define PET_FOLLOW_DIST
Definition PetDefines.h:85
@ PLAYER_FLAGS_NO_XP_GAIN
Definition Player.h:369
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:107
@ QUEST_STATUS_NONE
Definition QuestDef.h:104
@ QUEST_STATUS_COMPLETE
Definition QuestDef.h:105
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
if(posix_memalign(&__mallocedMemory, __align, __size)) return NULL
#define RegisterCreatureAI(ai_name)
Definition ScriptMgr.h:1139
void GetCreatureListWithEntryInGrid(Container &container, WorldObject *source, uint32 entry, float maxSearchRange)
void SendGossipMenuFor(Player *player, uint32 npcTextID, ObjectGuid const &guid)
void AddGossipItemFor(Player *player, GossipOptionIcon icon, std::string const &text, uint32 sender, uint32 action)
void ClearGossipMenuFor(Player *player)
void InitGossipMenuFor(Player *player, uint32 menuId)
void CloseGossipMenuFor(Player *player)
@ GOSSIP_SENDER_MAIN
@ GOSSIP_ACTION_INFO_DEF
@ LANG_ADDON
@ 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
@ CLASS_DEATH_KNIGHT
@ HORDE
@ CHAT_MSG_MONSTER_WHISPER
@ CHAT_MSG_MONSTER_PARTY
@ FACTION_FRIENDLY
@ FACTION_PREY
@ HOLIDAY_BREWFEST
#define ENSURE_AI(a, b)
Definition UnitAI.h:28
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
@ UNIT_STAND_STATE_DEAD
Definition UnitDefines.h:41
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:34
@ UNIT_NPC_FLAG_BANKER
@ UNIT_NPC_FLAG_VENDOR
@ UNIT_NPC_FLAG_QUESTGIVER
@ UNIT_NPC_FLAG_MAILBOX
@ UNIT_FLAG_NON_ATTACKABLE
@ UNIT_FLAG_IN_COMBAT
@ UNIT_FLAG_UNINTERACTIBLE
@ JUST_DIED
Definition Unit.h:212
DamageEffectType
Definition Unit.h:352
@ DOT
Definition Unit.h:355
@ PLAYER_FLAGS
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:554
@ SAY_RANDOM
@ EVENT_EMOTE
Definition boss_laj.cpp:48
@ SPELL_CONSUMPTION
WorldObject * GetOwner() const
Definition SpellAuras.h:121
bool Execute(uint64, uint32) override
CastFoodSpell(Unit *owner, uint32 spellId)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
virtual void EnterEvadeMode(EvadeReason why=EVADE_REASON_OTHER)
void setDeathState(DeathState s) override
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:186
void Update(uint32 time)
Definition EventMap.h:67
EventId ExecuteEvent()
Definition EventMap.cpp:73
void ScheduleEvent(EventId eventId, Milliseconds time, GroupIndex group=0u, PhaseIndex phase=0u)
Definition EventMap.cpp:36
void Reset()
Definition EventMap.cpp:21
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={})
bool IsEmpty() const
Definition ObjectGuid.h:172
void Clear()
Definition ObjectGuid.h:150
static Creature * ToCreature(Object *o)
Definition Object.h:186
TypeID GetTypeId() const
Definition Object.h:93
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:760
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:775
virtual void SetDynamicFlag(uint32 flag)
Definition Object.h:89
uint32 GetEntry() const
Definition Object.h:81
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:799
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
static Player * ToPlayer(Object *o)
Definition Object.h:180
void SendCloseGossip()
uint32 GetGossipOptionAction(uint32 selection) const
Definition GossipDef.h:269
uint32 GetTeam() const
Definition Player.h:1832
bool GetQuestRewardStatus(uint32 quest_id) const
Definition Player.cpp:15626
bool HasAchieved(uint32 achievementId) const
Definition Player.cpp:24920
WorldSession * GetSession() const
Definition Player.h:1719
void ResetPetTalents()
Definition Player.cpp:9163
void AreaExploredOrEventHappens(uint32 questId)
Definition Player.cpp:16008
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition Player.cpp:15642
void FailQuest(uint32 quest_id)
Definition Player.cpp:15040
PlayerMenu * PlayerTalkClass
Definition Player.h:1969
uint32 GetQuestId() const
Definition QuestDef.h:229
bool OnGossipSelect(Player *player, uint32 menuId, uint32 gossipListId) override
Definition SmartAI.cpp:772
uint32 Id
Definition SpellInfo.h:289
TaskContext & Repeat(std::chrono::duration< _Rep, _Period > const &duration)
TaskScheduler & CancelAll()
TaskScheduler & Schedule(std::chrono::duration< _Rep, _Period > const &time, task_handler_t const &task)
TaskScheduler & Update(success_t const &callback=EmptyCallback)
WorldObject * GetSummoner() const
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastSelf(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.h:241
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
int32 ModifyHealth(int32 val)
Definition Unit.cpp:8381
uint8 GetClass() const
Definition Unit.h:895
void SetFaction(uint32 faction) override
Definition Unit.h:974
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool IsAlive() const
Definition Unit.h:1234
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:1098
void SetHealth(uint32 val)
Definition Unit.cpp:9361
TempSummon * ToTempSummon()
Definition Unit.h:1794
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4535
void SetEmoteState(Emote emote)
Definition Unit.h:967
uint32 GetHealth() const
Definition Unit.h:913
void SetNpcFlag(NPCFlags flags)
Definition Unit.h:1097
bool SetWalk(bool enable)
Definition Unit.cpp:13268
void EngageWithTarget(Unit *who)
Definition Unit.cpp:8292
bool HasNpcFlag(NPCFlags flags) const
Definition Unit.h:1096
virtual void SetDisplayId(uint32 modelId)
Definition Unit.cpp:10407
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, uint8 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3784
bool IsEngagedBy(Unit const *who) const
Definition Unit.h:1127
void HandleEmoteCommand(Emote emoteId)
Definition Unit.cpp:1568
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13250
uint32 CountPctFromMaxHealth(int32 pct) const
Definition Unit.h:922
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10363
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:954
bool IsFlying() const
Definition Unit.h:1762
Vehicle * GetVehicleKit() const
Definition Unit.h:1735
void RemoveUnitFlag(UnitFlags flags)
Definition Unit.h:955
GameObject * FindNearestGameObject(uint32 entry, float range, bool spawnedOnly=true) const
Definition Object.cpp:2121
bool IsWithinLOS(float x, float y, float z, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags=VMAP::ModelIgnoreFlags::Nothing) const
Definition Object.cpp:1206
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
bool IsValidAttackTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition Object.cpp:2856
bool IsHostileTo(WorldObject const *target) const
Definition Object.cpp:2796
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1992
Unit * GetOwner() const
Definition Object.cpp:2180
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:2099
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:1192
EventProcessor m_Events
Definition Object.h:591
void SendShowMailBox(ObjectGuid guid)
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
CreatureAI * GetAI(Creature *creature) const override
CreatureAI * GetAI(Creature *creature) const override
RibbonPoleData
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:108
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
@ 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]
PetTrainer
@ MENU_ID_PET_UNLEARN
@ OPTION_ID_PLEASE_DO
@ NPC_ARGENT_SQUIRE
TrainWrecker
@ MOVEID_CHASE
@ EVENT_DO_JUMP
@ SPELL_TOY_TRAIN_PULSE
@ 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
@ 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
@ 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[]
BehstenSlahtz
@ OPTION_ID_XP_ON
@ MENU_ID_XP_ON_OFF
@ OPTION_ID_XP_OFF
@ NPC_TEXT_XP_ON_OFF
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
StableMasters
@ SPELL_JUBLING
@ SPELL_WOLPERTINGER
@ SPELL_DARTER
@ SPELL_SMOLDERWEB
@ SPELL_WORG
@ SPELL_MINIWING
@ SPELL_CHIKEN
@ STABLE_MASTER_GOSSIP_SUB_MENU
GuardianSpells
@ SPELL_DEATHTOUCH
@ SEAT_PLATE_HOLDER
AirForceBots type
static void VisitWorldObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:180
float GetPositionZ() const
Definition Position.h:81
float GetAbsoluteAngle(float x, float y) const
Definition Position.h:128
float GetPositionX() const
Definition Position.h:79
void GetPosition(float &x, float &y) const
Definition Position.h:84
float GetPositionY() const
Definition Position.h:80
void Relocate(float x, float y)
Definition Position.h:66
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 OnQuestReward(Player *, Quest const *quest, uint32) override
void ReceiveEmote(Player *player, uint32 emote) override
void OnQuestAccept(Player *, Quest const *quest) 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
bool OnGossipHello(Player *player) override
bool OnGossipSelect(Player *player, uint32, uint32 gossipListId) 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
bool OnGossipSelect(Player *player, uint32 menuId, uint32 gossipListId) override
void UpdateAI(uint32 diff) override
bool OnGossipSelect(Player *player, uint32 menuId, uint32 gossipListId) 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