TrinityCore
Loading...
Searching...
No Matches
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/*********************************/
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
234 }
235 };
236};
237
239{
240public:
241 npc_tito() : CreatureScript("npc_tito") { }
242
243 CreatureAI* GetAI(Creature* creature) const override
244 {
245 return GetKarazhanAI<npc_titoAI>(creature);
246 }
247
248 struct npc_titoAI : public ScriptedAI
249 {
250 npc_titoAI(Creature* creature) : ScriptedAI(creature)
251 {
252 Initialize();
253 }
254
256 {
258 YipTimer = 10000;
259 }
260
263
264 void Reset() override
265 {
266 Initialize();
267 }
268
269 void JustEngagedWith(Unit* /*who*/) override { }
270
271 void JustDied(Unit* /*killer*/) override
272 {
273 if (!DorotheeGUID.IsEmpty())
274 {
276 if (Dorothee && Dorothee->IsAlive())
277 {
278 ENSURE_AI(boss_dorothee::boss_dorotheeAI, Dorothee->AI())->TitoDied = true;
279 Talk(SAY_DOROTHEE_TITO_DEATH, Dorothee);
280 }
281 }
282 }
283
284 void UpdateAI(uint32 diff) override
285 {
286 if (!UpdateVictim())
287 return;
288
289 if (YipTimer <= diff)
290 {
292 YipTimer = 10000;
293 } else YipTimer -= diff;
294
296 }
297 };
298};
299
301{
302 if (Creature* pTito = me->SummonCreature(CREATURE_TITO, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30s))
303 {
305 ENSURE_AI(npc_tito::npc_titoAI, pTito->AI())->DorotheeGUID = me->GetGUID();
306 pTito->AI()->AttackStart(me->GetVictim());
307 SummonedTito = true;
308 TitoDied = false;
309 }
310}
311
313{
314public:
315 boss_strawman() : CreatureScript("boss_strawman") { }
316
317 CreatureAI* GetAI(Creature* creature) const override
318 {
319 return GetKarazhanAI<boss_strawmanAI>(creature);
320 }
321
323 {
324 boss_strawmanAI(Creature* creature) : ScriptedAI(creature)
325 {
326 Initialize();
327 instance = creature->GetInstanceScript();
328 }
329
331 {
332 AggroTimer = 13000;
333 BrainBashTimer = 5000;
334 BrainWipeTimer = 7000;
335 }
336
338
342
343 void Reset() override
344 {
345 Initialize();
346 }
347
348 void AttackStart(Unit* who) override
349 {
350 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
351 return;
352
354 }
355
356 void MoveInLineOfSight(Unit* who) override
357
358 {
359 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
360 return;
361
363 }
364
365 void JustEngagedWith(Unit* /*who*/) override
366 {
368 }
369
370 void JustReachedHome() override
371 {
372 me->DespawnOrUnsummon();
373 }
374
375 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
376 {
377 if ((spellInfo->SchoolMask == SPELL_SCHOOL_MASK_FIRE) && (!(rand32() % 10)))
378 {
379 /*
380 if (not direct damage(aoe, dot))
381 return;
382 */
383
384 DoCast(me, SPELL_BURNING_STRAW, true);
385 }
386 }
387
388 void JustDied(Unit* /*killer*/) override
389 {
391
392 SummonCroneIfReady(instance, me);
393 }
394
395 void KilledUnit(Unit* /*victim*/) override
396 {
398 }
399
400 void UpdateAI(uint32 diff) override
401 {
402 if (AggroTimer)
403 {
404 if (AggroTimer <= diff)
405 {
406 me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
407 AggroTimer = 0;
408 } else AggroTimer -= diff;
409 }
410
411 if (!UpdateVictim())
412 return;
413
414 if (BrainBashTimer <= diff)
415 {
416 DoCastVictim(SPELL_BRAIN_BASH);
417 BrainBashTimer = 15000;
418 } else BrainBashTimer -= diff;
419
420 if (BrainWipeTimer <= diff)
421 {
422 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
423 DoCast(target, SPELL_BRAIN_WIPE);
424 BrainWipeTimer = 20000;
425 } else BrainWipeTimer -= diff;
426
427 DoMeleeAttackIfReady();
428 }
429 };
430};
431
433{
434public:
435 boss_tinhead() : CreatureScript("boss_tinhead") { }
436
437 CreatureAI* GetAI(Creature* creature) const override
438 {
439 return GetKarazhanAI<boss_tinheadAI>(creature);
440 }
441
443 {
444 boss_tinheadAI(Creature* creature) : ScriptedAI(creature)
445 {
446 Initialize();
447 instance = creature->GetInstanceScript();
448 }
449
451 {
452 AggroTimer = 15000;
453 CleaveTimer = 5000;
454 RustTimer = 30000;
455
456 RustCount = 0;
457 }
458
460
464
466
467 void Reset() override
468 {
469 Initialize();
470 }
471
472 void JustEngagedWith(Unit* /*who*/) override
473 {
475 }
476
477 void JustReachedHome() override
478 {
479 me->DespawnOrUnsummon();
480 }
481
482 void AttackStart(Unit* who) override
483 {
484 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
485 return;
486
488 }
489
490 void MoveInLineOfSight(Unit* who) override
491
492 {
493 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
494 return;
495
497 }
498
499 void JustDied(Unit* /*killer*/) override
500 {
502
503 SummonCroneIfReady(instance, me);
504 }
505
506 void KilledUnit(Unit* /*victim*/) override
507 {
509 }
510
511 void UpdateAI(uint32 diff) override
512 {
513 if (AggroTimer)
514 {
515 if (AggroTimer <= diff)
516 {
517 me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
518 AggroTimer = 0;
519 } else AggroTimer -= diff;
520 }
521
522 if (!UpdateVictim())
523 return;
524
525 if (CleaveTimer <= diff)
526 {
527 DoCastVictim(SPELL_CLEAVE);
528 CleaveTimer = 5000;
529 } else CleaveTimer -= diff;
530
531 if (RustCount < 8)
532 {
533 if (RustTimer <= diff)
534 {
535 ++RustCount;
537 DoCast(me, SPELL_RUST);
538 RustTimer = 6000;
539 } else RustTimer -= diff;
540 }
541
542 DoMeleeAttackIfReady();
543 }
544 };
545};
546
548{
549public:
550 boss_roar() : CreatureScript("boss_roar") { }
551
552 CreatureAI* GetAI(Creature* creature) const override
553 {
554 return GetKarazhanAI<boss_roarAI>(creature);
555 }
556
557 struct boss_roarAI : public ScriptedAI
558 {
559 boss_roarAI(Creature* creature) : ScriptedAI(creature)
560 {
561 Initialize();
562 instance = creature->GetInstanceScript();
563 }
564
566 {
567 AggroTimer = 20000;
568 MangleTimer = 5000;
569 ShredTimer = 10000;
570 ScreamTimer = 15000;
571 }
572
574
579
580 void Reset() override
581 {
582 Initialize();
583 }
584
585 void MoveInLineOfSight(Unit* who) override
586
587 {
588 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
589 return;
590
592 }
593
594 void AttackStart(Unit* who) override
595 {
596 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
597 return;
598
600 }
601
602 void JustEngagedWith(Unit* /*who*/) override
603 {
605 }
606
607 void JustReachedHome() override
608 {
609 me->DespawnOrUnsummon();
610 }
611
612 void JustDied(Unit* /*killer*/) override
613 {
615
616 SummonCroneIfReady(instance, me);
617 }
618
619 void KilledUnit(Unit* /*victim*/) override
620 {
622 }
623
624 void UpdateAI(uint32 diff) override
625 {
626 if (AggroTimer)
627 {
628 if (AggroTimer <= diff)
629 {
630 me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
631 AggroTimer = 0;
632 } else AggroTimer -= diff;
633 }
634
635 if (!UpdateVictim())
636 return;
637
638 if (MangleTimer <= diff)
639 {
640 DoCastVictim(SPELL_MANGLE);
641 MangleTimer = urand(5000, 8000);
642 } else MangleTimer -= diff;
643
644 if (ShredTimer <= diff)
645 {
646 DoCastVictim(SPELL_SHRED);
647 ShredTimer = urand(10000, 15000);
648 } else ShredTimer -= diff;
649
650 if (ScreamTimer <= diff)
651 {
652 DoCastVictim(SPELL_FRIGHTENED_SCREAM);
653 ScreamTimer = urand(20000, 30000);
654 } else ScreamTimer -= diff;
655
656 DoMeleeAttackIfReady();
657 }
658 };
659};
660
662{
663public:
664 boss_crone() : CreatureScript("boss_crone") { }
665
666 CreatureAI* GetAI(Creature* creature) const override
667 {
668 return GetKarazhanAI<boss_croneAI>(creature);
669 }
670
671 struct boss_croneAI : public ScriptedAI
672 {
673 boss_croneAI(Creature* creature) : ScriptedAI(creature)
674 {
675 Initialize();
676 instance = creature->GetInstanceScript();
677 }
678
680 {
681 // Hello, developer from the future! It's me again!
682 // 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.
683 // Anyway, I digress.
684 // @todo This line below is obviously a hack. Duh. I'm just coming in here to hackfix the encounter to actually be completable.
685 // It needs a rewrite. Badly. Please, take good care of it.
686 me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
687 me->SetImmuneToPC(false);
688 CycloneTimer = 30000;
689 ChainLightningTimer = 10000;
690 }
691
693
696
697 void Reset() override
698 {
699 Initialize();
700 }
701
702 void JustReachedHome() override
703 {
704 me->DespawnOrUnsummon();
705 }
706
707 void KilledUnit(Unit* /*victim*/) override
708 {
710 }
711
712 void JustEngagedWith(Unit* /*who*/) override
713 {
715 }
716
717 void JustDied(Unit* /*killer*/) override
718 {
721 }
722
723 void UpdateAI(uint32 diff) override
724 {
725 if (!UpdateVictim())
726 return;
727
728 if (CycloneTimer <= diff)
729 {
730 if (Creature* Cyclone = DoSpawnCreature(CREATURE_CYCLONE, float(urand(0, 9)), float(urand(0, 9)), 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15s))
731 Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_VISUAL, true);
732 CycloneTimer = 30000;
733 } else CycloneTimer -= diff;
734
735 if (ChainLightningTimer <= diff)
736 {
737 DoCastVictim(SPELL_CHAIN_LIGHTNING);
738 ChainLightningTimer = 15000;
739 } else ChainLightningTimer -= diff;
740
741 DoMeleeAttackIfReady();
742 }
743 };
744};
745
747{
748public:
749 npc_cyclone() : CreatureScript("npc_cyclone") { }
750
751 CreatureAI* GetAI(Creature* creature) const override
752 {
753 return GetKarazhanAI<npc_cycloneAI>(creature);
754 }
755
756 struct npc_cycloneAI : public ScriptedAI
757 {
758 npc_cycloneAI(Creature* creature) : ScriptedAI(creature)
759 {
760 Initialize();
761 }
762
764 {
765 MoveTimer = 1000;
766 }
767
769
770 void Reset() override
771 {
772 Initialize();
773 }
774
775 void JustEngagedWith(Unit* /*who*/) override { }
776
777 void MoveInLineOfSight(Unit* /*who*/) override
778
779 {
780 }
781
782 void UpdateAI(uint32 diff) override
783 {
784 if (!me->HasAura(SPELL_KNOCKBACK))
785 DoCast(me, SPELL_KNOCKBACK, true);
786
787 if (MoveTimer <= diff)
788 {
789 Position pos = me->GetRandomNearPosition(10);
790 me->GetMotionMaster()->MovePoint(0, pos);
791 MoveTimer = urand(5000, 8000);
792 } else MoveTimer -= diff;
793 }
794 };
795};
796
797/**************************************/
798/**** Opera Red Riding Hood Event* ***/
799/************************************/
814
816{
817 public:
818 npc_grandmother() : CreatureScript("npc_grandmother") { }
819
821 {
822 npc_grandmotherAI(Creature* creature) : ScriptedAI(creature) { }
823
824 bool OnGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
825 {
826 if (menuId == OPTION_WHAT_PHAT_LEWTS_YOU_HAVE && gossipListId == 0)
827 {
828 CloseGossipMenuFor(player);
829
830 if (Creature* pBigBadWolf = me->SummonCreature(CREATURE_BIG_BAD_WOLF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 2h))
831 pBigBadWolf->AI()->AttackStart(player);
832
833 me->DespawnOrUnsummon();
834 }
835 return false;
836 }
837 };
838
839 CreatureAI* GetAI(Creature* creature) const override
840 {
841 return GetKarazhanAI<npc_grandmotherAI>(creature);
842 }
843};
844
846{
847public:
848 boss_bigbadwolf() : CreatureScript("boss_bigbadwolf") { }
849
850 CreatureAI* GetAI(Creature* creature) const override
851 {
852 return GetKarazhanAI<boss_bigbadwolfAI>(creature);
853 }
854
856 {
857 boss_bigbadwolfAI(Creature* creature) : ScriptedAI(creature)
858 {
859 Initialize();
860 instance = creature->GetInstanceScript();
861 }
862
864 {
865 ChaseTimer = 30000;
866 FearTimer = urand(25000, 35000);
867 SwipeTimer = 5000;
868
869 HoodGUID.Clear();
870 TempThreat = 0;
871
872 IsChasing = false;
873 }
874
876
880
883
885
886 void Reset() override
887 {
888 Initialize();
889 }
890
891 void JustEngagedWith(Unit* /*who*/) override
892 {
894 }
895
896 void KilledUnit(Unit* /*victim*/) override
897 {
899 }
900
901 void JustReachedHome() override
902 {
903 me->DespawnOrUnsummon();
904 }
905
906 void JustDied(Unit* /*killer*/) override
907 {
908 DoPlaySoundToSet(me, SOUND_WOLF_DEATH);
910 }
911
912 void UpdateAI(uint32 diff) override
913 {
914 if (!UpdateVictim())
915 return;
916
917 DoMeleeAttackIfReady();
918
919 if (ChaseTimer <= diff)
920 {
921 if (!IsChasing)
922 {
923 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
924 {
926 DoCast(target, SPELL_LITTLE_RED_RIDING_HOOD, true);
927 TempThreat = GetThreat(target);
928 if (TempThreat)
929 ModifyThreatByPercent(target, -100);
930 HoodGUID = target->GetGUID();
931 AddThreat(target, 1000000.0f);
932 ChaseTimer = 20000;
933 IsChasing = true;
934 }
935 }
936 else
937 {
938 IsChasing = false;
939
940 if (Unit* target = ObjectAccessor::GetUnit(*me, HoodGUID))
941 {
942 HoodGUID.Clear();
943 if (GetThreat(target))
944 ModifyThreatByPercent(target, -100);
945 AddThreat(target, TempThreat);
946 TempThreat = 0;
947 }
948
949 ChaseTimer = 40000;
950 }
951 } else ChaseTimer -= diff;
952
953 if (IsChasing)
954 return;
955
956 if (FearTimer <= diff)
957 {
958 DoCastVictim(SPELL_TERRIFYING_HOWL);
959 FearTimer = urand(25000, 35000);
960 } else FearTimer -= diff;
961
962 if (SwipeTimer <= diff)
963 {
964 DoCastVictim(SPELL_WIDE_SWIPE);
965 SwipeTimer = urand(25000, 30000);
966 } else SwipeTimer -= diff;
967 }
968 };
969};
970
971/**********************************************/
972/******** Opera Romeo and Juliet Event* ******/
973/********************************************/
974
1009
1016
1017void PretendToDie(Creature* creature)
1018{
1019 creature->InterruptNonMeleeSpells(true);
1020 creature->RemoveAllAuras();
1021 creature->SetHealth(0);
1023 creature->GetMotionMaster()->Clear();
1024 creature->GetMotionMaster()->MoveIdle();
1026}
1027
1028void Resurrect(Creature* target)
1029{
1031 target->SetFullHealth();
1033 target->CastSpell(target, SPELL_RES_VISUAL, true);
1034 if (target->GetVictim())
1035 {
1036 target->GetMotionMaster()->MoveChase(target->GetVictim());
1037 target->AI()->AttackStart(target->GetVictim());
1038 }
1039 else
1040 target->GetMotionMaster()->Initialize();
1041}
1042
1044{
1045public:
1046 boss_julianne() : CreatureScript("boss_julianne") { }
1047
1048 CreatureAI* GetAI(Creature* creature) const override
1049 {
1050 return GetKarazhanAI<boss_julianneAI>(creature);
1051 }
1052
1054 {
1055 boss_julianneAI(Creature* creature) : ScriptedAI(creature)
1056 {
1057 Initialize();
1058 instance = creature->GetInstanceScript();
1059 EntryYellTimer = 1000;
1060 AggroYellTimer = 10000;
1061 IsFakingDeath = false;
1062 ResurrectTimer = 0;
1063 }
1064
1066 {
1067 RomuloGUID.Clear();
1069
1070 BlindingPassionTimer = 30000;
1071 DevotionTimer = 15000;
1072 EternalAffectionTimer = 25000;
1073 PowerfulAttractionTimer = 5000;
1074 SummonRomuloTimer = 10000;
1075 DrinkPoisonTimer = 0;
1076 ResurrectSelfTimer = 0;
1077
1078 SummonedRomulo = false;
1079 RomuloDead = false;
1080 }
1081
1083
1086
1088
1090
1099
1103
1104 void Reset() override
1105 {
1106 Initialize();
1107 if (IsFakingDeath)
1108 {
1109 Resurrect(me);
1110 IsFakingDeath = false;
1111 }
1112 }
1113
1114 void JustEngagedWith(Unit* /*who*/) override { }
1115
1116 void AttackStart(Unit* who) override
1117 {
1118 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
1119 return;
1120
1122 }
1123
1124 void MoveInLineOfSight(Unit* who) override
1125
1126 {
1127 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
1128 return;
1129
1131 }
1132
1133 void JustReachedHome() override
1134 {
1135 me->DespawnOrUnsummon();
1136 }
1137
1138 void SpellHit(WorldObject* /*caster*/, SpellInfo const* spellInfo) override
1139 {
1140 if (spellInfo->Id == SPELL_DRINK_POISON)
1141 {
1143 DrinkPoisonTimer = 2500;
1144 }
1145 }
1146
1147 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override;
1148
1149 void JustDied(Unit* /*killer*/) override
1150 {
1153 }
1154
1155 void KilledUnit(Unit* /*victim*/) override
1156 {
1158 }
1159
1160 void UpdateAI(uint32 diff) override;
1161 };
1162};
1163
1165{
1166public:
1167 boss_romulo() : CreatureScript("boss_romulo") { }
1168
1169 CreatureAI* GetAI(Creature* creature) const override
1170 {
1171 return GetKarazhanAI<boss_romuloAI>(creature);
1172 }
1173
1175 {
1176 boss_romuloAI(Creature* creature) : ScriptedAI(creature)
1177 {
1178 Initialize();
1179 instance = creature->GetInstanceScript();
1180 EntryYellTimer = 8000;
1181 AggroYellTimer = 15000;
1182 }
1183
1185 {
1186 JulianneGUID.Clear();
1188
1189 BackwardLungeTimer = 15000;
1190 DaringTimer = 20000;
1191 DeadlySwatheTimer = 25000;
1192 PoisonThrustTimer = 10000;
1193 ResurrectTimer = 10000;
1194
1195 IsFakingDeath = false;
1196 JulianneDead = false;
1197 }
1198
1200
1203
1211
1214
1215 void Reset() override
1216 {
1217 Initialize();
1218 }
1219
1220 void JustReachedHome() override
1221 {
1222 me->DespawnOrUnsummon();
1223 }
1224
1225 void DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/) override
1226 {
1227 if (damage < me->GetHealth())
1228 return;
1229
1230 //anything below only used if incoming damage will kill
1231
1232 if (Phase == PHASE_ROMULO)
1233 {
1235 PretendToDie(me);
1236 IsFakingDeath = true;
1237 Phase = PHASE_BOTH;
1238
1239 if (Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID)))
1240 {
1241 ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->RomuloDead = true;
1242 ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->ResurrectSelfTimer = 10000;
1243 }
1244
1245 damage = 0;
1246 return;
1247 }
1248
1249 if (Phase == PHASE_BOTH)
1250 {
1251 if (JulianneDead)
1252 {
1253 if (Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID)))
1254 {
1255 Julianne->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
1256 Julianne->GetMotionMaster()->Clear();
1257 Julianne->setDeathState(JUST_DIED);
1258 Julianne->CombatStop(true);
1259 Julianne->ReplaceAllDynamicFlags(UNIT_DYNFLAG_LOOTABLE);
1260 }
1261 return;
1262 }
1263
1264 if (Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID)))
1265 {
1266 PretendToDie(me);
1267 IsFakingDeath = true;
1268 ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->ResurrectTimer = 10000;
1269 ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->RomuloDead = true;
1270 damage = 0;
1271 return;
1272 }
1273 }
1274
1275 TC_LOG_ERROR("scripts", "boss_romuloAI: DamageTaken reach end of code, that should not happen.");
1276 }
1277
1278 void JustEngagedWith(Unit* /*who*/) override
1279 {
1281 if (!JulianneGUID.IsEmpty())
1282 {
1283 Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID));
1284 if (Julianne && Julianne->GetVictim())
1285 {
1286 AddThreat(Julianne->GetVictim(), 1.0f);
1287 AttackStart(Julianne->GetVictim());
1288 }
1289 }
1290 }
1291
1292 void MoveInLineOfSight(Unit* who) override
1293
1294 {
1295 if (me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
1296 return;
1297
1299 }
1300
1301 void JustDied(Unit* /*killer*/) override
1302 {
1305 }
1306
1307 void KilledUnit(Unit* /*victim*/) override
1308 {
1310 }
1311
1312 void UpdateAI(uint32 diff) override
1313 {
1314 if (!UpdateVictim() || IsFakingDeath)
1315 return;
1316
1317 if (JulianneDead)
1318 {
1319 if (ResurrectTimer <= diff)
1320 {
1321 Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID));
1322 if (Julianne && ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->IsFakingDeath)
1323 {
1325 Resurrect(Julianne);
1326 ENSURE_AI(boss_julianne::boss_julianneAI, Julianne->AI())->IsFakingDeath = false;
1327 JulianneDead = false;
1328 ResurrectTimer = 10000;
1329 }
1330 } else ResurrectTimer -= diff;
1331 }
1332
1333 if (BackwardLungeTimer <= diff)
1334 {
1335 Unit* target = SelectTarget(SelectTargetMethod::Random, 1, 100, true);
1336 if (target && !me->HasInArc(float(M_PI), target))
1337 {
1338 DoCast(target, SPELL_BACKWARD_LUNGE);
1339 BackwardLungeTimer = urand(15000, 30000);
1340 }
1341 } else BackwardLungeTimer -= diff;
1342
1343 if (DaringTimer <= diff)
1344 {
1345 DoCast(me, SPELL_DARING);
1346 DaringTimer = urand(20000, 40000);
1347 } else DaringTimer -= diff;
1348
1349 if (DeadlySwatheTimer <= diff)
1350 {
1351 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
1352 DoCast(target, SPELL_DEADLY_SWATHE);
1353 DeadlySwatheTimer = urand(15000, 25000);
1354 } else DeadlySwatheTimer -= diff;
1355
1356 if (PoisonThrustTimer <= diff)
1357 {
1358 DoCastVictim(SPELL_POISON_THRUST);
1359 PoisonThrustTimer = urand(10000, 20000);
1360 } else PoisonThrustTimer -= diff;
1361
1362 DoMeleeAttackIfReady();
1363 }
1364 };
1365};
1366
1368{
1369 if (EntryYellTimer)
1370 {
1371 if (EntryYellTimer <= diff)
1372 {
1374 EntryYellTimer = 0;
1375 } else EntryYellTimer -= diff;
1376 }
1377
1378 if (AggroYellTimer)
1379 {
1380 if (AggroYellTimer <= diff)
1381 {
1383 me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
1384 me->SetFaction(FACTION_MONSTER_2);
1385 AggroYellTimer = 0;
1386 } else AggroYellTimer -= diff;
1387 }
1388
1389 if (DrinkPoisonTimer)
1390 {
1391 //will do this 2secs after spell hit. this is time to display visual as expected
1392 if (DrinkPoisonTimer <= diff)
1393 {
1394 PretendToDie(me);
1396 SummonRomuloTimer = 10000;
1397 DrinkPoisonTimer = 0;
1398 } else DrinkPoisonTimer -= diff;
1399 }
1400
1401 if (Phase == PHASE_ROMULO && !SummonedRomulo)
1402 {
1403 if (SummonRomuloTimer <= diff)
1404 {
1405 if (Creature* pRomulo = me->SummonCreature(CREATURE_ROMULO, ROMULO_X, ROMULO_Y, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 2h))
1406 {
1407 RomuloGUID = pRomulo->GetGUID();
1408 ENSURE_AI(boss_romulo::boss_romuloAI, pRomulo->AI())->JulianneGUID = me->GetGUID();
1409 ENSURE_AI(boss_romulo::boss_romuloAI, pRomulo->AI())->Phase = PHASE_ROMULO;
1410 DoZoneInCombat(pRomulo);
1411
1412 pRomulo->SetFaction(FACTION_MONSTER_2);
1413 }
1414 SummonedRomulo = true;
1415 } else SummonRomuloTimer -= diff;
1416 }
1417
1418 if (ResurrectSelfTimer)
1419 {
1420 if (ResurrectSelfTimer <= diff)
1421 {
1422 Resurrect(me);
1423 Phase = PHASE_BOTH;
1424 IsFakingDeath = false;
1425
1426 if (me->GetVictim())
1427 AttackStart(me->GetVictim());
1428
1429 ResurrectSelfTimer = 0;
1430 ResurrectTimer = 1000;
1431 } else ResurrectSelfTimer -= diff;
1432 }
1433
1434 if (!UpdateVictim() || IsFakingDeath)
1435 return;
1436
1437 if (RomuloDead)
1438 {
1439 if (ResurrectTimer <= diff)
1440 {
1441 Creature* Romulo = (ObjectAccessor::GetCreature((*me), RomuloGUID));
1442 if (Romulo && ENSURE_AI(boss_romulo::boss_romuloAI, Romulo->AI())->IsFakingDeath)
1443 {
1445 Resurrect(Romulo);
1446 ENSURE_AI(boss_romulo::boss_romuloAI, Romulo->AI())->IsFakingDeath = false;
1447 RomuloDead = false;
1448 ResurrectTimer = 10000;
1449 }
1450 } else ResurrectTimer -= diff;
1451 }
1452
1453 if (BlindingPassionTimer <= diff)
1454 {
1455 if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100, true))
1456 DoCast(target, SPELL_BLINDING_PASSION);
1457 BlindingPassionTimer = urand(30000, 45000);
1458 } else BlindingPassionTimer -= diff;
1459
1460 if (DevotionTimer <= diff)
1461 {
1462 DoCast(me, SPELL_DEVOTION);
1463 DevotionTimer = urand(15000, 45000);
1464 } else DevotionTimer -= diff;
1465
1466 if (PowerfulAttractionTimer <= diff)
1467 {
1468 DoCast(SelectTarget(SelectTargetMethod::Random, 0), SPELL_POWERFUL_ATTRACTION);
1469 PowerfulAttractionTimer = urand(5000, 30000);
1470 } else PowerfulAttractionTimer -= diff;
1471
1472 if (EternalAffectionTimer <= diff)
1473 {
1474 if (urand(0, 1) && SummonedRomulo)
1475 {
1476 Creature* Romulo = (ObjectAccessor::GetCreature((*me), RomuloGUID));
1477 if (Romulo && Romulo->IsAlive() && !RomuloDead)
1478 DoCast(Romulo, SPELL_ETERNAL_AFFECTION);
1479 } else DoCast(me, SPELL_ETERNAL_AFFECTION);
1480
1481 EternalAffectionTimer = urand(45000, 60000);
1482 } else EternalAffectionTimer -= diff;
1483
1484 DoMeleeAttackIfReady();
1485}
1486
1487void boss_julianne::boss_julianneAI::DamageTaken(Unit* /*done_by*/, uint32& damage, DamageEffectType /*damageType*/, SpellInfo const* /*spellInfo = nullptr*/)
1488{
1489 if (damage < me->GetHealth())
1490 return;
1491
1492 //anything below only used if incoming damage will kill
1493
1494 if (Phase == PHASE_JULIANNE)
1495 {
1496 damage = 0;
1497
1498 //this means already drinking, so return
1499 if (IsFakingDeath)
1500 return;
1501
1502 me->InterruptNonMeleeSpells(true);
1503 DoCast(me, SPELL_DRINK_POISON);
1504
1505 IsFakingDeath = true;
1506 //IS THIS USEFULL? Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID));
1507 return;
1508 }
1509
1510 if (Phase == PHASE_ROMULO)
1511 {
1512 TC_LOG_ERROR("scripts", "boss_julianneAI: cannot take damage in PHASE_ROMULO, why was i here?");
1513 damage = 0;
1514 return;
1515 }
1516
1517 if (Phase == PHASE_BOTH)
1518 {
1519 //if this is true then we have to kill romulo too
1520 if (RomuloDead)
1521 {
1522 if (Creature* Romulo = (ObjectAccessor::GetCreature((*me), RomuloGUID)))
1523 {
1524 Romulo->RemoveUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
1525 Romulo->GetMotionMaster()->Clear();
1526 Romulo->setDeathState(JUST_DIED);
1527 Romulo->CombatStop(true);
1528 Romulo->ReplaceAllDynamicFlags(UNIT_DYNFLAG_LOOTABLE);
1529 }
1530
1531 return;
1532 }
1533
1534 //if not already returned, then romulo is alive and we can pretend die
1535 if (Creature* Romulo = (ObjectAccessor::GetCreature((*me), RomuloGUID)))
1536 {
1537 PretendToDie(me);
1538 IsFakingDeath = true;
1539 ENSURE_AI(boss_romulo::boss_romuloAI, Romulo->AI())->ResurrectTimer = 10000;
1540 ENSURE_AI(boss_romulo::boss_romuloAI, Romulo->AI())->JulianneDead = true;
1541 damage = 0;
1542 return;
1543 }
1544 }
1545 TC_LOG_ERROR("scripts", "boss_julianneAI: DamageTaken reach end of code, that should not happen.");
1546}
1547
1549{
1550 new boss_dorothee();
1551 new boss_strawman();
1552 new boss_tinhead();
1553 new boss_roar();
1554 new boss_crone();
1555 new npc_tito();
1556 new npc_cyclone();
1557 new npc_grandmother();
1558 new boss_bigbadwolf();
1559 new boss_julianne();
1560 new boss_romulo();
1561}
#define M_PI
Definition Common.h:72
uint8_t uint8
Definition Define.h:135
uint32_t uint32
Definition Define.h:133
@ DONE
@ SPECIAL
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
@ TEMPSUMMON_TIMED_DESPAWN
@ TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
@ TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
Spells
Definition PlayerAI.cpp:32
@ SPELL_MANGLE
Definition PlayerAI.cpp:370
@ SPELL_CHAIN_LIGHTNING
Definition PlayerAI.cpp:264
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:28
@ UNIT_STAND_STATE_DEAD
Definition UnitDefines.h:41
@ UNIT_STAND_STATE_STAND
Definition UnitDefines.h:34
@ UNIT_FLAG_NON_ATTACKABLE
@ UNIT_FLAG_UNINTERACTIBLE
@ JUST_DIED
Definition Unit.h:212
DamageEffectType
Definition Unit.h:352
Creatures
@ SPELL_CLEAVE
@ 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
@ 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 *)
bool UpdateVictim()
Creature *const me
Definition CreatureAI.h:82
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
CreatureAI * AI() const
Definition Creature.h:154
virtual bool SetBossState(uint32 id, EncounterState state)
void MoveChase(Unit *target, Optional< ChaseRange > dist={}, Optional< ChaseAngle > angle={})
bool IsEmpty() const
Definition ObjectGuid.h:172
void Clear()
Definition ObjectGuid.h:150
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
uint32 Id
Definition SpellInfo.h:289
uint32 SchoolMask
Definition SpellInfo.h:361
void DoMeleeAttackIfReady()
Definition UnitAI.cpp:54
SpellCastResult DoCastVictim(uint32 spellId, CastSpellExtraArgs const &args={})
Definition UnitAI.cpp:166
Unit * SelectTarget(SelectTargetMethod targetType, uint32 offset=0, float dist=0.0f, bool playerOnly=false, bool withTank=true, int32 aura=0)
Definition UnitAI.cpp:96
virtual void AttackStart(Unit *)
Definition UnitAI.cpp:30
SpellCastResult DoCast(uint32 spellId)
Definition UnitAI.cpp:106
Definition Unit.h:769
void SetFullHealth()
Definition Unit.h:927
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid=0, bool withInstant=true)
Definition Unit.cpp:3093
MotionMaster * GetMotionMaster()
Definition Unit.h:1667
bool HasUnitFlag(UnitFlags flags) const
Definition Unit.h:953
bool IsAlive() const
Definition Unit.h:1234
void SetHealth(uint32 val)
Definition Unit.cpp:9361
Unit * GetVictim() const
Definition Unit.h:859
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10363
void RemoveAllAuras()
Definition Unit.cpp:4157
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:954
void RemoveUnitFlag(UnitFlags flags)
Definition Unit.h:955
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1087
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
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
virtual uint32 GetData(uint32) const
Definition ZoneScript.h:55
virtual void SetData(uint32, uint32)
Definition ZoneScript.h:56
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)
float GetPositionZ() const
Definition Position.h:81
bool HasInArc(float arcangle, Position const *pos, float border=2.0f) const
Definition Position.cpp:120
void AttackStart(Unit *) override
void UpdateAI(uint32 diff) override
void JustEngagedWith(Unit *) override
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
void MoveInLineOfSight(Unit *who) override
void JustDied(Unit *) override
void JustEngagedWith(Unit *) override
void UpdateAI(uint32 diff) override
void AttackStart(Unit *who) override
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
InstanceScript * instance
void JustReachedHome() override
boss_roarAI(Creature *creature)
void UpdateAI(uint32 diff) override
void KilledUnit(Unit *) override
void AttackStart(Unit *who) override
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 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
void MoveInLineOfSight(Unit *who) override
void MoveInLineOfSight(Unit *who) override
void AttackStart(Unit *who) override
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)
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