TrinityCore
bosses_opera.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/* ScriptData
19SDName: Bosses_Opera
20SD%Complete: 90
21SDComment: Oz, Hood, and RAJ event implemented. RAJ event requires more testing.
22SDCategory: Karazhan
23EndScriptData */
24
25#include "ScriptMgr.h"
26#include "InstanceScript.h"
27#include "karazhan.h"
28#include "Log.h"
29#include "MotionMaster.h"
30#include "ObjectAccessor.h"
31#include "Player.h"
32#include "ScriptedCreature.h"
33#include "ScriptedGossip.h"
34#include "SpellInfo.h"
35#include "TemporarySummon.h"
36
37/***********************************/
38/*** OPERA WIZARD OF OZ EVENT *****/
39/*********************************/
40enum Says
41{
46
50
54
59
63};
64
66{
67 // Dorothee
69 SPELL_SCREAM = 31013,
71
72 // Tito
74
75 // Strawman
79
80 // Tinhead
81 SPELL_CLEAVE = 31043,
82 SPELL_RUST = 31086,
83
84 // Roar
85 SPELL_MANGLE = 31041,
86 SPELL_SHRED = 31042,
88
89 // Crone
91
92 // Cyclone
95};
96
98{
102};
103
105{
106 instance->SetData(DATA_OPERA_OZ_DEATHCOUNT, SPECIAL); // Increment DeathCount
107
108 if (instance->GetData(DATA_OPERA_OZ_DEATHCOUNT) == 4)
109 {
110 if (Creature* pCrone = creature->SummonCreature(CREATURE_CRONE, -10891.96f, -1755.95f, creature->GetPositionZ(), 4.64f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 2h))
111 {
112 if (creature->GetVictim())
113 pCrone->AI()->AttackStart(creature->GetVictim());
114 }
115 }
116}
117
119{
120public:
121 boss_dorothee() : CreatureScript("boss_dorothee") { }
122
123 CreatureAI* GetAI(Creature* creature) const override
124 {
125 return GetKarazhanAI<boss_dorotheeAI>(creature);
126 }
127
129 {
130 boss_dorotheeAI(Creature* creature) : ScriptedAI(creature)
131 {
132 Initialize();
133 instance = creature->GetInstanceScript();
134 }
135
137 {
138 AggroTimer = 500;
139
140 WaterBoltTimer = 5000;
141 FearTimer = 15000;
142 SummonTitoTimer = 47500;
143
144 SummonedTito = false;
145 TitoDied = false;
146 }
147
149
151
155
158
159 void Reset() override
160 {
161 Initialize();
162 }
163
164 void JustEngagedWith(Unit* /*who*/) override
165 {
167 }
168
169 void JustReachedHome() override
170 {
172 }
173
174 void SummonTito();
175
176 void JustDied(Unit* /*killer*/) override
177 {
179
181 }
182
183 void AttackStart(Unit* who) override
184 {
186 return;
187
189 }
190
191 void MoveInLineOfSight(Unit* who) override
192
193 {
195 return;
196
198 }
199
200 void UpdateAI(uint32 diff) override
201 {
202 if (AggroTimer)
203 {
204 if (AggroTimer <= diff)
205 {
207 AggroTimer = 0;
208 } else AggroTimer -= diff;
209 }
210
211 if (!UpdateVictim())
212 return;
213
214 if (WaterBoltTimer <= diff)
215 {
217 WaterBoltTimer = TitoDied ? 1500 : 5000;
218 } else WaterBoltTimer -= diff;
219
220 if (FearTimer <= diff)
221 {
223 FearTimer = 30000;
224 } else FearTimer -= diff;
225
226 if (!SummonedTito)
227 {
228 if (SummonTitoTimer <= diff)
229 SummonTito();
230 else SummonTitoTimer -= diff;
231 }
232 }
233 };
234};
235
237{
238public:
239 npc_tito() : CreatureScript("npc_tito") { }
240
241 CreatureAI* GetAI(Creature* creature) const override
242 {
243 return GetKarazhanAI<npc_titoAI>(creature);
244 }
245
246 struct npc_titoAI : public ScriptedAI
247 {
248 npc_titoAI(Creature* creature) : ScriptedAI(creature)
249 {
250 Initialize();
251 }
252
254 {
256 YipTimer = 10000;
257 }
258
261
262 void Reset() override
263 {
264 Initialize();
265 }
266
267 void JustEngagedWith(Unit* /*who*/) override { }
268
269 void JustDied(Unit* /*killer*/) override
270 {
271 if (!DorotheeGUID.IsEmpty())
272 {
274 if (Dorothee && Dorothee->IsAlive())
275 {
276 ENSURE_AI(boss_dorothee::boss_dorotheeAI, Dorothee->AI())->TitoDied = true;
277 Talk(SAY_DOROTHEE_TITO_DEATH, Dorothee);
278 }
279 }
280 }
281
282 void UpdateAI(uint32 diff) override
283 {
284 if (!UpdateVictim())
285 return;
286
287 if (YipTimer <= diff)
288 {
290 YipTimer = 10000;
291 } else YipTimer -= diff;
292 }
293 };
294};
295
297{
298 if (Creature* pTito = me->SummonCreature(CREATURE_TITO, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30s))
299 {
301 ENSURE_AI(npc_tito::npc_titoAI, pTito->AI())->DorotheeGUID = me->GetGUID();
302 pTito->AI()->AttackStart(me->GetVictim());
303 SummonedTito = true;
304 TitoDied = false;
305 }
306}
307
309{
310public:
311 boss_strawman() : CreatureScript("boss_strawman") { }
312
313 CreatureAI* GetAI(Creature* creature) const override
314 {
315 return GetKarazhanAI<boss_strawmanAI>(creature);
316 }
317
319 {
320 boss_strawmanAI(Creature* creature) : ScriptedAI(creature)
321 {
322 Initialize();
323 instance = creature->GetInstanceScript();
324 }
325
327 {
328 AggroTimer = 13000;
329 BrainBashTimer = 5000;
330 BrainWipeTimer = 7000;
331 }
332
334
338
339 void Reset() override
340 {
341 Initialize();
342 }
343
344 void AttackStart(Unit* who) override
345 {
346 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
347 return;
348
350 }
351
352 void MoveInLineOfSight(Unit* who) override
353
354 {
355 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
356 return;
357
359 }
360
361 void JustEngagedWith(Unit* /*who*/) override
362 {
364 }
365
366 void JustReachedHome() override
367 {
368 me->DespawnOrUnsummon();
369 }
370
371 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
372 {
373 if ((spellInfo->SchoolMask == SPELL_SCHOOL_MASK_FIRE) && (!(rand32() % 10)))
374 {
375 /*
376 if (not direct damage(aoe, dot))
377 return;
378 */
379
380 DoCast(me, SPELL_BURNING_STRAW, true);
381 }
382 }
383
384 void JustDied(Unit* /*killer*/) override
385 {
387
388 SummonCroneIfReady(instance, me);
389 }
390
391 void KilledUnit(Unit* /*victim*/) override
392 {
394 }
395
396 void UpdateAI(uint32 diff) override
397 {
398 if (AggroTimer)
399 {
400 if (AggroTimer <= diff)
401 {
402 me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
403 AggroTimer = 0;
404 } else AggroTimer -= diff;
405 }
406
407 if (!UpdateVictim())
408 return;
409
410 if (BrainBashTimer <= diff)
411 {
412 DoCastVictim(SPELL_BRAIN_BASH);
413 BrainBashTimer = 15000;
414 } else BrainBashTimer -= diff;
415
416 if (BrainWipeTimer <= diff)
417 {
418 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
419 DoCast(target, SPELL_BRAIN_WIPE);
420 BrainWipeTimer = 20000;
421 } else BrainWipeTimer -= diff;
422 }
423 };
424};
425
427{
428public:
429 boss_tinhead() : CreatureScript("boss_tinhead") { }
430
431 CreatureAI* GetAI(Creature* creature) const override
432 {
433 return GetKarazhanAI<boss_tinheadAI>(creature);
434 }
435
437 {
438 boss_tinheadAI(Creature* creature) : ScriptedAI(creature)
439 {
440 Initialize();
441 instance = creature->GetInstanceScript();
442 }
443
445 {
446 AggroTimer = 15000;
447 CleaveTimer = 5000;
448 RustTimer = 30000;
449
450 RustCount = 0;
451 }
452
454
458
460
461 void Reset() override
462 {
463 Initialize();
464 }
465
466 void JustEngagedWith(Unit* /*who*/) override
467 {
469 }
470
471 void JustReachedHome() override
472 {
473 me->DespawnOrUnsummon();
474 }
475
476 void AttackStart(Unit* who) override
477 {
478 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
479 return;
480
482 }
483
484 void MoveInLineOfSight(Unit* who) override
485
486 {
487 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
488 return;
489
491 }
492
493 void JustDied(Unit* /*killer*/) override
494 {
496
497 SummonCroneIfReady(instance, me);
498 }
499
500 void KilledUnit(Unit* /*victim*/) override
501 {
503 }
504
505 void UpdateAI(uint32 diff) override
506 {
507 if (AggroTimer)
508 {
509 if (AggroTimer <= diff)
510 {
511 me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
512 AggroTimer = 0;
513 } else AggroTimer -= diff;
514 }
515
516 if (!UpdateVictim())
517 return;
518
519 if (CleaveTimer <= diff)
520 {
521 DoCastVictim(SPELL_CLEAVE);
522 CleaveTimer = 5000;
523 } else CleaveTimer -= diff;
524
525 if (RustCount < 8)
526 {
527 if (RustTimer <= diff)
528 {
529 ++RustCount;
531 DoCast(me, SPELL_RUST);
532 RustTimer = 6000;
533 } else RustTimer -= diff;
534 }
535 }
536 };
537};
538
540{
541public:
542 boss_roar() : CreatureScript("boss_roar") { }
543
544 CreatureAI* GetAI(Creature* creature) const override
545 {
546 return GetKarazhanAI<boss_roarAI>(creature);
547 }
548
549 struct boss_roarAI : public ScriptedAI
550 {
551 boss_roarAI(Creature* creature) : ScriptedAI(creature)
552 {
553 Initialize();
554 instance = creature->GetInstanceScript();
555 }
556
558 {
559 AggroTimer = 20000;
560 MangleTimer = 5000;
561 ShredTimer = 10000;
562 ScreamTimer = 15000;
563 }
564
566
571
572 void Reset() override
573 {
574 Initialize();
575 }
576
577 void MoveInLineOfSight(Unit* who) override
578
579 {
580 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
581 return;
582
584 }
585
586 void AttackStart(Unit* who) override
587 {
588 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
589 return;
590
592 }
593
594 void JustEngagedWith(Unit* /*who*/) override
595 {
597 }
598
599 void JustReachedHome() override
600 {
601 me->DespawnOrUnsummon();
602 }
603
604 void JustDied(Unit* /*killer*/) override
605 {
607
608 SummonCroneIfReady(instance, me);
609 }
610
611 void KilledUnit(Unit* /*victim*/) override
612 {
614 }
615
616 void UpdateAI(uint32 diff) override
617 {
618 if (AggroTimer)
619 {
620 if (AggroTimer <= diff)
621 {
622 me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
623 AggroTimer = 0;
624 } else AggroTimer -= diff;
625 }
626
627 if (!UpdateVictim())
628 return;
629
630 if (MangleTimer <= diff)
631 {
632 DoCastVictim(SPELL_MANGLE);
633 MangleTimer = urand(5000, 8000);
634 } else MangleTimer -= diff;
635
636 if (ShredTimer <= diff)
637 {
638 DoCastVictim(SPELL_SHRED);
639 ShredTimer = urand(10000, 15000);
640 } else ShredTimer -= diff;
641
642 if (ScreamTimer <= diff)
643 {
644 DoCastVictim(SPELL_FRIGHTENED_SCREAM);
645 ScreamTimer = urand(20000, 30000);
646 } else ScreamTimer -= diff;
647 }
648 };
649};
650
652{
653public:
654 boss_crone() : CreatureScript("boss_crone") { }
655
656 CreatureAI* GetAI(Creature* creature) const override
657 {
658 return GetKarazhanAI<boss_croneAI>(creature);
659 }
660
661 struct boss_croneAI : public ScriptedAI
662 {
663 boss_croneAI(Creature* creature) : ScriptedAI(creature)
664 {
665 Initialize();
666 instance = creature->GetInstanceScript();
667 }
668
670 {
671 // Hello, developer from the future! It's me again!
672 // This time, you're fixing Karazhan scripts. Awesome. These are a mess of hacks. An amalgamation of hacks, so to speak. Maybe even a Patchwerk thereof.
673 // Anyway, I digress.
674 // @todo This line below is obviously a hack. Duh. I'm just coming in here to hackfix the encounter to actually be completable.
675 // It needs a rewrite. Badly. Please, take good care of it.
676 me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
677 me->SetImmuneToPC(false);
678 CycloneTimer = 30000;
679 ChainLightningTimer = 10000;
680 }
681
683
686
687 void Reset() override
688 {
689 Initialize();
690 }
691
692 void JustReachedHome() override
693 {
694 me->DespawnOrUnsummon();
695 }
696
697 void KilledUnit(Unit* /*victim*/) override
698 {
700 }
701
702 void JustEngagedWith(Unit* /*who*/) override
703 {
705 }
706
707 void JustDied(Unit* /*killer*/) override
708 {
711 }
712
713 void UpdateAI(uint32 diff) override
714 {
715 if (!UpdateVictim())
716 return;
717
718 if (CycloneTimer <= diff)
719 {
720 if (Creature* Cyclone = DoSpawnCreature(CREATURE_CYCLONE, float(urand(0, 9)), float(urand(0, 9)), 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15s))
721 Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_VISUAL, true);
722 CycloneTimer = 30000;
723 } else CycloneTimer -= diff;
724
725 if (ChainLightningTimer <= diff)
726 {
727 DoCastVictim(SPELL_CHAIN_LIGHTNING);
728 ChainLightningTimer = 15000;
729 } else ChainLightningTimer -= diff;
730 }
731 };
732};
733
735{
736public:
737 npc_cyclone() : CreatureScript("npc_cyclone") { }
738
739 CreatureAI* GetAI(Creature* creature) const override
740 {
741 return GetKarazhanAI<npc_cycloneAI>(creature);
742 }
743
744 struct npc_cycloneAI : public ScriptedAI
745 {
746 npc_cycloneAI(Creature* creature) : ScriptedAI(creature)
747 {
748 Initialize();
749 }
750
752 {
753 MoveTimer = 1000;
754 }
755
757
758 void Reset() override
759 {
760 Initialize();
761 }
762
763 void JustEngagedWith(Unit* /*who*/) override { }
764
765 void MoveInLineOfSight(Unit* /*who*/) override
766
767 {
768 }
769
770 void UpdateAI(uint32 diff) override
771 {
772 if (!me->HasAura(SPELL_KNOCKBACK))
773 DoCast(me, SPELL_KNOCKBACK, true);
774
775 if (MoveTimer <= diff)
776 {
777 Position pos = me->GetRandomNearPosition(10);
778 me->GetMotionMaster()->MovePoint(0, pos);
779 MoveTimer = urand(5000, 8000);
780 } else MoveTimer -= diff;
781 }
782 };
783};
784
785/**************************************/
786/**** Opera Red Riding Hood Event* ***/
787/************************************/
789{
795
799
802
804{
805 public:
806 npc_grandmother() : CreatureScript("npc_grandmother") { }
807
809 {
810 npc_grandmotherAI(Creature* creature) : ScriptedAI(creature) { }
811
812 bool OnGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
813 {
814 if (menuId == OPTION_WHAT_PHAT_LEWTS_YOU_HAVE && gossipListId == 0)
815 {
816 CloseGossipMenuFor(player);
817
818 if (Creature* pBigBadWolf = me->SummonCreature(CREATURE_BIG_BAD_WOLF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 2h))
819 pBigBadWolf->AI()->AttackStart(player);
820
821 me->DespawnOrUnsummon();
822 }
823 return false;
824 }
825 };
826
827 CreatureAI* GetAI(Creature* creature) const override
828 {
829 return GetKarazhanAI<npc_grandmotherAI>(creature);
830 }
831};
832
834{
835public:
836 boss_bigbadwolf() : CreatureScript("boss_bigbadwolf") { }
837
838 CreatureAI* GetAI(Creature* creature) const override
839 {
840 return GetKarazhanAI<boss_bigbadwolfAI>(creature);
841 }
842
844 {
845 boss_bigbadwolfAI(Creature* creature) : ScriptedAI(creature)
846 {
847 Initialize();
848 instance = creature->GetInstanceScript();
849 }
850
852 {
853 ChaseTimer = 30000;
854 FearTimer = urand(25000, 35000);
855 SwipeTimer = 5000;
856
857 HoodGUID.Clear();
858 TempThreat = 0;
859
860 IsChasing = false;
861 }
862
864
868
871
873
874 void Reset() override
875 {
876 Initialize();
877 }
878
879 void JustEngagedWith(Unit* /*who*/) override
880 {
882 }
883
884 void KilledUnit(Unit* /*victim*/) override
885 {
887 }
888
889 void JustReachedHome() override
890 {
891 me->DespawnOrUnsummon();
892 }
893
894 void JustDied(Unit* /*killer*/) override
895 {
896 DoPlaySoundToSet(me, SOUND_WOLF_DEATH);
898 }
899
900 void UpdateAI(uint32 diff) override
901 {
902 if (!UpdateVictim())
903 return;
904
905 if (ChaseTimer <= diff)
906 {
907 if (!IsChasing)
908 {
909 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
910 {
912 DoCast(target, SPELL_LITTLE_RED_RIDING_HOOD, true);
913 TempThreat = GetThreat(target);
914 if (TempThreat)
915 ModifyThreatByPercent(target, -100);
916 HoodGUID = target->GetGUID();
917 AddThreat(target, 1000000.0f);
918 ChaseTimer = 20000;
919 IsChasing = true;
920 }
921 }
922 else
923 {
924 IsChasing = false;
925
926 if (Unit* target = ObjectAccessor::GetUnit(*me, HoodGUID))
927 {
928 HoodGUID.Clear();
929 if (GetThreat(target))
930 ModifyThreatByPercent(target, -100);
931 AddThreat(target, TempThreat);
932 TempThreat = 0;
933 }
934
935 ChaseTimer = 40000;
936 }
937 } else ChaseTimer -= diff;
938
939 if (IsChasing)
940 return;
941
942 if (FearTimer <= diff)
943 {
944 DoCastVictim(SPELL_TERRIFYING_HOWL);
945 FearTimer = urand(25000, 35000);
946 } else FearTimer -= diff;
947
948 if (SwipeTimer <= diff)
949 {
950 DoCastVictim(SPELL_WIDE_SWIPE);
951 SwipeTimer = urand(25000, 30000);
952 } else SwipeTimer -= diff;
953 }
954 };
955};
956
957/**********************************************/
958/******** Opera Romeo and Juliet Event* ******/
959/********************************************/
960
962{
963 /**** Speech *****/
970
976
982
987
990
992 ROMULO_X = -10900,
993 ROMULO_Y = -1758,
994};
995
997{
1001};
1002
1003void PretendToDie(Creature* creature)
1004{
1005 creature->InterruptNonMeleeSpells(true);
1006 creature->RemoveAllAuras();
1007 creature->SetHealth(0);
1008 creature->SetUninteractible(true);
1009 creature->GetMotionMaster()->Clear();
1010 creature->GetMotionMaster()->MoveIdle();
1012}
1013
1014void Resurrect(Creature* target)
1015{
1016 target->SetUninteractible(false);
1017 target->SetFullHealth();
1019 target->CastSpell(target, SPELL_RES_VISUAL, true);
1020 if (target->GetVictim())
1021 {
1022 target->GetMotionMaster()->MoveChase(target->GetVictim());
1023 target->AI()->AttackStart(target->GetVictim());
1024 }
1025 else
1026 target->GetMotionMaster()->Initialize();
1027}
1028
1030{
1031public:
1032 boss_julianne() : CreatureScript("boss_julianne") { }
1033
1034 CreatureAI* GetAI(Creature* creature) const override
1035 {
1036 return GetKarazhanAI<boss_julianneAI>(creature);
1037 }
1038
1040 {
1041 boss_julianneAI(Creature* creature) : ScriptedAI(creature)
1042 {
1043 Initialize();
1044 instance = creature->GetInstanceScript();
1045 EntryYellTimer = 1000;
1046 AggroYellTimer = 10000;
1047 IsFakingDeath = false;
1048 ResurrectTimer = 0;
1049 }
1050
1052 {
1053 RomuloGUID.Clear();
1055
1056 BlindingPassionTimer = 30000;
1057 DevotionTimer = 15000;
1058 EternalAffectionTimer = 25000;
1059 PowerfulAttractionTimer = 5000;
1060 SummonRomuloTimer = 10000;
1061 DrinkPoisonTimer = 0;
1062 ResurrectSelfTimer = 0;
1063
1064 SummonedRomulo = false;
1065 RomuloDead = false;
1066 }
1067
1069
1072
1074
1076
1085
1089
1090 void Reset() override
1091 {
1092 Initialize();
1093 if (IsFakingDeath)
1094 {
1095 Resurrect(me);
1096 IsFakingDeath = false;
1097 }
1098 }
1099
1100 void JustEngagedWith(Unit* /*who*/) override { }
1101
1102 void AttackStart(Unit* who) override
1103 {
1104 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
1105 return;
1106
1108 }
1109
1110 void MoveInLineOfSight(Unit* who) override
1111
1112 {
1113 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
1114 return;
1115
1117 }
1118
1119 void JustReachedHome() override
1120 {
1121 me->DespawnOrUnsummon();
1122 }
1123
1124 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
1125 {
1126 if (spellInfo->Id == SPELL_DRINK_POISON)
1127 {
1129 DrinkPoisonTimer = 2500;
1130 }
1131 }
1132
1133 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override;
1134
1135 void JustDied(Unit* /*killer*/) override
1136 {
1139 }
1140
1141 void KilledUnit(Unit* /*victim*/) override
1142 {
1144 }
1145
1146 void UpdateAI(uint32 diff) override;
1147 };
1148};
1149
1151{
1152public:
1153 boss_romulo() : CreatureScript("boss_romulo") { }
1154
1155 CreatureAI* GetAI(Creature* creature) const override
1156 {
1157 return GetKarazhanAI<boss_romuloAI>(creature);
1158 }
1159
1161 {
1162 boss_romuloAI(Creature* creature) : ScriptedAI(creature)
1163 {
1164 Initialize();
1165 instance = creature->GetInstanceScript();
1166 EntryYellTimer = 8000;
1167 AggroYellTimer = 15000;
1168 }
1169
1171 {
1172 JulianneGUID.Clear();
1174
1175 BackwardLungeTimer = 15000;
1176 DaringTimer = 20000;
1177 DeadlySwatheTimer = 25000;
1178 PoisonThrustTimer = 10000;
1179 ResurrectTimer = 10000;
1180
1181 IsFakingDeath = false;
1182 JulianneDead = false;
1183 }
1184
1186
1189
1197
1200
1201 void Reset() override
1202 {
1203 Initialize();
1204 }
1205
1206 void JustReachedHome() override
1207 {
1208 me->DespawnOrUnsummon();
1209 }
1210
1211 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1212 {
1213 if (damage < me->GetHealth())
1214 return;
1215
1216 //anything below only used if incoming damage will kill
1217
1218 if (Phase == PHASE_ROMULO)
1219 {
1221 PretendToDie(me);
1222 IsFakingDeath = true;
1223 Phase = PHASE_BOTH;
1224
1225 if (Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID)))
1226 {
1227 ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->RomuloDead = true;
1228 ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->ResurrectSelfTimer = 10000;
1229 }
1230
1231 damage = 0;
1232 return;
1233 }
1234
1235 if (Phase == PHASE_BOTH)
1236 {
1237 if (JulianneDead)
1238 {
1239 if (Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID)))
1240 {
1241 Julianne->SetUninteractible(false);
1242 Julianne->GetMotionMaster()->Clear();
1243 Julianne->setDeathState(JUST_DIED);
1244 Julianne->CombatStop(true);
1245 Julianne->ReplaceAllDynamicFlags(UNIT_DYNFLAG_LOOTABLE);
1246 }
1247 return;
1248 }
1249
1250 if (Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID)))
1251 {
1252 PretendToDie(me);
1253 IsFakingDeath = true;
1254 ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->ResurrectTimer = 10000;
1255 ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->RomuloDead = true;
1256 damage = 0;
1257 return;
1258 }
1259 }
1260
1261 TC_LOG_ERROR("scripts", "boss_romuloAI: DamageTaken reach end of code, that should not happen.");
1262 }
1263
1264 void JustEngagedWith(Unit* /*who*/) override
1265 {
1267 if (!JulianneGUID.IsEmpty())
1268 {
1269 Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID));
1270 if (Julianne && Julianne->GetVictim())
1271 {
1272 AddThreat(Julianne->GetVictim(), 1.0f);
1273 AttackStart(Julianne->GetVictim());
1274 }
1275 }
1276 }
1277
1278 void MoveInLineOfSight(Unit* who) override
1279
1280 {
1281 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
1282 return;
1283
1285 }
1286
1287 void JustDied(Unit* /*killer*/) override
1288 {
1291 }
1292
1293 void KilledUnit(Unit* /*victim*/) override
1294 {
1296 }
1297
1298 void UpdateAI(uint32 diff) override
1299 {
1300 if (!UpdateVictim() || IsFakingDeath)
1301 return;
1302
1303 if (JulianneDead)
1304 {
1305 if (ResurrectTimer <= diff)
1306 {
1307 Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID));
1308 if (Julianne && ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->IsFakingDeath)
1309 {
1311 Resurrect(Julianne);
1312 ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->IsFakingDeath = false;
1313 JulianneDead = false;
1314 ResurrectTimer = 10000;
1315 }
1316 } else ResurrectTimer -= diff;
1317 }
1318
1319 if (BackwardLungeTimer <= diff)
1320 {
1321 Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100, true);
1322 if (target && !me->HasInArc(float(M_PI), target))
1323 {
1324 DoCast(target, SPELL_BACKWARD_LUNGE);
1325 BackwardLungeTimer = urand(15000, 30000);
1326 }
1327 } else BackwardLungeTimer -= diff;
1328
1329 if (DaringTimer <= diff)
1330 {
1331 DoCast(me, SPELL_DARING);
1332 DaringTimer = urand(20000, 40000);
1333 } else DaringTimer -= diff;
1334
1335 if (DeadlySwatheTimer <= diff)
1336 {
1337 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
1338 DoCast(target, SPELL_DEADLY_SWATHE);
1339 DeadlySwatheTimer = urand(15000, 25000);
1340 } else DeadlySwatheTimer -= diff;
1341
1342 if (PoisonThrustTimer <= diff)
1343 {
1344 DoCastVictim(SPELL_POISON_THRUST);
1345 PoisonThrustTimer = urand(10000, 20000);
1346 } else PoisonThrustTimer -= diff;
1347 }
1348 };
1349};
1350
1352{
1353 if (EntryYellTimer)
1354 {
1355 if (EntryYellTimer <= diff)
1356 {
1358 EntryYellTimer = 0;
1359 } else EntryYellTimer -= diff;
1360 }
1361
1362 if (AggroYellTimer)
1363 {
1364 if (AggroYellTimer <= diff)
1365 {
1367 me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
1368 me->SetFaction(FACTION_MONSTER_2);
1369 AggroYellTimer = 0;
1370 } else AggroYellTimer -= diff;
1371 }
1372
1373 if (DrinkPoisonTimer)
1374 {
1375 //will do this 2secs after spell hit. this is time to display visual as expected
1376 if (DrinkPoisonTimer <= diff)
1377 {
1378 PretendToDie(me);
1380 SummonRomuloTimer = 10000;
1381 DrinkPoisonTimer = 0;
1382 } else DrinkPoisonTimer -= diff;
1383 }
1384
1385 if (Phase == PHASE_ROMULO && !SummonedRomulo)
1386 {
1387 if (SummonRomuloTimer <= diff)
1388 {
1389 if (Creature* pRomulo = me->SummonCreature(CREATURE_ROMULO, ROMULO_X, ROMULO_Y, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 2h))
1390 {
1391 RomuloGUID = pRomulo->GetGUID();
1392 ENSURE_AI(boss_romulo::boss_romuloAI, pRomulo->AI())->JulianneGUID = me->GetGUID();
1393 ENSURE_AI(boss_romulo::boss_romuloAI, pRomulo->AI())->Phase = PHASE_ROMULO;
1394 DoZoneInCombat(pRomulo);
1395
1396 pRomulo->SetFaction(FACTION_MONSTER_2);
1397 }
1398 SummonedRomulo = true;
1399 } else SummonRomuloTimer -= diff;
1400 }
1401
1402 if (ResurrectSelfTimer)
1403 {
1404 if (ResurrectSelfTimer <= diff)
1405 {
1406 Resurrect(me);
1407 Phase = PHASE_BOTH;
1408 IsFakingDeath = false;
1409
1410 if (me->GetVictim())
1411 AttackStart(me->GetVictim());
1412
1413 ResurrectSelfTimer = 0;
1414 ResurrectTimer = 1000;
1415 } else ResurrectSelfTimer -= diff;
1416 }
1417
1418 if (!UpdateVictim() || IsFakingDeath)
1419 return;
1420
1421 if (RomuloDead)
1422 {
1423 if (ResurrectTimer <= diff)
1424 {
1425 Creature* Romulo = (ObjectAccessor::GetCreature((*me), RomuloGUID));
1426 if (Romulo && ENSURE_AI(boss_romulo::boss_romuloAI, Romulo->AI())->IsFakingDeath)
1427 {
1429 Resurrect(Romulo);
1430 ENSURE_AI(boss_romulo::boss_romuloAI, Romulo->AI())->IsFakingDeath = false;
1431 RomuloDead = false;
1432 ResurrectTimer = 10000;
1433 }
1434 } else ResurrectTimer -= diff;
1435 }
1436
1437 if (BlindingPassionTimer <= diff)
1438 {
1439 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
1440 DoCast(target, SPELL_BLINDING_PASSION);
1441 BlindingPassionTimer = urand(30000, 45000);
1442 } else BlindingPassionTimer -= diff;
1443
1444 if (DevotionTimer <= diff)
1445 {
1446 DoCast(me, SPELL_DEVOTION);
1447 DevotionTimer = urand(15000, 45000);
1448 } else DevotionTimer -= diff;
1449
1450 if (PowerfulAttractionTimer <= diff)
1451 {
1452 DoCast(SelectTarget(SelectTargetMethod::Random, 0), SPELL_POWERFUL_ATTRACTION);
1453 PowerfulAttractionTimer = urand(5000, 30000);
1454 } else PowerfulAttractionTimer -= diff;
1455
1456 if (EternalAffectionTimer <= diff)
1457 {
1458 if (urand(0, 1) && SummonedRomulo)
1459 {
1460 Creature* Romulo = (ObjectAccessor::GetCreature((*me), RomuloGUID));
1461 if (Romulo && Romulo->IsAlive() && !RomuloDead)
1462 DoCast(Romulo, SPELL_ETERNAL_AFFECTION);
1463 } else DoCast(me, SPELL_ETERNAL_AFFECTION);
1464
1465 EternalAffectionTimer = urand(45000, 60000);
1466 } else EternalAffectionTimer -= diff;
1467}
1468
1469void boss_julianne::boss_julianneAI::DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/)
1470{
1471 if (damage < me->GetHealth())
1472 return;
1473
1474 //anything below only used if incoming damage will kill
1475
1476 if (Phase == PHASE_JULIANNE)
1477 {
1478 damage = 0;
1479
1480 //this means already drinking, so return
1481 if (IsFakingDeath)
1482 return;
1483
1484 me->InterruptNonMeleeSpells(true);
1485 DoCast(me, SPELL_DRINK_POISON);
1486
1487 IsFakingDeath = true;
1488 //IS THIS USEFULL? Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID));
1489 return;
1490 }
1491
1492 if (Phase == PHASE_ROMULO)
1493 {
1494 TC_LOG_ERROR("scripts", "boss_julianneAI: cannot take damage in PHASE_ROMULO, why was i here?");
1495 damage = 0;
1496 return;
1497 }
1498
1499 if (Phase == PHASE_BOTH)
1500 {
1501 //if this is true then we have to kill romulo too
1502 if (RomuloDead)
1503 {
1504 if (Creature* Romulo = (ObjectAccessor::GetCreature((*me), RomuloGUID)))
1505 {
1506 Romulo->SetUninteractible(false);
1507 Romulo->GetMotionMaster()->Clear();
1508 Romulo->setDeathState(JUST_DIED);
1509 Romulo->CombatStop(true);
1510 Romulo->ReplaceAllDynamicFlags(UNIT_DYNFLAG_LOOTABLE);
1511 }
1512
1513 return;
1514 }
1515
1516 //if not already returned, then romulo is alive and we can pretend die
1517 if (Creature* Romulo = (ObjectAccessor::GetCreature((*me), RomuloGUID)))
1518 {
1519 PretendToDie(me);
1520 IsFakingDeath = true;
1521 ENSURE_AI(boss_romulo::boss_romuloAI, Romulo->AI())->ResurrectTimer = 10000;
1522 ENSURE_AI(boss_romulo::boss_romuloAI, Romulo->AI())->JulianneDead = true;
1523 damage = 0;
1524 return;
1525 }
1526 }
1527 TC_LOG_ERROR("scripts", "boss_julianneAI: DamageTaken reach end of code, that should not happen.");
1528}
1529
1531{
1532 new boss_dorothee();
1533 new boss_strawman();
1534 new boss_tinhead();
1535 new boss_roar();
1536 new boss_crone();
1537 new npc_tito();
1538 new npc_cyclone();
1539 new npc_grandmother();
1540 new boss_bigbadwolf();
1541 new boss_julianne();
1542 new boss_romulo();
1543}
#define M_PI
Definition: Common.h:115
uint8_t uint8
Definition: Define.h:144
uint32_t uint32
Definition: Define.h:142
@ DONE
@ SPECIAL
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
@ TEMPSUMMON_TIMED_DESPAWN
Definition: ObjectDefines.h:65
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
Definition: ObjectDefines.h:66
@ TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
Definition: ObjectDefines.h:63
Spells
Definition: PlayerAI.cpp:32
uint32 urand(uint32 min, uint32 max)
Definition: Random.cpp:42
uint32 rand32()
Definition: Random.cpp:70
void CloseGossipMenuFor(Player *player)
@ SPELL_SCHOOL_MASK_FIRE
@ UNIT_DYNFLAG_LOOTABLE
@ FACTION_MONSTER_2
#define ENSURE_AI(a, b)
Definition: UnitAI.h:29
@ UNIT_STAND_STATE_DEAD
Definition: UnitDefines.h:49
@ UNIT_STAND_STATE_STAND
Definition: UnitDefines.h:42
DamageEffectType
Definition: UnitDefines.h:131
@ UNIT_FLAG_NON_ATTACKABLE
Definition: UnitDefines.h:145
@ JUST_DIED
Definition: Unit.h:247
Says
@ SAY_ROAR_DEATH
@ SAY_ROAR_AGGRO
@ SAY_DOROTHEE_TITO_DEATH
@ SAY_DOROTHEE_DEATH
@ SAY_STRAWMAN_DEATH
@ SAY_CRONE_SLAY
@ SAY_CRONE_DEATH
@ SAY_DOROTHEE_AGGRO
@ SAY_STRAWMAN_SLAY
@ SAY_TINHEAD_DEATH
@ SAY_TINHEAD_SLAY
@ SAY_TINHEAD_AGGRO
@ SAY_CRONE_AGGRO
@ EMOTE_RUST
@ SAY_DOROTHEE_SUMMON
@ SAY_STRAWMAN_AGGRO
@ SAY_ROAR_SLAY
@ CREATURE_TITO
@ CREATURE_CRONE
@ CREATURE_CYCLONE
JulianneRomulo
@ SAY_ROMULO_DEATH
@ SAY_ROMULO_AGGRO
@ SAY_ROMULO_SLAY
@ CREATURE_ROMULO
@ SAY_JULIANNE_DEATH02
@ SPELL_ETERNAL_AFFECTION
@ SPELL_UNDYING_LOVE
@ SPELL_DRINK_POISON
@ ROMULO_Y
@ SAY_JULIANNE_ENTER
@ SPELL_BLINDING_PASSION
@ SAY_JULIANNE_RESURRECT
@ SPELL_POWERFUL_ATTRACTION
@ SAY_JULIANNE_AGGRO
@ SAY_ROMULO_RESURRECT
@ ROMULO_X
@ SPELL_DEADLY_SWATHE
@ SPELL_DEVOTION
@ SAY_ROMULO_ENTER
@ SPELL_POISON_THRUST
@ SAY_JULIANNE_DEATH01
@ SPELL_BACKWARD_LUNGE
@ SPELL_DARING
@ SAY_JULIANNE_SLAY
@ SPELL_RES_VISUAL
RAJPhase
@ PHASE_BOTH
@ PHASE_JULIANNE
@ PHASE_ROMULO
@ SPELL_CLEAVE
@ SPELL_CYCLONE_VISUAL
@ SPELL_WATERBOLT
@ SPELL_SUMMONTITO
@ SPELL_KNOCKBACK
@ SPELL_MANGLE
@ SPELL_BRAIN_WIPE
@ SPELL_SCREAM
@ SPELL_SHRED
@ SPELL_RUST
@ SPELL_FRIGHTENED_SCREAM
@ SPELL_CHAIN_LIGHTNING
@ SPELL_BURNING_STRAW
@ SPELL_YIPPING
@ SPELL_BRAIN_BASH
RedRidingHood
@ SAY_WOLF_HOOD
@ CREATURE_BIG_BAD_WOLF
@ OPTION_WHAT_PHAT_LEWTS_YOU_HAVE
@ SPELL_WIDE_SWIPE
@ SAY_WOLF_SLAY
@ SAY_WOLF_AGGRO
@ SPELL_LITTLE_RED_RIDING_HOOD
@ SOUND_WOLF_DEATH
@ SPELL_TERRIFYING_HOWL
void AddSC_bosses_opera()
void Resurrect(Creature *target)
void PretendToDie(Creature *creature)
void SummonCroneIfReady(InstanceScript *instance, Creature *creature)
virtual void MoveInLineOfSight(Unit *)
Definition: CreatureAI.cpp:122
void Talk(uint8 id, WorldObject const *whisperTarget=nullptr)
Definition: CreatureAI.cpp:56
bool UpdateVictim()
Definition: CreatureAI.cpp:245
void AttackStart(Unit *victim) override
== Triggered Actions Requested ==================
Definition: CreatureAI.cpp:328
Creature *const me
Definition: CreatureAI.h:61
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
Definition: Creature.cpp:2415
CreatureAI * AI() const
Definition: Creature.h:214
virtual bool SetBossState(uint32 id, EncounterState state)
void Initialize()
void MoveChase(Unit *target, Optional< ChaseRange > dist={}, Optional< ChaseAngle > angle={})
bool IsEmpty() const
Definition: ObjectGuid.h:319
void Clear()
Definition: ObjectGuid.h:286
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
uint32 const Id
Definition: SpellInfo.h:325
uint32 SchoolMask
Definition: SpellInfo.h:413
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition: UnitAI.cpp:180
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition: UnitAI.cpp:79
SpellCastResult DoCast(uint32 spellId)
Definition: UnitAI.cpp:89
Definition: Unit.h:627
void SetHealth(uint64 val)
Definition: Unit.cpp:9346
void SetFullHealth()
Definition: Unit.h:790
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition: Unit.cpp:10100
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition: Unit.cpp:3089
MotionMaster * GetMotionMaster()
Definition: Unit.h:1652
bool HasUnitFlag(UnitFlags flags) const
Definition: Unit.h:832
bool IsAlive() const
Definition: Unit.h:1164
void SetUninteractible(bool apply)
Definition: Unit.cpp:8147
Unit * GetVictim() const
Definition: Unit.h:715
void RemoveAllAuras()
Definition: Unit.cpp:4242
void RemoveUnitFlag(UnitFlags flags)
Definition: Unit.h:834
InstanceScript * GetInstanceScript() const
Definition: Object.cpp:1042
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition: Object.cpp:2896
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition: Object.cpp:2025
virtual uint32 GetData(uint32) const
Definition: ZoneScript.h:91
virtual void SetData(uint32, uint32)
Definition: ZoneScript.h:92
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
@ DATA_OPERA_OZ_DEATHCOUNT
Definition: karazhan.h:43
@ DATA_OPERA_PERFORMANCE
Definition: karazhan.h:34
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
bool HasInArc(float arcangle, Position const *pos, float border=2.0f) const
Definition: Position.cpp:99
constexpr float GetPositionZ() const
Definition: Position.h:78
void AttackStart(Unit *) override
== Triggered Actions Requested ==================
void UpdateAI(uint32 diff) override
void KilledUnit(Unit *) override
void JustEngagedWith(Unit *) override
boss_bigbadwolfAI(Creature *creature)
boss_croneAI(Creature *creature)
void UpdateAI(uint32 diff) override
InstanceScript * instance
void KilledUnit(Unit *) override
void JustDied(Unit *) override
void JustReachedHome() override
void JustEngagedWith(Unit *) override
boss_dorotheeAI(Creature *creature)
void AttackStart(Unit *who) override
== Triggered Actions Requested ==================
void MoveInLineOfSight(Unit *who) override
void JustDied(Unit *) override
void JustEngagedWith(Unit *) override
void UpdateAI(uint32 diff) override
void AttackStart(Unit *who) override
== Triggered Actions Requested ==================
void KilledUnit(Unit *) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void JustDied(Unit *) override
void MoveInLineOfSight(Unit *who) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
boss_julianneAI(Creature *creature)
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *) override
void JustDied(Unit *) override
void MoveInLineOfSight(Unit *who) override
void JustEngagedWith(Unit *) override
void Reset() override
InstanceScript * instance
void JustReachedHome() override
boss_roarAI(Creature *creature)
void UpdateAI(uint32 diff) override
void KilledUnit(Unit *) override
void AttackStart(Unit *who) override
== Triggered Actions Requested ==================
void JustDied(Unit *) override
void KilledUnit(Unit *) override
void JustEngagedWith(Unit *) override
void DamageTaken(Unit *, uint32 &damage, DamageEffectType, SpellInfo const *) override
boss_romuloAI(Creature *creature)
void UpdateAI(uint32 diff) override
void MoveInLineOfSight(Unit *who) override
void JustReachedHome() override
void JustDied(Unit *) override
void SpellHit(WorldObject *, SpellInfo const *spellInfo) override
void JustEngagedWith(Unit *) override
boss_strawmanAI(Creature *creature)
void UpdateAI(uint32 diff) override
void KilledUnit(Unit *) override
void AttackStart(Unit *who) override
== Triggered Actions Requested ==================
void MoveInLineOfSight(Unit *who) override
void MoveInLineOfSight(Unit *who) override
void AttackStart(Unit *who) override
== Triggered Actions Requested ==================
void KilledUnit(Unit *) override
void JustDied(Unit *) override
boss_tinheadAI(Creature *creature)
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *) override
void JustEngagedWith(Unit *) override
void MoveInLineOfSight(Unit *) override
void UpdateAI(uint32 diff) override
npc_cycloneAI(Creature *creature)
npc_grandmotherAI(Creature *creature)
bool OnGossipSelect(Player *player, uint32 menuId, uint32 gossipListId) override
void JustDied(Unit *) override
void JustEngagedWith(Unit *) override
void Reset() override
npc_titoAI(Creature *creature)
void UpdateAI(uint32 diff) override